diff --git a/Android.bp b/Android.bp index d0bee2890fb767f955952dbb6a16e6e42ca80fd2..d5e04f9f4e2d84b0eccb7307b0c68e2689f170a4 100644 --- a/Android.bp +++ b/Android.bp @@ -319,6 +319,10 @@ java_library { "core/java/android/service/chooser/IChooserTargetResult.aidl", "core/java/android/service/resolver/IResolverRankerService.aidl", "core/java/android/service/resolver/IResolverRankerResult.aidl", + "core/java/android/service/textclassifier/ITextClassificationCallback.aidl", + "core/java/android/service/textclassifier/ITextClassifierService.aidl", + "core/java/android/service/textclassifier/ITextLinksCallback.aidl", + "core/java/android/service/textclassifier/ITextSelectionCallback.aidl", "core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl", "core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl", "core/java/android/view/accessibility/IAccessibilityManager.aidl", @@ -483,16 +487,19 @@ java_library { "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl", "telephony/java/android/telephony/data/IDataService.aidl", "telephony/java/android/telephony/data/IDataServiceCallback.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl", - "telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl", - "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl", + "telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl", + "telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl", + "telephony/java/android/telephony/ims/aidl/IImsConfig.aidl", + "telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl", + "telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl", + "telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl", + "telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl", + "telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl", + "telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl", + "telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl", + "telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl", + "telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl", + "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl", "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl", "telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl", "telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl", @@ -510,13 +517,10 @@ java_library { "telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl", "telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl", "telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl", - "telephony/java/com/android/ims/internal/IImsRegistration.aidl", - "telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl", "telephony/java/com/android/ims/internal/IImsRcsFeature.aidl", "telephony/java/com/android/ims/internal/IImsService.aidl", "telephony/java/com/android/ims/internal/IImsServiceController.aidl", "telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl", - "telephony/java/com/android/ims/internal/IImsSmsListener.aidl", "telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl", "telephony/java/com/android/ims/internal/IImsUt.aidl", "telephony/java/com/android/ims/internal/IImsUtListener.aidl", @@ -643,8 +647,10 @@ java_library { ], }, - // See comment on framework-oahl-backward-compatibility module below exclude_srcs: [ + // See comment on framework-atb-backward-compatibility module below + "core/java/android/content/pm/AndroidTestBaseUpdater.java", + // See comment on framework-oahl-backward-compatibility module below "core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java", ], @@ -670,6 +676,7 @@ java_library { "android.hardware.vibrator-V1.1-java-constants", "android.hardware.wifi-V1.0-java-constants", "android.hardware.radio-V1.0-java", + "android.hardware.usb.gadget-V1.0-java", ], // Loaded with System.loadLibrary by android.view.textclassifier @@ -697,6 +704,18 @@ java_library { ], } +// A temporary build target that is conditionally included on the bootclasspath if +// android.test.base library has been removed and which provides support for +// maintaining backwards compatibility for APKs that target pre-P and depend on +// android.test.base classes. This is used iff REMOVE_ATB_FROM_BCP=true is +// specified on the build command line. +java_library { + name: "framework-atb-backward-compatibility", + srcs: [ + "core/java/android/content/pm/AndroidTestBaseUpdater.java", + ], +} + genrule { name: "framework-statslog-gen", tools: ["stats-log-api-gen"], diff --git a/Android.mk b/Android.mk index 35b5f92be3107180849d52bfa30d8b46f4ee2244..a78a01a1600f55e4e94927dbf9815594b73d8ea7 100644 --- a/Android.mk +++ b/Android.mk @@ -821,39 +821,41 @@ LOCAL_PROTOC_FLAGS := \ LOCAL_SRC_FILES := \ $(call all-proto-files-under, core/proto) \ $(call all-proto-files-under, libs/incident/proto/android/os) +# Protos have lots of MissingOverride and similar. +LOCAL_ERROR_PRONE_FLAGS := -XepDisableAllChecks include $(BUILD_STATIC_JAVA_LIBRARY) # ==== hiddenapi lists ======================================= -# Copy blacklist and dark greylist over into the build folder. +# Copy blacklist and light greylist over into the build folder. # This is for ART buildbots which need to mock these lists and have alternative # rules for building them. Other rules in the build system should depend on the # files in the build folder. $(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))) -$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\ - $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))) - -# Generate light greylist as private API minus (blacklist plus dark greylist). - -$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) -$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) -$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): DARK_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) -$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \ - $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) \ - $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) - if [ ! -z "`comm -12 <(sort $(BLACKLIST)) <(sort $(DARK_GREYLIST))`" ]; then \ - echo "There should be no overlap between $(BLACKLIST) and $(DARK_GREYLIST)" 1>&2; \ +$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-light-greylist.txt,\ + $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))) + +# Generate dark greylist as private API minus (blacklist plus light greylist). + +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \ + $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) \ + $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) + if [ ! -z "`comm -12 <(sort $(BLACKLIST)) <(sort $(LIGHT_GREYLIST))`" ]; then \ + echo "There should be no overlap between $(BLACKLIST) and $(LIGHT_GREYLIST)" 1>&2; \ exit 1; \ elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST))`" ]; then \ echo "$(BLACKLIST) must be a subset of $(PRIVATE_API)" 1>&2; \ exit 2; \ - elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST))`" ]; then \ - echo "$(DARK_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \ + elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST))`" ]; then \ + echo "$(LIGHT_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \ exit 3; \ fi - comm -23 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST) $(DARK_GREYLIST)) > $@ + comm -23 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST) $(LIGHT_GREYLIST)) > $@ # Include subdirectory makefiles # ============================================================ diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java index bab2a859698cb59f77c82b39b125b6e1e6eb8277..231aaf2ca074910077c537e634322594a47a8b7f 100644 --- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java @@ -232,7 +232,7 @@ public class StaticLayoutPerfTest { while (state.keepRunning()) { state.pauseTiming(); final MeasuredText text = new MeasuredText.Builder( - mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT) + mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT) .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) .build(); diff --git a/api/current.txt b/api/current.txt index 800412bd2e1279bd85d27bf636a24e0011fbe23f..3c3cfccaebef34593464986d318809a3cbab6220 100644 --- a/api/current.txt +++ b/api/current.txt @@ -902,6 +902,7 @@ package android { field public static final int maxLength = 16843104; // 0x1010160 field public static final int maxLevel = 16843186; // 0x10101b2 field public static final int maxLines = 16843091; // 0x1010153 + field public static final int maxLongVersionCode = 16844163; // 0x1010583 field public static final int maxRecents = 16843846; // 0x1010446 field public static final int maxRows = 16843059; // 0x1010133 field public static final int maxSdkVersion = 16843377; // 0x1010271 @@ -969,7 +970,9 @@ package android { field public static final int orderingFromXml = 16843239; // 0x10101e7 field public static final int orientation = 16842948; // 0x10100c4 field public static final int outAnimation = 16843128; // 0x1010178 + field public static final int outlineAmbientShadowColor = 16844162; // 0x1010582 field public static final int outlineProvider = 16843960; // 0x10104b8 + field public static final int outlineSpotShadowColor = 16844161; // 0x1010581 field public static final int overScrollFooter = 16843459; // 0x10102c3 field public static final int overScrollHeader = 16843458; // 0x10102c2 field public static final int overScrollMode = 16843457; // 0x10102c1 @@ -5708,7 +5711,8 @@ package android.app { field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED"; field public static final java.lang.String EXTRA_BLOCKED_STATE = "android.app.extra.BLOCKED_STATE"; - field public static final java.lang.String EXTRA_BLOCK_STATE_CHANGED_ID = "android.app.extra.BLOCK_STATE_CHANGED_ID"; + field public static final java.lang.String EXTRA_NOTIFICATION_CHANNEL_GROUP_ID = "android.app.extra.NOTIFICATION_CHANNEL_GROUP_ID"; + field public static final java.lang.String EXTRA_NOTIFICATION_CHANNEL_ID = "android.app.extra.NOTIFICATION_CHANNEL_ID"; field public static final int IMPORTANCE_DEFAULT = 3; // 0x3 field public static final int IMPORTANCE_HIGH = 4; // 0x4 field public static final int IMPORTANCE_LOW = 2; // 0x2 @@ -6085,16 +6089,16 @@ package android.app { method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow(); - method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); + method public android.accessibilityservice.AccessibilityServiceInfo getServiceInfo(); method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats(); method public android.view.WindowContentFrameStats getWindowContentFrameStats(int); method public java.util.List getWindows(); method public boolean injectInputEvent(android.view.InputEvent, boolean); - method public final boolean performGlobalAction(int); + method public boolean performGlobalAction(int); method public void setOnAccessibilityEventListener(android.app.UiAutomation.OnAccessibilityEventListener); method public boolean setRotation(int); method public void setRunAsMonkey(boolean); - method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo); + method public void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo); method public android.graphics.Bitmap takeScreenshot(); method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException; field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1 @@ -6498,7 +6502,7 @@ package android.app.admin { method public boolean isUsingUnifiedPassword(android.content.ComponentName); method public void lockNow(); method public void lockNow(int); - method public boolean logoutUser(android.content.ComponentName); + method public int logoutUser(android.content.ComponentName); method public void reboot(android.content.ComponentName); method public void removeActiveAdmin(android.content.ComponentName); method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); @@ -6583,8 +6587,8 @@ package android.app.admin { method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle); method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean); method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap); - method public boolean startUserInBackground(android.content.ComponentName, android.os.UserHandle); - method public boolean stopUser(android.content.ComponentName, android.os.UserHandle); + method public int startUserInBackground(android.content.ComponentName, android.os.UserHandle); + method public int stopUser(android.content.ComponentName, android.os.UserHandle); method public boolean switchUser(android.content.ComponentName, android.os.UserHandle); method public void transferOwnership(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle); method public void uninstallAllUserCaCerts(android.content.ComponentName); @@ -6698,6 +6702,11 @@ package android.app.admin { field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 + field public static final int USER_OPERATION_ERROR_CURRENT_USER = 4; // 0x4 + field public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2; // 0x2 + field public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; // 0x3 + field public static final int USER_OPERATION_ERROR_UNKNOWN = 1; // 0x1 + field public static final int USER_OPERATION_SUCCESS = 0; // 0x0 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } @@ -7161,7 +7170,8 @@ package android.app.slice { method public android.net.Uri getUri(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; - field public static final java.lang.String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE"; + field public static final java.lang.String EXTRA_RANGE_VALUE = "android.app.slice.extra.RANGE_VALUE"; + field public static final deprecated java.lang.String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE"; field public static final java.lang.String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE"; field public static final java.lang.String HINT_ACTIONS = "actions"; field public static final java.lang.String HINT_CALLER_NEEDED = "caller_needed"; @@ -7181,7 +7191,8 @@ package android.app.slice { field public static final java.lang.String SUBTYPE_MAX = "max"; field public static final java.lang.String SUBTYPE_MESSAGE = "message"; field public static final java.lang.String SUBTYPE_PRIORITY = "priority"; - field public static final java.lang.String SUBTYPE_SLIDER = "slider"; + field public static final java.lang.String SUBTYPE_RANGE = "range"; + field public static final deprecated java.lang.String SUBTYPE_SLIDER = "slider"; field public static final java.lang.String SUBTYPE_SOURCE = "source"; field public static final java.lang.String SUBTYPE_TOGGLE = "toggle"; field public static final java.lang.String SUBTYPE_VALUE = "value"; @@ -7243,6 +7254,7 @@ package android.app.slice { method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List); method public java.util.List getPinnedSpecs(android.net.Uri); method public java.util.Collection getSliceDescendants(android.net.Uri); + method public android.net.Uri mapIntentToUri(android.content.Intent); method public void pinSlice(android.net.Uri, java.util.List); method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List); method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List, java.util.concurrent.Executor); @@ -11622,15 +11634,9 @@ package android.content.res { } public final class AssetManager.AssetInputStream extends java.io.InputStream { - method public final int available() throws java.io.IOException; - method public final void close() throws java.io.IOException; - method public final void mark(int); - method public final boolean markSupported(); - method public final int read() throws java.io.IOException; - method public final int read(byte[]) throws java.io.IOException; - method public final int read(byte[], int, int) throws java.io.IOException; - method public final void reset() throws java.io.IOException; - method public final long skip(long) throws java.io.IOException; + method public void mark(int); + method public int read() throws java.io.IOException; + method public void reset() throws java.io.IOException; } public class ColorStateList implements android.os.Parcelable { @@ -12392,7 +12398,7 @@ package android.database.sqlite { method public java.util.List> getAttachedDbs(); method public long getMaximumSize(); method public long getPageSize(); - method public final java.lang.String getPath(); + method public java.lang.String getPath(); method public deprecated java.util.Map getSyncedTables(); method public int getVersion(); method public boolean inTransaction(); @@ -13044,34 +13050,36 @@ package android.graphics { method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config); method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config); method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, android.graphics.Bitmap.Config); + method public static android.graphics.Bitmap createBitmap(android.graphics.Picture); + method public static android.graphics.Bitmap createBitmap(android.graphics.Picture, int, int, android.graphics.Bitmap.Config); method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, boolean); method public int describeContents(); method public void eraseColor(int); method public android.graphics.Bitmap extractAlpha(); method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]); - method public final int getAllocationByteCount(); - method public final int getByteCount(); - method public final android.graphics.ColorSpace getColorSpace(); - method public final android.graphics.Bitmap.Config getConfig(); + method public int getAllocationByteCount(); + method public int getByteCount(); + method public android.graphics.ColorSpace getColorSpace(); + method public android.graphics.Bitmap.Config getConfig(); method public int getDensity(); method public int getGenerationId(); - method public final int getHeight(); + method public int getHeight(); method public byte[] getNinePatchChunk(); method public int getPixel(int, int); method public void getPixels(int[], int, int, int, int, int, int); - method public final int getRowBytes(); + method public int getRowBytes(); method public int getScaledHeight(android.graphics.Canvas); method public int getScaledHeight(android.util.DisplayMetrics); method public int getScaledHeight(int); method public int getScaledWidth(android.graphics.Canvas); method public int getScaledWidth(android.util.DisplayMetrics); method public int getScaledWidth(int); - method public final int getWidth(); - method public final boolean hasAlpha(); - method public final boolean hasMipMap(); - method public final boolean isMutable(); - method public final boolean isPremultiplied(); - method public final boolean isRecycled(); + method public int getWidth(); + method public boolean hasAlpha(); + method public boolean hasMipMap(); + method public boolean isMutable(); + method public boolean isPremultiplied(); + method public boolean isRecycled(); method public void prepareToDraw(); method public void reconfigure(int, int, android.graphics.Bitmap.Config); method public void recycle(); @@ -13079,11 +13087,11 @@ package android.graphics { method public void setConfig(android.graphics.Bitmap.Config); method public void setDensity(int); method public void setHasAlpha(boolean); - method public final void setHasMipMap(boolean); + method public void setHasMipMap(boolean); method public void setHeight(int); method public void setPixel(int, int, int); method public void setPixels(int[], int, int, int, int, int, int); - method public final void setPremultiplied(boolean); + method public void setPremultiplied(boolean); method public void setWidth(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -13155,7 +13163,7 @@ package android.graphics { method public android.graphics.Bitmap decodeRegion(android.graphics.Rect, android.graphics.BitmapFactory.Options); method public int getHeight(); method public int getWidth(); - method public final boolean isRecycled(); + method public boolean isRecycled(); method public static android.graphics.BitmapRegionDecoder newInstance(byte[], int, int, boolean) throws java.io.IOException; method public static android.graphics.BitmapRegionDecoder newInstance(java.io.FileDescriptor, boolean) throws java.io.IOException; method public static android.graphics.BitmapRegionDecoder newInstance(java.io.InputStream, boolean) throws java.io.IOException; @@ -14101,6 +14109,7 @@ package android.graphics { method public void endRecording(); method public int getHeight(); method public int getWidth(); + method public boolean requiresHardwareAcceleration(); method public deprecated void writeToStream(java.io.OutputStream); } @@ -14215,22 +14224,22 @@ package android.graphics { ctor public Rect(); ctor public Rect(int, int, int, int); ctor public Rect(android.graphics.Rect); - method public final int centerX(); - method public final int centerY(); + method public int centerX(); + method public int centerY(); method public boolean contains(int, int); method public boolean contains(int, int, int, int); method public boolean contains(android.graphics.Rect); method public int describeContents(); - method public final float exactCenterX(); - method public final float exactCenterY(); + method public float exactCenterX(); + method public float exactCenterY(); method public java.lang.String flattenToString(); - method public final int height(); + method public int height(); method public void inset(int, int); method public boolean intersect(int, int, int, int); method public boolean intersect(android.graphics.Rect); method public boolean intersects(int, int, int, int); method public static boolean intersects(android.graphics.Rect, android.graphics.Rect); - method public final boolean isEmpty(); + method public boolean isEmpty(); method public void offset(int, int); method public void offsetTo(int, int); method public void readFromParcel(android.os.Parcel); @@ -14244,7 +14253,7 @@ package android.graphics { method public void union(int, int, int, int); method public void union(android.graphics.Rect); method public void union(int, int); - method public final int width(); + method public int width(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public int bottom; @@ -15813,9 +15822,7 @@ package android.hardware.camera2 { } public static final class CameraCharacteristics.Key { - method public final boolean equals(java.lang.Object); method public java.lang.String getName(); - method public final int hashCode(); } public abstract class CameraConstrainedHighSpeedCaptureSession extends android.hardware.camera2.CameraCaptureSession { @@ -16177,9 +16184,7 @@ package android.hardware.camera2 { } public static final class CaptureRequest.Key { - method public final boolean equals(java.lang.Object); method public java.lang.String getName(); - method public final int hashCode(); } public class CaptureResult extends android.hardware.camera2.CameraMetadata { @@ -16272,9 +16277,7 @@ package android.hardware.camera2 { } public static final class CaptureResult.Key { - method public final boolean equals(java.lang.Object); method public java.lang.String getName(); - method public final int hashCode(); } public final class DngCreator implements java.lang.AutoCloseable { @@ -16293,7 +16296,7 @@ package android.hardware.camera2 { public final class TotalCaptureResult extends android.hardware.camera2.CaptureResult { method public java.util.List getPartialResults(); - method public T getPhysicalCameraKey(android.hardware.camera2.CaptureResult.Key, java.lang.String); + method public java.util.Map getPhysicalCameraResults(); } } @@ -16368,7 +16371,7 @@ package android.hardware.camera2.params { method public void addSurface(android.view.Surface); method public int describeContents(); method public void enableSurfaceSharing(); - method public static int getMaxSharedSurfaceCount(); + method public int getMaxSharedSurfaceCount(); method public android.view.Surface getSurface(); method public int getSurfaceGroupId(); method public java.util.List getSurfaces(); @@ -16386,7 +16389,7 @@ package android.hardware.camera2.params { method public float getComponent(int); method public float getGreenEven(); method public float getGreenOdd(); - method public final float getRed(); + method public float getRed(); field public static final int BLUE = 3; // 0x3 field public static final int COUNT = 4; // 0x4 field public static final int GREEN_EVEN = 1; // 0x1 @@ -16414,16 +16417,16 @@ package android.hardware.camera2.params { method public android.util.Range[] getHighSpeedVideoFpsRangesFor(android.util.Size); method public android.util.Size[] getHighSpeedVideoSizes(); method public android.util.Size[] getHighSpeedVideoSizesFor(android.util.Range); - method public final int[] getInputFormats(); + method public int[] getInputFormats(); method public android.util.Size[] getInputSizes(int); - method public final int[] getOutputFormats(); + method public int[] getOutputFormats(); method public long getOutputMinFrameDuration(int, android.util.Size); method public long getOutputMinFrameDuration(java.lang.Class, android.util.Size); method public android.util.Size[] getOutputSizes(java.lang.Class); method public android.util.Size[] getOutputSizes(int); method public long getOutputStallDuration(int, android.util.Size); method public long getOutputStallDuration(java.lang.Class, android.util.Size); - method public final int[] getValidOutputFormatsForInput(int); + method public int[] getValidOutputFormatsForInput(int); method public boolean isOutputSupportedFor(int); method public static boolean isOutputSupportedFor(java.lang.Class); method public boolean isOutputSupportedFor(android.view.Surface); @@ -16488,8 +16491,37 @@ package android.hardware.display { package android.hardware.fingerprint { public class FingerprintDialog { - method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback); - method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback); + method public void authenticate(android.hardware.fingerprint.FingerprintDialog.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintDialog.AuthenticationCallback); + method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.fingerprint.FingerprintDialog.AuthenticationCallback); + field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 + field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3 + field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2 + field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1 + field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5 + field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4 + field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5 + field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc + field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1 + field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7 + field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9 + field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb + field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 + field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 + field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 + field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa + field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 + } + + public static abstract class FingerprintDialog.AuthenticationCallback { + ctor public FingerprintDialog.AuthenticationCallback(); + method public void onAuthenticationError(int, java.lang.CharSequence); + method public void onAuthenticationFailed(); + method public void onAuthenticationHelp(int, java.lang.CharSequence); + method public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintDialog.AuthenticationResult); + } + + public static class FingerprintDialog.AuthenticationResult { + method public android.hardware.fingerprint.FingerprintDialog.CryptoObject getCryptoObject(); } public static class FingerprintDialog.Builder { @@ -16501,10 +16533,19 @@ package android.hardware.fingerprint { method public android.hardware.fingerprint.FingerprintDialog.Builder setTitle(java.lang.CharSequence); } - public class FingerprintManager { - method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler); - method public boolean hasEnrolledFingerprints(); - method public boolean isHardwareDetected(); + public static final class FingerprintDialog.CryptoObject { + ctor public FingerprintDialog.CryptoObject(java.security.Signature); + ctor public FingerprintDialog.CryptoObject(javax.crypto.Cipher); + ctor public FingerprintDialog.CryptoObject(javax.crypto.Mac); + method public javax.crypto.Cipher getCipher(); + method public javax.crypto.Mac getMac(); + method public java.security.Signature getSignature(); + } + + public deprecated class FingerprintManager { + method public deprecated void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler); + method public deprecated boolean hasEnrolledFingerprints(); + method public deprecated boolean isHardwareDetected(); field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3 field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2 @@ -16512,9 +16553,11 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5 field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4 field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5 + field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1 field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7 field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9 + field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 @@ -16731,12 +16774,12 @@ package android.icu.lang { public final class UCharacter implements android.icu.lang.UCharacterEnums.ECharacterCategory android.icu.lang.UCharacterEnums.ECharacterDirection { method public static int charCount(int); - method public static final int codePointAt(java.lang.CharSequence, int); - method public static final int codePointAt(char[], int); - method public static final int codePointAt(char[], int, int); - method public static final int codePointBefore(java.lang.CharSequence, int); - method public static final int codePointBefore(char[], int); - method public static final int codePointBefore(char[], int, int); + method public static int codePointAt(java.lang.CharSequence, int); + method public static int codePointAt(char[], int); + method public static int codePointAt(char[], int, int); + method public static int codePointBefore(java.lang.CharSequence, int); + method public static int codePointBefore(char[], int); + method public static int codePointBefore(char[], int, int); method public static int codePointCount(java.lang.CharSequence, int, int); method public static int codePointCount(char[], int, int); method public static int digit(int, int); @@ -16744,7 +16787,7 @@ package android.icu.lang { method public static int foldCase(int, boolean); method public static java.lang.String foldCase(java.lang.String, boolean); method public static int foldCase(int, int); - method public static final java.lang.String foldCase(java.lang.String, int); + method public static java.lang.String foldCase(java.lang.String, int); method public static char forDigit(int, int); method public static android.icu.util.VersionInfo getAge(int); method public static int getBidiPairedBracket(int); @@ -16796,8 +16839,8 @@ package android.icu.lang { method public static boolean isPrintable(int); method public static boolean isSpaceChar(int); method public static boolean isSupplementary(int); - method public static final boolean isSupplementaryCodePoint(int); - method public static final boolean isSurrogatePair(char, char); + method public static boolean isSupplementaryCodePoint(int); + method public static boolean isSurrogatePair(char, char); method public static boolean isTitleCase(int); method public static boolean isUAlphabetic(int); method public static boolean isULowercase(int); @@ -16806,13 +16849,13 @@ package android.icu.lang { method public static boolean isUnicodeIdentifierPart(int); method public static boolean isUnicodeIdentifierStart(int); method public static boolean isUpperCase(int); - method public static final boolean isValidCodePoint(int); + method public static boolean isValidCodePoint(int); method public static boolean isWhitespace(int); method public static int offsetByCodePoints(java.lang.CharSequence, int, int); method public static int offsetByCodePoints(char[], int, int, int, int); - method public static final int toChars(int, char[], int); - method public static final char[] toChars(int); - method public static final int toCodePoint(char, char); + method public static int toChars(int, char[], int); + method public static char[] toChars(int); + method public static int toCodePoint(char, char); method public static int toLowerCase(int); method public static java.lang.String toLowerCase(java.lang.String); method public static java.lang.String toLowerCase(java.util.Locale, java.lang.String); @@ -17102,7 +17145,7 @@ package android.icu.lang { } public static final class UCharacter.UnicodeBlock extends java.lang.Character.Subset { - method public static final android.icu.lang.UCharacter.UnicodeBlock forName(java.lang.String); + method public static android.icu.lang.UCharacter.UnicodeBlock forName(java.lang.String); method public int getID(); method public static android.icu.lang.UCharacter.UnicodeBlock getInstance(int); method public static android.icu.lang.UCharacter.UnicodeBlock of(int); @@ -17909,20 +17952,20 @@ package android.icu.lang { } public final class UScript { - method public static final boolean breaksBetweenLetters(int); - method public static final int[] getCode(java.util.Locale); - method public static final int[] getCode(android.icu.util.ULocale); - method public static final int[] getCode(java.lang.String); - method public static final int getCodeFromName(java.lang.String); - method public static final java.lang.String getName(int); - method public static final java.lang.String getSampleString(int); - method public static final int getScript(int); - method public static final int getScriptExtensions(int, java.util.BitSet); - method public static final java.lang.String getShortName(int); - method public static final android.icu.lang.UScript.ScriptUsage getUsage(int); - method public static final boolean hasScript(int, int); - method public static final boolean isCased(int); - method public static final boolean isRightToLeft(int); + method public static boolean breaksBetweenLetters(int); + method public static int[] getCode(java.util.Locale); + method public static int[] getCode(android.icu.util.ULocale); + method public static int[] getCode(java.lang.String); + method public static int getCodeFromName(java.lang.String); + method public static java.lang.String getName(int); + method public static java.lang.String getSampleString(int); + method public static int getScript(int); + method public static int getScriptExtensions(int, java.util.BitSet); + method public static java.lang.String getShortName(int); + method public static android.icu.lang.UScript.ScriptUsage getUsage(int); + method public static boolean hasScript(int, int); + method public static boolean isCased(int); + method public static boolean isRightToLeft(int); field public static final int ADLAM = 167; // 0xa7 field public static final int AFAKA = 147; // 0x93 field public static final int AHOM = 161; // 0xa1 @@ -18337,14 +18380,14 @@ package android.icu.text { method public deprecated int hashCode(); method public int next(); method public int previous(); - method public static final int primaryOrder(int); + method public static int primaryOrder(int); method public void reset(); - method public static final int secondaryOrder(int); + method public static int secondaryOrder(int); method public void setOffset(int); method public void setText(java.lang.String); method public void setText(android.icu.text.UCharacterIterator); method public void setText(java.text.CharacterIterator); - method public static final int tertiaryOrder(int); + method public static int tertiaryOrder(int); field public static final int IGNORABLE = 0; // 0x0 field public static final int NULLORDER = -1; // 0xffffffff } @@ -19571,7 +19614,7 @@ package android.icu.text { method public boolean isUpperCaseFirst(); method public void setAlternateHandlingDefault(); method public void setAlternateHandlingShifted(boolean); - method public final void setCaseFirstDefault(); + method public void setCaseFirstDefault(); method public void setCaseLevel(boolean); method public void setCaseLevelDefault(); method public void setDecompositionDefault(); @@ -20544,11 +20587,11 @@ package android.icu.util { public final class LocaleData { method public static android.icu.util.VersionInfo getCLDRVersion(); method public java.lang.String getDelimiter(int); - method public static final android.icu.util.LocaleData getInstance(android.icu.util.ULocale); - method public static final android.icu.util.LocaleData getInstance(); - method public static final android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale); + method public static android.icu.util.LocaleData getInstance(android.icu.util.ULocale); + method public static android.icu.util.LocaleData getInstance(); + method public static android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale); method public boolean getNoSubstitute(); - method public static final android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale); + method public static android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale); method public void setNoSubstitute(boolean); field public static final int ALT_QUOTATION_END = 3; // 0x3 field public static final int ALT_QUOTATION_START = 2; // 0x2 @@ -21948,6 +21991,7 @@ package android.media { field public static final int ENCODING_DTS = 7; // 0x7 field public static final int ENCODING_DTS_HD = 8; // 0x8 field public static final int ENCODING_E_AC3 = 6; // 0x6 + field public static final int ENCODING_E_AC3_JOC = 18; // 0x12 field public static final int ENCODING_IEC61937 = 13; // 0xd field public static final int ENCODING_INVALID = 0; // 0x0 field public static final int ENCODING_MP3 = 9; // 0x9 @@ -21978,6 +22022,7 @@ package android.media { method public java.util.List getActivePlaybackConfigurations(); method public java.util.List getActiveRecordingConfigurations(); method public android.media.AudioDeviceInfo[] getDevices(int); + method public java.util.List getMicrophones() throws java.io.IOException; method public int getMode(); method public java.lang.String getParameters(java.lang.String); method public java.lang.String getProperty(java.lang.String); @@ -22151,11 +22196,26 @@ package android.media { field public static final android.os.Parcelable.Creator CREATOR; } + public final class AudioPresentation { + method public java.util.Map getLabels(); + method public java.util.Locale getLocale(); + method public int getMasteringIndication(); + method public boolean hasAudioDescription(); + method public boolean hasDialogueEnhancement(); + method public boolean hasSpokenSubtitles(); + field public static final int MASTERED_FOR_3D = 3; // 0x3 + field public static final int MASTERED_FOR_HEADPHONE = 4; // 0x4 + field public static final int MASTERED_FOR_STEREO = 1; // 0x1 + field public static final int MASTERED_FOR_SURROUND = 2; // 0x2 + field public static final int MASTERING_NOT_INDICATED = 0; // 0x0 + } + public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler); method protected void finalize(); + method public java.util.List getActiveMicrophones() throws java.io.IOException; method public int getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSource(); @@ -22316,6 +22376,7 @@ package android.media { method public int setPlaybackRate(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); + method public int setPresentation(android.media.AudioPresentation); method protected deprecated void setState(int); method public deprecated int setStereoVolume(float, float); method public void setStreamEventCallback(java.util.concurrent.Executor, android.media.AudioTrack.StreamEventCallback); @@ -22820,40 +22881,40 @@ package android.media { method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException; method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException; method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException; - method public final android.view.Surface createInputSurface(); + method public android.view.Surface createInputSurface(); method public static android.view.Surface createPersistentInputSurface(); - method public final int dequeueInputBuffer(long); - method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long); + method public int dequeueInputBuffer(long); + method public int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long); method protected void finalize(); - method public final void flush(); + method public void flush(); method public android.media.MediaCodecInfo getCodecInfo(); method public java.nio.ByteBuffer getInputBuffer(int); method public deprecated java.nio.ByteBuffer[] getInputBuffers(); - method public final android.media.MediaFormat getInputFormat(); + method public android.media.MediaFormat getInputFormat(); method public android.media.Image getInputImage(int); method public android.os.PersistableBundle getMetrics(); - method public final java.lang.String getName(); + method public java.lang.String getName(); method public java.nio.ByteBuffer getOutputBuffer(int); method public deprecated java.nio.ByteBuffer[] getOutputBuffers(); - method public final android.media.MediaFormat getOutputFormat(); - method public final android.media.MediaFormat getOutputFormat(int); + method public android.media.MediaFormat getOutputFormat(); + method public android.media.MediaFormat getOutputFormat(int); method public android.media.Image getOutputImage(int); - method public final void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException; - method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException; - method public final void release(); - method public final void releaseOutputBuffer(int, boolean); - method public final void releaseOutputBuffer(int, long); - method public final void reset(); + method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException; + method public void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException; + method public void release(); + method public void releaseOutputBuffer(int, boolean); + method public void releaseOutputBuffer(int, long); + method public void reset(); method public void setCallback(android.media.MediaCodec.Callback, android.os.Handler); method public void setCallback(android.media.MediaCodec.Callback); method public void setInputSurface(android.view.Surface); method public void setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler); method public void setOutputSurface(android.view.Surface); - method public final void setParameters(android.os.Bundle); - method public final void setVideoScalingMode(int); - method public final void signalEndOfInputStream(); - method public final void start(); - method public final void stop(); + method public void setParameters(android.os.Bundle); + method public void setVideoScalingMode(int); + method public void signalEndOfInputStream(); + method public void start(); + method public void stop(); field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2 field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4 field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1 @@ -22947,10 +23008,10 @@ package android.media { } public final class MediaCodecInfo { - method public final android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String); - method public final java.lang.String getName(); - method public final java.lang.String[] getSupportedTypes(); - method public final boolean isEncoder(); + method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String); + method public java.lang.String getName(); + method public java.lang.String[] getSupportedTypes(); + method public boolean isEncoder(); } public static final class MediaCodecInfo.AudioCapabilities { @@ -22970,9 +23031,9 @@ package android.media { method public int getMaxSupportedInstances(); method public java.lang.String getMimeType(); method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities(); - method public final boolean isFeatureRequired(java.lang.String); - method public final boolean isFeatureSupported(java.lang.String); - method public final boolean isFormatSupported(android.media.MediaFormat); + method public boolean isFeatureRequired(java.lang.String); + method public boolean isFeatureSupported(java.lang.String); + method public boolean isFormatSupported(android.media.MediaFormat); field public static final deprecated int COLOR_Format12bitRGB444 = 3; // 0x3 field public static final deprecated int COLOR_Format16bitARGB1555 = 5; // 0x5 field public static final deprecated int COLOR_Format16bitARGB4444 = 4; // 0x4 @@ -23230,11 +23291,11 @@ package android.media { public final class MediaCodecList { ctor public MediaCodecList(int); - method public final java.lang.String findDecoderForFormat(android.media.MediaFormat); - method public final java.lang.String findEncoderForFormat(android.media.MediaFormat); - method public static final deprecated int getCodecCount(); - method public static final deprecated android.media.MediaCodecInfo getCodecInfoAt(int); - method public final android.media.MediaCodecInfo[] getCodecInfos(); + method public java.lang.String findDecoderForFormat(android.media.MediaFormat); + method public java.lang.String findEncoderForFormat(android.media.MediaFormat); + method public static deprecated int getCodecCount(); + method public static deprecated android.media.MediaCodecInfo getCodecInfoAt(int); + method public android.media.MediaCodecInfo[] getCodecInfos(); field public static final int ALL_CODECS = 1; // 0x1 field public static final int REGULAR_CODECS = 0; // 0x0 } @@ -23242,10 +23303,10 @@ package android.media { public final class MediaCrypto { ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException; method protected void finalize(); - method public static final boolean isCryptoSchemeSupported(java.util.UUID); - method public final void release(); - method public final boolean requiresSecureDecoderComponent(java.lang.String); - method public final void setMediaDrmSession(byte[]) throws android.media.MediaCryptoException; + method public static boolean isCryptoSchemeSupported(java.util.UUID); + method public void release(); + method public boolean requiresSecureDecoderComponent(java.lang.String); + method public void setMediaDrmSession(byte[]) throws android.media.MediaCryptoException; } public final class MediaCryptoException extends java.lang.Exception { @@ -23261,10 +23322,10 @@ package android.media { public final class MediaDescrambler implements java.lang.AutoCloseable { ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException; method public void close(); - method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo); + method public int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo); method protected void finalize(); - method public final boolean requiresSecureDecoderComponent(java.lang.String); - method public final void setMediaCasSession(android.media.MediaCas.Session); + method public boolean requiresSecureDecoderComponent(java.lang.String); + method public void setMediaCasSession(android.media.MediaCas.Session); } public class MediaDescription implements android.os.Parcelable { @@ -23320,8 +23381,8 @@ package android.media { method public java.util.List getSecureStopIds(); method public java.util.List getSecureStops(); method public int getSecurityLevel(byte[]); - method public static final boolean isCryptoSchemeSupported(java.util.UUID); - method public static final boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String); + method public static boolean isCryptoSchemeSupported(java.util.UUID); + method public static boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String); method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException; method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException; method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException; @@ -23472,6 +23533,7 @@ package android.media { ctor public MediaExtractor(); method public boolean advance(); method protected void finalize(); + method public java.util.List getAudioPresentations(int); method public long getCachedDuration(); method public android.media.MediaExtractor.CasInfo getCasInfo(int); method public android.media.DrmInitData getDrmInitData(); @@ -23482,21 +23544,21 @@ package android.media { method public long getSampleSize(); method public long getSampleTime(); method public int getSampleTrackIndex(); - method public final int getTrackCount(); + method public int getTrackCount(); method public android.media.MediaFormat getTrackFormat(int); method public boolean hasCacheReachedEndOfStream(); method public int readSampleData(java.nio.ByteBuffer, int); - method public final void release(); + method public void release(); method public void seekTo(long, int); method public void selectTrack(int); - method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException; - method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map) throws java.io.IOException; - method public final void setDataSource(java.lang.String, java.util.Map) throws java.io.IOException; - method public final void setDataSource(java.lang.String) throws java.io.IOException; - method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException; - method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException; - method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException; - method public final void setMediaCas(android.media.MediaCas); + method public void setDataSource(android.media.MediaDataSource) throws java.io.IOException; + method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map) throws java.io.IOException; + method public void setDataSource(java.lang.String, java.util.Map) throws java.io.IOException; + method public void setDataSource(java.lang.String) throws java.io.IOException; + method public void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException; + method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException; + method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException; + method public void setMediaCas(android.media.MediaCas); method public void unselectTrack(int); field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2 field public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4; // 0x4 @@ -23519,22 +23581,22 @@ package android.media { public final class MediaFormat { ctor public MediaFormat(); - method public final boolean containsKey(java.lang.String); - method public static final android.media.MediaFormat createAudioFormat(java.lang.String, int, int); - method public static final android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String); - method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int); - method public final java.nio.ByteBuffer getByteBuffer(java.lang.String); + method public boolean containsKey(java.lang.String); + method public static android.media.MediaFormat createAudioFormat(java.lang.String, int, int); + method public static android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String); + method public static android.media.MediaFormat createVideoFormat(java.lang.String, int, int); + method public java.nio.ByteBuffer getByteBuffer(java.lang.String); method public boolean getFeatureEnabled(java.lang.String); - method public final float getFloat(java.lang.String); - method public final int getInteger(java.lang.String); - method public final long getLong(java.lang.String); - method public final java.lang.String getString(java.lang.String); - method public final void setByteBuffer(java.lang.String, java.nio.ByteBuffer); + method public float getFloat(java.lang.String); + method public int getInteger(java.lang.String); + method public long getLong(java.lang.String); + method public java.lang.String getString(java.lang.String); + method public void setByteBuffer(java.lang.String, java.nio.ByteBuffer); method public void setFeatureEnabled(java.lang.String, boolean); - method public final void setFloat(java.lang.String, float); - method public final void setInteger(java.lang.String, int); - method public final void setLong(java.lang.String, long); - method public final void setString(java.lang.String, java.lang.String); + method public void setFloat(java.lang.String, float); + method public void setInteger(java.lang.String, int); + method public void setLong(java.lang.String, long); + method public void setString(java.lang.String, java.lang.String); field public static final int COLOR_RANGE_FULL = 1; // 0x1 field public static final int COLOR_RANGE_LIMITED = 2; // 0x2 field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6 @@ -24160,6 +24222,7 @@ package android.media { ctor public MediaRecorder(); method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method protected void finalize(); + method public java.util.List getActiveMicrophones() throws java.io.IOException; method public static final int getAudioSourceMax(); method public int getMaxAmplitude() throws java.lang.IllegalStateException; method public android.os.PersistableBundle getMetrics(); @@ -24433,14 +24496,14 @@ package android.media { public final class MediaSync { ctor public MediaSync(); - method public final android.view.Surface createInputSurface(); + method public android.view.Surface createInputSurface(); method protected void finalize(); method public void flush(); method public android.media.PlaybackParams getPlaybackParams(); method public android.media.SyncParams getSyncParams(); method public android.media.MediaTimestamp getTimestamp(); method public void queueAudio(java.nio.ByteBuffer, int, long); - method public final void release(); + method public void release(); method public void setAudioTrack(android.media.AudioTrack); method public void setCallback(android.media.MediaSync.Callback, android.os.Handler); method public void setOnErrorListener(android.media.MediaSync.OnErrorListener, android.os.Handler); @@ -24475,6 +24538,41 @@ package android.media { method public float getMediaClockRate(); } + public final class MicrophoneInfo { + method public java.util.List> getChannelMapping(); + method public java.lang.String getDescription(); + method public int getDirectionality(); + method public java.util.List> getFrequencyResponse(); + method public int getGroup(); + method public int getId(); + method public int getIndexInTheGroup(); + method public int getLocation(); + method public float getMaxSpl(); + method public float getMinSpl(); + method public android.media.MicrophoneInfo.Coordinate3F getOrientation(); + method public android.media.MicrophoneInfo.Coordinate3F getPosition(); + method public float getSensitivity(); + method public int getType(); + field public static final int CHANNEL_MAPPING_DIRECT = 1; // 0x1 + field public static final int CHANNEL_MAPPING_PROCESSED = 2; // 0x2 + field public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2; // 0x2 + field public static final int DIRECTIONALITY_CARDIOID = 3; // 0x3 + field public static final int DIRECTIONALITY_HYPER_CARDIOID = 4; // 0x4 + field public static final int DIRECTIONALITY_OMNI = 1; // 0x1 + field public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; // 0x5 + field public static final int DIRECTIONALITY_UNKNOWN = 0; // 0x0 + field public static final int LOCATION_MAINBODY = 1; // 0x1 + field public static final int LOCATION_MAINBODY_MOVABLE = 2; // 0x2 + field public static final int LOCATION_PERIPHERAL = 3; // 0x3 + field public static final int LOCATION_UNKNOWN = 0; // 0x0 + } + + public class MicrophoneInfo.Coordinate3F { + field public final float x; + field public final float y; + field public final float z; + } + public final class NotProvisionedException extends android.media.MediaDrmException { ctor public NotProvisionedException(java.lang.String); } @@ -25395,7 +25493,7 @@ package android.media.midi { public final class MidiInputPort extends android.media.midi.MidiReceiver implements java.io.Closeable { method public void close() throws java.io.IOException; - method public final int getPortNumber(); + method public int getPortNumber(); method public void onSend(byte[], int, int, long) throws java.io.IOException; } @@ -25420,7 +25518,7 @@ package android.media.midi { public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable { method public void close() throws java.io.IOException; - method public final int getPortNumber(); + method public int getPortNumber(); method public void onConnect(android.media.midi.MidiReceiver); method public void onDisconnect(android.media.midi.MidiReceiver); } @@ -25695,7 +25793,7 @@ package android.media.session { package android.media.tv { public final class TvContentRating { - method public final boolean contains(android.media.tv.TvContentRating); + method public boolean contains(android.media.tv.TvContentRating); method public static android.media.tv.TvContentRating createRating(java.lang.String, java.lang.String, java.lang.String, java.lang.String...); method public java.lang.String flattenToString(); method public java.lang.String getDomain(); @@ -25745,7 +25843,7 @@ package android.media.tv { } public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns { - method public static final java.lang.String getVideoResolution(java.lang.String); + method public static java.lang.String getVideoResolution(java.lang.String); field public static final java.lang.String COLUMN_APP_LINK_COLOR = "app_link_color"; field public static final java.lang.String COLUMN_APP_LINK_ICON_URI = "app_link_icon_uri"; field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri"; @@ -26270,18 +26368,18 @@ package android.media.tv { public final class TvTrackInfo implements android.os.Parcelable { method public int describeContents(); - method public final int getAudioChannelCount(); - method public final int getAudioSampleRate(); - method public final java.lang.CharSequence getDescription(); - method public final android.os.Bundle getExtra(); - method public final java.lang.String getId(); - method public final java.lang.String getLanguage(); - method public final int getType(); - method public final byte getVideoActiveFormatDescription(); - method public final float getVideoFrameRate(); - method public final int getVideoHeight(); - method public final float getVideoPixelAspectRatio(); - method public final int getVideoWidth(); + method public int getAudioChannelCount(); + method public int getAudioSampleRate(); + method public java.lang.CharSequence getDescription(); + method public android.os.Bundle getExtra(); + method public java.lang.String getId(); + method public java.lang.String getLanguage(); + method public int getType(); + method public byte getVideoActiveFormatDescription(); + method public float getVideoFrameRate(); + method public int getVideoHeight(); + method public float getVideoPixelAspectRatio(); + method public int getVideoWidth(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int TYPE_AUDIO = 0; // 0x0 @@ -26292,16 +26390,16 @@ package android.media.tv { public static final class TvTrackInfo.Builder { ctor public TvTrackInfo.Builder(int, java.lang.String); method public android.media.tv.TvTrackInfo build(); - method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int); - method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int); - method public final android.media.tv.TvTrackInfo.Builder setDescription(java.lang.CharSequence); - method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle); - method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String); - method public final android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte); - method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float); - method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int); - method public final android.media.tv.TvTrackInfo.Builder setVideoPixelAspectRatio(float); - method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int); + method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int); + method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int); + method public android.media.tv.TvTrackInfo.Builder setDescription(java.lang.CharSequence); + method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle); + method public android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String); + method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte); + method public android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float); + method public android.media.tv.TvTrackInfo.Builder setVideoHeight(int); + method public android.media.tv.TvTrackInfo.Builder setVideoPixelAspectRatio(float); + method public android.media.tv.TvTrackInfo.Builder setVideoWidth(int); } public class TvView extends android.view.ViewGroup { @@ -26532,34 +26630,34 @@ package android.mtp { } public final class MtpObjectInfo { - method public final int getAssociationDesc(); - method public final int getAssociationType(); - method public final int getCompressedSize(); - method public final long getCompressedSizeLong(); - method public final long getDateCreated(); - method public final long getDateModified(); - method public final int getFormat(); - method public final int getImagePixDepth(); - method public final long getImagePixDepthLong(); - method public final int getImagePixHeight(); - method public final long getImagePixHeightLong(); - method public final int getImagePixWidth(); - method public final long getImagePixWidthLong(); - method public final java.lang.String getKeywords(); - method public final java.lang.String getName(); - method public final int getObjectHandle(); - method public final int getParent(); - method public final int getProtectionStatus(); - method public final int getSequenceNumber(); - method public final long getSequenceNumberLong(); - method public final int getStorageId(); - method public final int getThumbCompressedSize(); - method public final long getThumbCompressedSizeLong(); - method public final int getThumbFormat(); - method public final int getThumbPixHeight(); - method public final long getThumbPixHeightLong(); - method public final int getThumbPixWidth(); - method public final long getThumbPixWidthLong(); + method public int getAssociationDesc(); + method public int getAssociationType(); + method public int getCompressedSize(); + method public long getCompressedSizeLong(); + method public long getDateCreated(); + method public long getDateModified(); + method public int getFormat(); + method public int getImagePixDepth(); + method public long getImagePixDepthLong(); + method public int getImagePixHeight(); + method public long getImagePixHeightLong(); + method public int getImagePixWidth(); + method public long getImagePixWidthLong(); + method public java.lang.String getKeywords(); + method public java.lang.String getName(); + method public int getObjectHandle(); + method public int getParent(); + method public int getProtectionStatus(); + method public int getSequenceNumber(); + method public long getSequenceNumberLong(); + method public int getStorageId(); + method public int getThumbCompressedSize(); + method public long getThumbCompressedSizeLong(); + method public int getThumbFormat(); + method public int getThumbPixHeight(); + method public long getThumbPixHeightLong(); + method public int getThumbPixWidth(); + method public long getThumbPixWidthLong(); } public static class MtpObjectInfo.Builder { @@ -26589,11 +26687,11 @@ package android.mtp { } public final class MtpStorageInfo { - method public final java.lang.String getDescription(); - method public final long getFreeSpace(); - method public final long getMaxCapacity(); - method public final int getStorageId(); - method public final java.lang.String getVolumeIdentifier(); + method public java.lang.String getDescription(); + method public long getFreeSpace(); + method public long getMaxCapacity(); + method public int getStorageId(); + method public java.lang.String getVolumeIdentifier(); } } @@ -27026,10 +27124,10 @@ package android.net { public final class Proxy { ctor public Proxy(); - method public static final deprecated java.lang.String getDefaultHost(); - method public static final deprecated int getDefaultPort(); - method public static final deprecated java.lang.String getHost(android.content.Context); - method public static final deprecated int getPort(android.content.Context); + method public static deprecated java.lang.String getDefaultHost(); + method public static deprecated int getDefaultPort(); + method public static deprecated java.lang.String getHost(android.content.Context); + method public static deprecated int getPort(android.content.Context); field public static final deprecated java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; } @@ -28550,10 +28648,14 @@ package android.nfc { field public static final java.lang.String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; field public static final java.lang.String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; field public static final java.lang.String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; + field public static final java.lang.String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED"; field public static final java.lang.String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE"; + field public static final java.lang.String EXTRA_AID = "android.nfc.extra.AID"; + field public static final java.lang.String EXTRA_DATA = "android.nfc.extra.DATA"; field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID"; field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; + field public static final java.lang.String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME"; field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG"; field public static final int FLAG_READER_NFC_A = 1; // 0x1 field public static final int FLAG_READER_NFC_B = 2; // 0x2 @@ -32056,9 +32158,9 @@ package android.os { method public static void dumpHprofData(java.lang.String) throws java.io.IOException; method public static boolean dumpService(java.lang.String, java.io.FileDescriptor, java.lang.String[]); method public static void enableEmulatorTraceOutput(); - method public static final int getBinderDeathObjectCount(); - method public static final int getBinderLocalObjectCount(); - method public static final int getBinderProxyObjectCount(); + method public static int getBinderDeathObjectCount(); + method public static int getBinderLocalObjectCount(); + method public static int getBinderProxyObjectCount(); method public static int getBinderReceivedTransactions(); method public static int getBinderSentTransactions(); method public static deprecated int getGlobalAllocCount(); @@ -32467,114 +32569,114 @@ package android.os { } public final class Parcel { - method public final void appendFrom(android.os.Parcel, int, int); - method public final android.os.IBinder[] createBinderArray(); - method public final java.util.ArrayList createBinderArrayList(); - method public final boolean[] createBooleanArray(); - method public final byte[] createByteArray(); - method public final char[] createCharArray(); - method public final double[] createDoubleArray(); - method public final float[] createFloatArray(); - method public final int[] createIntArray(); - method public final long[] createLongArray(); - method public final java.lang.String[] createStringArray(); - method public final java.util.ArrayList createStringArrayList(); - method public final T[] createTypedArray(android.os.Parcelable.Creator); - method public final java.util.ArrayList createTypedArrayList(android.os.Parcelable.Creator); - method public final int dataAvail(); - method public final int dataCapacity(); - method public final int dataPosition(); - method public final int dataSize(); - method public final void enforceInterface(java.lang.String); - method public final boolean hasFileDescriptors(); - method public final byte[] marshall(); + method public void appendFrom(android.os.Parcel, int, int); + method public android.os.IBinder[] createBinderArray(); + method public java.util.ArrayList createBinderArrayList(); + method public boolean[] createBooleanArray(); + method public byte[] createByteArray(); + method public char[] createCharArray(); + method public double[] createDoubleArray(); + method public float[] createFloatArray(); + method public int[] createIntArray(); + method public long[] createLongArray(); + method public java.lang.String[] createStringArray(); + method public java.util.ArrayList createStringArrayList(); + method public T[] createTypedArray(android.os.Parcelable.Creator); + method public java.util.ArrayList createTypedArrayList(android.os.Parcelable.Creator); + method public int dataAvail(); + method public int dataCapacity(); + method public int dataPosition(); + method public int dataSize(); + method public void enforceInterface(java.lang.String); + method public boolean hasFileDescriptors(); + method public byte[] marshall(); method public static android.os.Parcel obtain(); - method public final java.lang.Object[] readArray(java.lang.ClassLoader); - method public final java.util.ArrayList readArrayList(java.lang.ClassLoader); - method public final void readBinderArray(android.os.IBinder[]); - method public final void readBinderList(java.util.List); - method public final void readBooleanArray(boolean[]); - method public final android.os.Bundle readBundle(); - method public final android.os.Bundle readBundle(java.lang.ClassLoader); - method public final byte readByte(); - method public final void readByteArray(byte[]); - method public final void readCharArray(char[]); - method public final double readDouble(); - method public final void readDoubleArray(double[]); - method public final void readException(); - method public final void readException(int, java.lang.String); - method public final android.os.ParcelFileDescriptor readFileDescriptor(); - method public final float readFloat(); - method public final void readFloatArray(float[]); - method public final java.util.HashMap readHashMap(java.lang.ClassLoader); - method public final int readInt(); - method public final void readIntArray(int[]); - method public final void readList(java.util.List, java.lang.ClassLoader); - method public final long readLong(); - method public final void readLongArray(long[]); - method public final void readMap(java.util.Map, java.lang.ClassLoader); - method public final T readParcelable(java.lang.ClassLoader); - method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader); - method public final android.os.PersistableBundle readPersistableBundle(); - method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader); - method public final java.io.Serializable readSerializable(); - method public final android.util.Size readSize(); - method public final android.util.SizeF readSizeF(); - method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader); - method public final android.util.SparseBooleanArray readSparseBooleanArray(); - method public final java.lang.String readString(); - method public final void readStringArray(java.lang.String[]); - method public final void readStringList(java.util.List); - method public final android.os.IBinder readStrongBinder(); - method public final void readTypedArray(T[], android.os.Parcelable.Creator); - method public final void readTypedList(java.util.List, android.os.Parcelable.Creator); - method public final T readTypedObject(android.os.Parcelable.Creator); - method public final java.lang.Object readValue(java.lang.ClassLoader); - method public final void recycle(); - method public final void setDataCapacity(int); - method public final void setDataPosition(int); - method public final void setDataSize(int); - method public final void unmarshall(byte[], int, int); - method public final void writeArray(java.lang.Object[]); - method public final void writeBinderArray(android.os.IBinder[]); - method public final void writeBinderList(java.util.List); - method public final void writeBooleanArray(boolean[]); - method public final void writeBundle(android.os.Bundle); - method public final void writeByte(byte); - method public final void writeByteArray(byte[]); - method public final void writeByteArray(byte[], int, int); - method public final void writeCharArray(char[]); - method public final void writeDouble(double); - method public final void writeDoubleArray(double[]); - method public final void writeException(java.lang.Exception); - method public final void writeFileDescriptor(java.io.FileDescriptor); - method public final void writeFloat(float); - method public final void writeFloatArray(float[]); - method public final void writeInt(int); - method public final void writeIntArray(int[]); - method public final void writeInterfaceToken(java.lang.String); - method public final void writeList(java.util.List); - method public final void writeLong(long); - method public final void writeLongArray(long[]); - method public final void writeMap(java.util.Map); - method public final void writeNoException(); - method public final void writeParcelable(android.os.Parcelable, int); - method public final void writeParcelableArray(T[], int); - method public final void writePersistableBundle(android.os.PersistableBundle); - method public final void writeSerializable(java.io.Serializable); - method public final void writeSize(android.util.Size); - method public final void writeSizeF(android.util.SizeF); - method public final void writeSparseArray(android.util.SparseArray); - method public final void writeSparseBooleanArray(android.util.SparseBooleanArray); - method public final void writeString(java.lang.String); - method public final void writeStringArray(java.lang.String[]); - method public final void writeStringList(java.util.List); - method public final void writeStrongBinder(android.os.IBinder); - method public final void writeStrongInterface(android.os.IInterface); - method public final void writeTypedArray(T[], int); - method public final void writeTypedList(java.util.List); - method public final void writeTypedObject(T, int); - method public final void writeValue(java.lang.Object); + method public java.lang.Object[] readArray(java.lang.ClassLoader); + method public java.util.ArrayList readArrayList(java.lang.ClassLoader); + method public void readBinderArray(android.os.IBinder[]); + method public void readBinderList(java.util.List); + method public void readBooleanArray(boolean[]); + method public android.os.Bundle readBundle(); + method public android.os.Bundle readBundle(java.lang.ClassLoader); + method public byte readByte(); + method public void readByteArray(byte[]); + method public void readCharArray(char[]); + method public double readDouble(); + method public void readDoubleArray(double[]); + method public void readException(); + method public void readException(int, java.lang.String); + method public android.os.ParcelFileDescriptor readFileDescriptor(); + method public float readFloat(); + method public void readFloatArray(float[]); + method public java.util.HashMap readHashMap(java.lang.ClassLoader); + method public int readInt(); + method public void readIntArray(int[]); + method public void readList(java.util.List, java.lang.ClassLoader); + method public long readLong(); + method public void readLongArray(long[]); + method public void readMap(java.util.Map, java.lang.ClassLoader); + method public T readParcelable(java.lang.ClassLoader); + method public android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader); + method public android.os.PersistableBundle readPersistableBundle(); + method public android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader); + method public java.io.Serializable readSerializable(); + method public android.util.Size readSize(); + method public android.util.SizeF readSizeF(); + method public android.util.SparseArray readSparseArray(java.lang.ClassLoader); + method public android.util.SparseBooleanArray readSparseBooleanArray(); + method public java.lang.String readString(); + method public void readStringArray(java.lang.String[]); + method public void readStringList(java.util.List); + method public android.os.IBinder readStrongBinder(); + method public void readTypedArray(T[], android.os.Parcelable.Creator); + method public void readTypedList(java.util.List, android.os.Parcelable.Creator); + method public T readTypedObject(android.os.Parcelable.Creator); + method public java.lang.Object readValue(java.lang.ClassLoader); + method public void recycle(); + method public void setDataCapacity(int); + method public void setDataPosition(int); + method public void setDataSize(int); + method public void unmarshall(byte[], int, int); + method public void writeArray(java.lang.Object[]); + method public void writeBinderArray(android.os.IBinder[]); + method public void writeBinderList(java.util.List); + method public void writeBooleanArray(boolean[]); + method public void writeBundle(android.os.Bundle); + method public void writeByte(byte); + method public void writeByteArray(byte[]); + method public void writeByteArray(byte[], int, int); + method public void writeCharArray(char[]); + method public void writeDouble(double); + method public void writeDoubleArray(double[]); + method public void writeException(java.lang.Exception); + method public void writeFileDescriptor(java.io.FileDescriptor); + method public void writeFloat(float); + method public void writeFloatArray(float[]); + method public void writeInt(int); + method public void writeIntArray(int[]); + method public void writeInterfaceToken(java.lang.String); + method public void writeList(java.util.List); + method public void writeLong(long); + method public void writeLongArray(long[]); + method public void writeMap(java.util.Map); + method public void writeNoException(); + method public void writeParcelable(android.os.Parcelable, int); + method public void writeParcelableArray(T[], int); + method public void writePersistableBundle(android.os.PersistableBundle); + method public void writeSerializable(java.io.Serializable); + method public void writeSize(android.util.Size); + method public void writeSizeF(android.util.SizeF); + method public void writeSparseArray(android.util.SparseArray); + method public void writeSparseBooleanArray(android.util.SparseBooleanArray); + method public void writeString(java.lang.String); + method public void writeStringArray(java.lang.String[]); + method public void writeStringList(java.util.List); + method public void writeStrongBinder(android.os.IBinder); + method public void writeStrongInterface(android.os.IInterface); + method public void writeTypedArray(T[], int); + method public void writeTypedList(java.util.List); + method public void writeTypedObject(T, int); + method public void writeValue(java.lang.Object); field public static final android.os.Parcelable.Creator STRING_CREATOR; } @@ -33019,7 +33121,7 @@ package android.os { field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; field public static final java.lang.String DISALLOW_CONFIG_DATE_TIME = "no_config_date_time"; field public static final java.lang.String DISALLOW_CONFIG_LOCALE = "no_config_locale"; - field public static final java.lang.String DISALLOW_CONFIG_LOCATION_MODE = "no_config_location_mode"; + field public static final java.lang.String DISALLOW_CONFIG_LOCATION = "no_config_location"; field public static final java.lang.String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks"; field public static final java.lang.String DISALLOW_CONFIG_SCREEN_TIMEOUT = "no_config_screen_timeout"; field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering"; @@ -34228,7 +34330,7 @@ package android.provider { } public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns { - method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]); + method public static android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]); field public static final android.net.Uri CONTENT_URI; } @@ -34357,7 +34459,7 @@ package android.provider { } public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns { - method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]); + method public static android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]); field public static final android.net.Uri CONTENT_URI; } @@ -34450,8 +34552,8 @@ package android.provider { } public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns { - method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long); - method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String); + method public static android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long); + method public static android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String); field public static final java.lang.String BEGIN = "begin"; field public static final android.net.Uri CONTENT_BY_DAY_URI; field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI; @@ -34466,7 +34568,7 @@ package android.provider { } public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns { - method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]); + method public static android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]); field public static final android.net.Uri CONTENT_URI; } @@ -34575,7 +34677,7 @@ package android.provider { method public static deprecated java.lang.Object decodeImProtocol(java.lang.String); method public static deprecated java.lang.String encodeCustomImProtocol(java.lang.String); method public static deprecated java.lang.String encodePredefinedImProtocol(int); - method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence); + method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence); field public static final deprecated java.lang.String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email"; field public static final deprecated java.lang.String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email"; field public static final deprecated android.net.Uri CONTENT_EMAIL_URI; @@ -34725,7 +34827,7 @@ package android.provider { } public static final deprecated class Contacts.Organizations implements android.provider.BaseColumns android.provider.Contacts.OrganizationColumns { - method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence); + method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence); field public static final deprecated java.lang.String CONTENT_DIRECTORY = "organizations"; field public static final deprecated android.net.Uri CONTENT_URI; field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "company, title, isprimary ASC"; @@ -34782,8 +34884,8 @@ package android.provider { } public static final deprecated class Contacts.Phones implements android.provider.BaseColumns android.provider.Contacts.PeopleColumns android.provider.Contacts.PhonesColumns { - method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]); - method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence); + method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]); + method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence); field public static final deprecated android.net.Uri CONTENT_FILTER_URL; field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone"; field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone"; @@ -34923,8 +35025,8 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.Email implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final java.lang.String ADDRESS = "data1"; field public static final android.net.Uri CONTENT_FILTER_URI; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2"; @@ -34944,7 +35046,7 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); method public static int getTypeResource(java.lang.Integer); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event"; field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; @@ -34975,10 +35077,10 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.Im implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getProtocolLabelResource(int); - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getProtocolLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im"; field public static final java.lang.String CUSTOM_PROTOCOL = "data6"; field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; @@ -35023,8 +35125,8 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.Organization implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final java.lang.String COMPANY = "data1"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization"; field public static final java.lang.String DEPARTMENT = "data5"; @@ -35042,8 +35144,8 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.Phone implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final android.net.Uri CONTENT_FILTER_URI; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2"; @@ -35088,8 +35190,8 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation"; field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; @@ -35112,8 +35214,8 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.SipAddress implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address"; field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX"; field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS"; @@ -35143,8 +35245,8 @@ package android.provider { } public static final class ContactsContract.CommonDataKinds.StructuredPostal implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins { - method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); - method public static final int getTypeLabelResource(int); + method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence); + method public static int getTypeLabelResource(int); field public static final java.lang.String CITY = "data7"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address_v2"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2"; @@ -35971,7 +36073,7 @@ package android.provider { public static final class MediaStore.Audio.Artists.Albums implements android.provider.MediaStore.Audio.AlbumColumns { ctor public MediaStore.Audio.Artists.Albums(); - method public static final android.net.Uri getContentUri(java.lang.String, long); + method public static android.net.Uri getContentUri(java.lang.String, long); } public static abstract interface MediaStore.Audio.AudioColumns implements android.provider.MediaStore.MediaColumns { @@ -36007,7 +36109,7 @@ package android.provider { public static final class MediaStore.Audio.Genres.Members implements android.provider.MediaStore.Audio.AudioColumns { ctor public MediaStore.Audio.Genres.Members(); - method public static final android.net.Uri getContentUri(java.lang.String, long); + method public static android.net.Uri getContentUri(java.lang.String, long); field public static final java.lang.String AUDIO_ID = "audio_id"; field public static final java.lang.String CONTENT_DIRECTORY = "members"; field public static final java.lang.String DEFAULT_SORT_ORDER = "title_key"; @@ -36043,8 +36145,8 @@ package android.provider { public static final class MediaStore.Audio.Playlists.Members implements android.provider.MediaStore.Audio.AudioColumns { ctor public MediaStore.Audio.Playlists.Members(); - method public static final android.net.Uri getContentUri(java.lang.String, long); - method public static final boolean moveItem(android.content.ContentResolver, long, int, int); + method public static android.net.Uri getContentUri(java.lang.String, long); + method public static boolean moveItem(android.content.ContentResolver, long, int, int); field public static final java.lang.String AUDIO_ID = "audio_id"; field public static final java.lang.String CONTENT_DIRECTORY = "members"; field public static final java.lang.String DEFAULT_SORT_ORDER = "play_order"; @@ -36067,7 +36169,7 @@ package android.provider { public static final class MediaStore.Files { ctor public MediaStore.Files(); method public static android.net.Uri getContentUri(java.lang.String); - method public static final android.net.Uri getContentUri(java.lang.String, long); + method public static android.net.Uri getContentUri(java.lang.String, long); } public static abstract interface MediaStore.Files.FileColumns implements android.provider.MediaStore.MediaColumns { @@ -36101,13 +36203,13 @@ package android.provider { public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns { ctor public MediaStore.Images.Media(); - method public static final android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException; + method public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException; method public static android.net.Uri getContentUri(java.lang.String); - method public static final java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException; - method public static final java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String); - method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]); - method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String); - method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String); + method public static java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException; + method public static java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String); + method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]); + method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String); + method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String); field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/image"; field public static final java.lang.String DEFAULT_SORT_ORDER = "bucket_display_name"; field public static final android.net.Uri EXTERNAL_CONTENT_URI; @@ -36152,7 +36254,7 @@ package android.provider { public static final class MediaStore.Video { ctor public MediaStore.Video(); - method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]); + method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]); field public static final java.lang.String DEFAULT_SORT_ORDER = "_display_name"; } @@ -36384,12 +36486,12 @@ package android.provider { method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException; method public static java.lang.String getString(android.content.ContentResolver, java.lang.String); method public static android.net.Uri getUriFor(java.lang.String); - method public static final deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String); + method public static deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String); method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float); method public static boolean putInt(android.content.ContentResolver, java.lang.String, int); method public static boolean putLong(android.content.ContentResolver, java.lang.String, long); method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String); - method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean); + method public static deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean); field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled"; field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled"; field public static final deprecated java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password"; @@ -38192,6 +38294,37 @@ package android.security { method public java.security.KeyPair getKeyPair(); } + public class ConfirmationAlreadyPresentingException extends java.lang.Exception { + ctor public ConfirmationAlreadyPresentingException(); + ctor public ConfirmationAlreadyPresentingException(java.lang.String); + } + + public abstract class ConfirmationCallback { + ctor public ConfirmationCallback(); + method public void onConfirmedByUser(byte[]); + method public void onDismissedByApplication(); + method public void onDismissedByUser(); + method public void onError(java.lang.Exception); + } + + public class ConfirmationDialog { + method public void cancelPrompt(); + method public static boolean isSupported(); + method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException; + } + + public static class ConfirmationDialog.Builder { + ctor public ConfirmationDialog.Builder(); + method public android.security.ConfirmationDialog build(android.content.Context); + method public android.security.ConfirmationDialog.Builder setExtraData(byte[]); + method public android.security.ConfirmationDialog.Builder setPromptText(java.lang.CharSequence); + } + + public class ConfirmationNotAvailableException extends java.lang.Exception { + ctor public ConfirmationNotAvailableException(); + ctor public ConfirmationNotAvailableException(java.lang.String); + } + public final class KeyChain { ctor public KeyChain(); method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String); @@ -38301,6 +38434,7 @@ package android.security.keystore { method public boolean isTrustedUserPresenceRequired(); method public boolean isUserAuthenticationRequired(); method public boolean isUserAuthenticationValidWhileOnBody(); + method public boolean isUserConfirmationRequired(); } public static final class KeyGenParameterSpec.Builder { @@ -38328,6 +38462,7 @@ package android.security.keystore { method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean); method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean); method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int); + method public android.security.keystore.KeyGenParameterSpec.Builder setUserConfirmationRequired(boolean); } public class KeyInfo implements java.security.spec.KeySpec { @@ -38349,6 +38484,7 @@ package android.security.keystore { method public boolean isUserAuthenticationRequired(); method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware(); method public boolean isUserAuthenticationValidWhileOnBody(); + method public boolean isUserConfirmationRequired(); } public class KeyNotYetValidException extends java.security.InvalidKeyException { @@ -38416,6 +38552,7 @@ package android.security.keystore { method public boolean isRandomizedEncryptionRequired(); method public boolean isUserAuthenticationRequired(); method public boolean isUserAuthenticationValidWhileOnBody(); + method public boolean isUserConfirmationRequired(); } public static final class KeyProtection.Builder { @@ -38434,6 +38571,7 @@ package android.security.keystore { method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int); + method public android.security.keystore.KeyProtection.Builder setUserConfirmationRequired(boolean); } public class StrongBoxUnavailableException extends java.security.ProviderException { @@ -38531,6 +38669,20 @@ package android.service.autofill { method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, java.util.regex.Pattern, android.widget.RemoteViews); } + public final class DateTransformation implements android.os.Parcelable android.service.autofill.Transformation { + ctor public DateTransformation(android.view.autofill.AutofillId, java.text.DateFormat); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class DateValueSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer { + ctor public DateValueSanitizer(java.text.DateFormat); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public final class FieldClassification { method public java.util.List getMatches(); } @@ -38700,6 +38852,7 @@ package android.service.autofill { public final class UserData implements android.os.Parcelable { method public int describeContents(); method public java.lang.String getFieldClassificationAlgorithm(); + method public java.lang.String getId(); method public static int getMaxFieldClassificationIdsSize(); method public static int getMaxUserDataSize(); method public static int getMaxValueLength(); @@ -38709,7 +38862,7 @@ package android.service.autofill { } public static final class UserData.Builder { - ctor public UserData.Builder(java.lang.String, java.lang.String); + ctor public UserData.Builder(java.lang.String, java.lang.String, java.lang.String); method public android.service.autofill.UserData.Builder add(java.lang.String, java.lang.String); method public android.service.autofill.UserData build(); method public android.service.autofill.UserData.Builder setFieldClassificationAlgorithm(java.lang.String, android.os.Bundle); @@ -40370,12 +40523,12 @@ package android.telecom { method public void playDtmfTone(char); method public void postDialContinue(boolean); method public void pullExternalCall(); - method public final void putExtras(android.os.Bundle); + method public void putExtras(android.os.Bundle); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); - method public final void removeExtras(java.util.List); - method public final void removeExtras(java.lang.String...); + method public void removeExtras(java.util.List); + method public void removeExtras(java.lang.String...); method public void respondToRttRequest(int, boolean); method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void sendRttRequest(); @@ -40944,23 +41097,23 @@ package android.telecom { public final class RemoteConference { method public void disconnect(); method public java.util.List getConferenceableConnections(); - method public final int getConnectionCapabilities(); - method public final int getConnectionProperties(); - method public final java.util.List getConnections(); + method public int getConnectionCapabilities(); + method public int getConnectionProperties(); + method public java.util.List getConnections(); method public android.telecom.DisconnectCause getDisconnectCause(); - method public final android.os.Bundle getExtras(); - method public final int getState(); + method public android.os.Bundle getExtras(); + method public int getState(); method public void hold(); method public void merge(); method public void playDtmfTone(char); - method public final void registerCallback(android.telecom.RemoteConference.Callback); - method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler); + method public void registerCallback(android.telecom.RemoteConference.Callback); + method public void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler); method public void separate(android.telecom.RemoteConnection); method public void setCallAudioState(android.telecom.CallAudioState); method public void stopDtmfTone(); method public void swap(); method public void unhold(); - method public final void unregisterCallback(android.telecom.RemoteConference.Callback); + method public void unregisterCallback(android.telecom.RemoteConference.Callback); } public static abstract class RemoteConference.Callback { @@ -40989,10 +41142,10 @@ package android.telecom { method public int getConnectionCapabilities(); method public int getConnectionProperties(); method public android.telecom.DisconnectCause getDisconnectCause(); - method public final android.os.Bundle getExtras(); + method public android.os.Bundle getExtras(); method public int getState(); method public android.telecom.StatusHints getStatusHints(); - method public final android.telecom.RemoteConnection.VideoProvider getVideoProvider(); + method public android.telecom.RemoteConnection.VideoProvider getVideoProvider(); method public int getVideoState(); method public void hold(); method public boolean isRingbackRequested(); @@ -41659,10 +41812,10 @@ package android.telephony { method public static android.telephony.MbmsDownloadSession create(android.content.Context, android.telephony.mbms.MbmsDownloadSessionCallback, android.os.Handler); method public static android.telephony.MbmsDownloadSession create(android.content.Context, android.telephony.mbms.MbmsDownloadSessionCallback, int, android.os.Handler); method public int download(android.telephony.mbms.DownloadRequest); - method public int getDownloadStatus(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo); method public java.io.File getTempFileRootDirectory(); method public java.util.List listPendingDownloads(); method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback, android.os.Handler); + method public void requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo); method public void requestUpdateFileServices(java.util.List); method public void resetDownloadKnowledge(android.telephony.mbms.DownloadRequest); method public void setTempFileRootDirectory(java.io.File); @@ -42445,11 +42598,11 @@ package android.telephony.gsm { } public final deprecated class SmsManager { - method public final deprecated java.util.ArrayList divideMessage(java.lang.String); - method public static final deprecated android.telephony.gsm.SmsManager getDefault(); - method public final deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); - method public final deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList, java.util.ArrayList, java.util.ArrayList); - method public final deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent); + method public deprecated java.util.ArrayList divideMessage(java.lang.String); + method public static deprecated android.telephony.gsm.SmsManager getDefault(); + method public deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); + method public deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList, java.util.ArrayList, java.util.ArrayList); + method public deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent); field public static final deprecated int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 field public static final deprecated int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final deprecated int RESULT_ERROR_NULL_PDU = 3; // 0x3 @@ -42591,6 +42744,7 @@ package android.telephony.mbms { public static class MbmsErrors.DownloadErrors { field public static final int ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT = 401; // 0x191 field public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402; // 0x192 + field public static final int ERROR_UNKNOWN_FILE_INFO = 403; // 0x193 } public static class MbmsErrors.GeneralErrors { @@ -44321,6 +44475,11 @@ package android.text.util { method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String); method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter); method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter); + method public static java.util.concurrent.Future addLinksAsync(android.widget.TextView, android.view.textclassifier.TextLinks.Options); + method public static java.util.concurrent.Future addLinksAsync(android.widget.TextView, android.view.textclassifier.TextLinks.Options, java.util.concurrent.Executor, java.util.function.Consumer); + method public static java.util.concurrent.Future addLinksAsync(android.text.Spannable, android.view.textclassifier.TextClassifier, android.view.textclassifier.TextLinks.Options); + method public static java.util.concurrent.Future addLinksAsync(android.text.Spannable, android.view.textclassifier.TextClassifier, int); + method public static java.util.concurrent.Future addLinksAsync(android.text.Spannable, android.view.textclassifier.TextClassifier, android.view.textclassifier.TextLinks.Options, java.util.concurrent.Executor, java.util.function.Consumer); field public static final int ALL = 15; // 0xf field public static final int EMAIL_ADDRESSES = 2; // 0x2 field public static final int MAP_ADDRESSES = 8; // 0x8 @@ -44819,6 +44978,7 @@ package android.util { field public static final int DENSITY_360 = 360; // 0x168 field public static final int DENSITY_400 = 400; // 0x190 field public static final int DENSITY_420 = 420; // 0x1a4 + field public static final int DENSITY_440 = 440; // 0x1b8 field public static final int DENSITY_560 = 560; // 0x230 field public static final int DENSITY_DEFAULT = 160; // 0xa0 field public static final int DENSITY_DEVICE_STABLE; @@ -46503,76 +46663,76 @@ package android.view { public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable { method public static java.lang.String actionToString(int); - method public final void addBatch(long, float, float, float, float, int); - method public final void addBatch(long, android.view.MotionEvent.PointerCoords[], int); + method public void addBatch(long, float, float, float, float, int); + method public void addBatch(long, android.view.MotionEvent.PointerCoords[], int); method public static int axisFromString(java.lang.String); method public static java.lang.String axisToString(int); - method public final int findPointerIndex(int); - method public final int getAction(); - method public final int getActionButton(); - method public final int getActionIndex(); - method public final int getActionMasked(); - method public final float getAxisValue(int); - method public final float getAxisValue(int, int); - method public final int getButtonState(); - method public final int getDeviceId(); - method public final long getDownTime(); - method public final int getEdgeFlags(); - method public final long getEventTime(); - method public final int getFlags(); - method public final float getHistoricalAxisValue(int, int); - method public final float getHistoricalAxisValue(int, int, int); - method public final long getHistoricalEventTime(int); - method public final float getHistoricalOrientation(int); - method public final float getHistoricalOrientation(int, int); - method public final void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords); - method public final float getHistoricalPressure(int); - method public final float getHistoricalPressure(int, int); - method public final float getHistoricalSize(int); - method public final float getHistoricalSize(int, int); - method public final float getHistoricalToolMajor(int); - method public final float getHistoricalToolMajor(int, int); - method public final float getHistoricalToolMinor(int); - method public final float getHistoricalToolMinor(int, int); - method public final float getHistoricalTouchMajor(int); - method public final float getHistoricalTouchMajor(int, int); - method public final float getHistoricalTouchMinor(int); - method public final float getHistoricalTouchMinor(int, int); - method public final float getHistoricalX(int); - method public final float getHistoricalX(int, int); - method public final float getHistoricalY(int); - method public final float getHistoricalY(int, int); - method public final int getHistorySize(); - method public final int getMetaState(); - method public final float getOrientation(); - method public final float getOrientation(int); - method public final void getPointerCoords(int, android.view.MotionEvent.PointerCoords); - method public final int getPointerCount(); - method public final int getPointerId(int); - method public final void getPointerProperties(int, android.view.MotionEvent.PointerProperties); - method public final float getPressure(); - method public final float getPressure(int); - method public final float getRawX(); - method public final float getRawY(); - method public final float getSize(); - method public final float getSize(int); - method public final int getSource(); - method public final float getToolMajor(); - method public final float getToolMajor(int); - method public final float getToolMinor(); - method public final float getToolMinor(int); - method public final int getToolType(int); - method public final float getTouchMajor(); - method public final float getTouchMajor(int); - method public final float getTouchMinor(); - method public final float getTouchMinor(int); - method public final float getX(); - method public final float getX(int); - method public final float getXPrecision(); - method public final float getY(); - method public final float getY(int); - method public final float getYPrecision(); - method public final boolean isButtonPressed(int); + method public int findPointerIndex(int); + method public int getAction(); + method public int getActionButton(); + method public int getActionIndex(); + method public int getActionMasked(); + method public float getAxisValue(int); + method public float getAxisValue(int, int); + method public int getButtonState(); + method public int getDeviceId(); + method public long getDownTime(); + method public int getEdgeFlags(); + method public long getEventTime(); + method public int getFlags(); + method public float getHistoricalAxisValue(int, int); + method public float getHistoricalAxisValue(int, int, int); + method public long getHistoricalEventTime(int); + method public float getHistoricalOrientation(int); + method public float getHistoricalOrientation(int, int); + method public void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords); + method public float getHistoricalPressure(int); + method public float getHistoricalPressure(int, int); + method public float getHistoricalSize(int); + method public float getHistoricalSize(int, int); + method public float getHistoricalToolMajor(int); + method public float getHistoricalToolMajor(int, int); + method public float getHistoricalToolMinor(int); + method public float getHistoricalToolMinor(int, int); + method public float getHistoricalTouchMajor(int); + method public float getHistoricalTouchMajor(int, int); + method public float getHistoricalTouchMinor(int); + method public float getHistoricalTouchMinor(int, int); + method public float getHistoricalX(int); + method public float getHistoricalX(int, int); + method public float getHistoricalY(int); + method public float getHistoricalY(int, int); + method public int getHistorySize(); + method public int getMetaState(); + method public float getOrientation(); + method public float getOrientation(int); + method public void getPointerCoords(int, android.view.MotionEvent.PointerCoords); + method public int getPointerCount(); + method public int getPointerId(int); + method public void getPointerProperties(int, android.view.MotionEvent.PointerProperties); + method public float getPressure(); + method public float getPressure(int); + method public float getRawX(); + method public float getRawY(); + method public float getSize(); + method public float getSize(int); + method public int getSource(); + method public float getToolMajor(); + method public float getToolMajor(int); + method public float getToolMinor(); + method public float getToolMinor(int); + method public int getToolType(int); + method public float getTouchMajor(); + method public float getTouchMajor(int); + method public float getTouchMinor(); + method public float getTouchMinor(int); + method public float getX(); + method public float getX(int); + method public float getXPrecision(); + method public float getY(); + method public float getY(int); + method public float getYPrecision(); + method public boolean isButtonPressed(int); method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int); method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int); method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int); @@ -46580,13 +46740,13 @@ package android.view { method public static android.view.MotionEvent obtain(long, long, int, float, float, int); method public static android.view.MotionEvent obtain(android.view.MotionEvent); method public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent); - method public final void offsetLocation(float, float); - method public final void recycle(); - method public final void setAction(int); - method public final void setEdgeFlags(int); - method public final void setLocation(float, float); - method public final void setSource(int); - method public final void transform(android.graphics.Matrix); + method public void offsetLocation(float, float); + method public void recycle(); + method public void setAction(int); + method public void setEdgeFlags(int); + method public void setLocation(float, float); + method public void setSource(int); + method public void transform(android.graphics.Matrix); method public void writeToParcel(android.os.Parcel, int); field public static final int ACTION_BUTTON_PRESS = 11; // 0xb field public static final int ACTION_BUTTON_RELEASE = 12; // 0xc @@ -47147,7 +47307,9 @@ package android.view { method public int getNextFocusRightId(); method public int getNextFocusUpId(); method public android.view.View.OnFocusChangeListener getOnFocusChangeListener(); + method public int getOutlineAmbientShadowColor(); method public android.view.ViewOutlineProvider getOutlineProvider(); + method public int getOutlineSpotShadowColor(); method public int getOverScrollMode(); method public android.view.ViewOverlay getOverlay(); method public int getPaddingBottom(); @@ -47275,6 +47437,7 @@ package android.view { method public boolean isTextDirectionResolved(); method public boolean isVerticalFadingEdgeEnabled(); method public boolean isVerticalScrollBarEnabled(); + method public boolean isVisibleToUserForAutofill(int); method public void jumpDrawablesToCurrentState(); method public android.view.View keyboardNavigationClusterSearch(android.view.View, int); method public void layout(int, int, int, int); @@ -47469,7 +47632,9 @@ package android.view { method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener); method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener); method public void setOnTouchListener(android.view.View.OnTouchListener); + method public void setOutlineAmbientShadowColor(int); method public void setOutlineProvider(android.view.ViewOutlineProvider); + method public void setOutlineSpotShadowColor(int); method public void setOverScrollMode(int); method public void setPadding(int, int, int, int); method public void setPaddingRelative(int, int, int, int); @@ -48304,9 +48469,9 @@ package android.view { method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); method public void addOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener); method public void addOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener); - method public final void dispatchOnDraw(); - method public final void dispatchOnGlobalLayout(); - method public final boolean dispatchOnPreDraw(); + method public void dispatchOnDraw(); + method public void dispatchOnGlobalLayout(); + method public boolean dispatchOnPreDraw(); method public boolean isAlive(); method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener); @@ -49561,6 +49726,7 @@ package android.view.autofill { method public java.util.List getAvailableFieldClassificationAlgorithms(); method public java.lang.String getDefaultFieldClassificationAlgorithm(); method public android.service.autofill.UserData getUserData(); + method public java.lang.String getUserDataId(); method public boolean hasEnabledAutofillServices(); method public boolean isAutofillSupported(); method public boolean isEnabled(); @@ -50016,7 +50182,8 @@ package android.view.inputmethod { package android.view.textclassifier { - public final class TextClassification { + public final class TextClassification implements android.os.Parcelable { + method public int describeContents(); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public int getEntityCount(); @@ -50030,6 +50197,8 @@ package android.view.textclassifier { method public java.lang.CharSequence getSecondaryLabel(int); method public java.lang.String getSignature(); method public java.lang.String getText(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; } public static final class TextClassification.Builder { @@ -50070,6 +50239,7 @@ package android.view.textclassifier { method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence, android.view.textclassifier.TextLinks.Options); method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence); method public default java.util.Collection getEntitiesForPreset(int); + method public default android.view.textclassifier.logging.Logger getLogger(android.view.textclassifier.logging.Logger.Config); method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options); method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int); method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList); @@ -50099,32 +50269,42 @@ package android.view.textclassifier { } public final class TextLinks implements android.os.Parcelable { - method public boolean apply(android.text.SpannableString, java.util.function.Function); method public int describeContents(); method public java.util.Collection getLinks(); method public void writeToParcel(android.os.Parcel, int); + field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0 + field public static final int APPLY_STRATEGY_REPLACE = 1; // 0x1 field public static final android.os.Parcelable.Creator CREATOR; + field public static final int STATUS_DIFFERENT_TEXT = 3; // 0x3 + field public static final int STATUS_LINKS_APPLIED = 0; // 0x0 + field public static final int STATUS_NO_LINKS_APPLIED = 2; // 0x2 + field public static final int STATUS_NO_LINKS_FOUND = 1; // 0x1 } public static final class TextLinks.Builder { ctor public TextLinks.Builder(java.lang.String); - method public android.view.textclassifier.TextLinks.Builder addLink(android.view.textclassifier.TextLinks.TextLink); + method public android.view.textclassifier.TextLinks.Builder addLink(int, int, java.util.Map); method public android.view.textclassifier.TextLinks build(); + method public android.view.textclassifier.TextLinks.Builder clearTextLinks(); } public static final class TextLinks.Options implements android.os.Parcelable { ctor public TextLinks.Options(); method public int describeContents(); + method public static android.view.textclassifier.TextLinks.Options fromLinkMask(int); + method public int getApplyStrategy(); method public android.os.LocaleList getDefaultLocales(); method public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig(); + method public java.util.function.Function getSpanFactory(); + method public android.view.textclassifier.TextLinks.Options setApplyStrategy(int); method public android.view.textclassifier.TextLinks.Options setDefaultLocales(android.os.LocaleList); method public android.view.textclassifier.TextLinks.Options setEntityConfig(android.view.textclassifier.TextClassifier.EntityConfig); + method public android.view.textclassifier.TextLinks.Options setSpanFactory(java.util.function.Function); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; } public static final class TextLinks.TextLink implements android.os.Parcelable { - ctor public TextLinks.TextLink(java.lang.String, int, int, java.util.Map); method public int describeContents(); method public float getConfidenceScore(java.lang.String); method public int getEnd(); @@ -50135,13 +50315,22 @@ package android.view.textclassifier { field public static final android.os.Parcelable.Creator CREATOR; } - public final class TextSelection { + public static class TextLinks.TextLinkSpan extends android.text.style.ClickableSpan { + ctor public TextLinks.TextLinkSpan(android.view.textclassifier.TextLinks.TextLink); + method public final android.view.textclassifier.TextLinks.TextLink getTextLink(); + method public void onClick(android.view.View); + } + + public final class TextSelection implements android.os.Parcelable { + method public int describeContents(); method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); method public int getEntityCount(); method public int getSelectionEndIndex(); method public int getSelectionStartIndex(); method public java.lang.String getSignature(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; } public static final class TextSelection.Builder { @@ -50162,6 +50351,75 @@ package android.view.textclassifier { } +package android.view.textclassifier.logging { + + public abstract class Logger { + ctor public Logger(android.view.textclassifier.logging.Logger.Config); + method public java.text.BreakIterator getTokenIterator(java.util.Locale); + method public boolean isSmartSelection(java.lang.String); + method public final void logSelectionActionEvent(int, int, int); + method public final void logSelectionActionEvent(int, int, int, android.view.textclassifier.TextClassification); + method public final void logSelectionModifiedEvent(int, int); + method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextClassification); + method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextSelection); + method public final void logSelectionStartedEvent(int); + method public abstract void writeEvent(android.view.textclassifier.logging.SelectionEvent); + field public static final int OUT_OF_BOUNDS = 2147483647; // 0x7fffffff + field public static final int OUT_OF_BOUNDS_NEGATIVE = -2147483648; // 0x80000000 + field public static final java.lang.String WIDGET_CUSTOM_EDITTEXT = "customedit"; + field public static final java.lang.String WIDGET_CUSTOM_TEXTVIEW = "customview"; + field public static final java.lang.String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview"; + field public static final java.lang.String WIDGET_EDITTEXT = "edittext"; + field public static final java.lang.String WIDGET_EDIT_WEBVIEW = "edit-webview"; + field public static final java.lang.String WIDGET_TEXTVIEW = "textview"; + field public static final java.lang.String WIDGET_UNKNOWN = "unknown"; + field public static final java.lang.String WIDGET_UNSELECTABLE_TEXTVIEW = "nosel-textview"; + field public static final java.lang.String WIDGET_WEBVIEW = "webview"; + } + + public static final class Logger.Config { + ctor public Logger.Config(android.content.Context, java.lang.String, java.lang.String); + method public java.lang.String getPackageName(); + method public java.lang.String getWidgetType(); + method public java.lang.String getWidgetVersion(); + } + + public final class SelectionEvent { + method public long getDurationSincePreviousEvent(); + method public long getDurationSinceSessionStart(); + method public int getEnd(); + method public java.lang.String getEntityType(); + method public int getEventIndex(); + method public long getEventTime(); + method public int getEventType(); + method public java.lang.String getPackageName(); + method public java.lang.String getSessionId(); + method public java.lang.String getSignature(); + method public int getSmartEnd(); + method public int getSmartStart(); + method public int getStart(); + method public java.lang.String getWidgetType(); + method public java.lang.String getWidgetVersion(); + field public static final int ACTION_ABANDON = 107; // 0x6b + field public static final int ACTION_COPY = 101; // 0x65 + field public static final int ACTION_CUT = 103; // 0x67 + field public static final int ACTION_DRAG = 106; // 0x6a + field public static final int ACTION_OTHER = 108; // 0x6c + field public static final int ACTION_OVERTYPE = 100; // 0x64 + field public static final int ACTION_PASTE = 102; // 0x66 + field public static final int ACTION_RESET = 201; // 0xc9 + field public static final int ACTION_SELECT_ALL = 200; // 0xc8 + field public static final int ACTION_SHARE = 104; // 0x68 + field public static final int ACTION_SMART_SHARE = 105; // 0x69 + field public static final int EVENT_AUTO_SELECTION = 5; // 0x5 + field public static final int EVENT_SELECTION_MODIFIED = 2; // 0x2 + field public static final int EVENT_SELECTION_STARTED = 1; // 0x1 + field public static final int EVENT_SMART_SELECTION_MULTI = 4; // 0x4 + field public static final int EVENT_SMART_SELECTION_SINGLE = 3; // 0x3 + } + +} + package android.view.textservice { public final class SentenceSuggestionsInfo implements android.os.Parcelable { @@ -50474,7 +50732,7 @@ package android.webkit { ctor public URLUtil(); method public static java.lang.String composeSearchUrl(java.lang.String, java.lang.String, java.lang.String); method public static byte[] decode(byte[]) throws java.lang.IllegalArgumentException; - method public static final java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String); + method public static java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String); method public static java.lang.String guessUrl(java.lang.String); method public static boolean isAboutUrl(java.lang.String); method public static boolean isAssetUrl(java.lang.String); @@ -52286,6 +52544,7 @@ package android.widget { ctor public Magnifier(android.view.View); method public void dismiss(); method public void show(float, float); + method public void update(); } public class MediaController extends android.widget.FrameLayout { @@ -55542,7 +55801,7 @@ package java.lang { } public static final class Character.UnicodeBlock extends java.lang.Character.Subset { - method public static final java.lang.Character.UnicodeBlock forName(java.lang.String); + method public static java.lang.Character.UnicodeBlock forName(java.lang.String); method public static java.lang.Character.UnicodeBlock of(char); method public static java.lang.Character.UnicodeBlock of(int); field public static final java.lang.Character.UnicodeBlock AEGEAN_NUMBERS; @@ -55769,7 +56028,7 @@ package java.lang { } public static final class Character.UnicodeScript extends java.lang.Enum { - method public static final java.lang.Character.UnicodeScript forName(java.lang.String); + method public static java.lang.Character.UnicodeScript forName(java.lang.String); method public static java.lang.Character.UnicodeScript of(int); method public static java.lang.Character.UnicodeScript valueOf(java.lang.String); method public static final java.lang.Character.UnicodeScript[] values(); @@ -57432,6 +57691,7 @@ package java.lang.ref { method public boolean enqueue(); method public T get(); method public boolean isEnqueued(); + method public static void reachabilityFence(java.lang.Object); } public class ReferenceQueue { @@ -58584,8 +58844,8 @@ package java.net { ctor public URL(java.net.URL, java.lang.String) throws java.net.MalformedURLException; ctor public URL(java.net.URL, java.lang.String, java.net.URLStreamHandler) throws java.net.MalformedURLException; method public java.lang.String getAuthority(); - method public final java.lang.Object getContent() throws java.io.IOException; - method public final java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException; + method public java.lang.Object getContent() throws java.io.IOException; + method public java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException; method public int getDefaultPort(); method public java.lang.String getFile(); method public java.lang.String getHost(); @@ -58598,7 +58858,7 @@ package java.net { method public synchronized int hashCode(); method public java.net.URLConnection openConnection() throws java.io.IOException; method public java.net.URLConnection openConnection(java.net.Proxy) throws java.io.IOException; - method public final java.io.InputStream openStream() throws java.io.IOException; + method public java.io.InputStream openStream() throws java.io.IOException; method public boolean sameFile(java.net.URL); method public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory); method public java.lang.String toExternalForm(); @@ -63254,13 +63514,13 @@ package java.text { method public int getOffset(); method public int next(); method public int previous(); - method public static final int primaryOrder(int); + method public static int primaryOrder(int); method public void reset(); - method public static final short secondaryOrder(int); + method public static short secondaryOrder(int); method public void setOffset(int); method public void setText(java.lang.String); method public void setText(java.text.CharacterIterator); - method public static final short tertiaryOrder(int); + method public static short tertiaryOrder(int); field public static final int NULLORDER = -1; // 0xffffffff } @@ -64541,7 +64801,7 @@ package java.time.chrono { } public final class HijrahDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster { - method public final java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); + method public java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); method public static java.time.chrono.HijrahDate from(java.time.temporal.TemporalAccessor); method public java.time.chrono.HijrahChronology getChronology(); method public java.time.chrono.HijrahEra getEra(); @@ -64628,7 +64888,7 @@ package java.time.chrono { } public final class JapaneseDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster { - method public final java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); + method public java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); method public static java.time.chrono.JapaneseDate from(java.time.temporal.TemporalAccessor); method public java.time.chrono.JapaneseChronology getChronology(); method public java.time.chrono.JapaneseEra getEra(); @@ -64684,7 +64944,7 @@ package java.time.chrono { } public final class MinguoDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster { - method public final java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); + method public java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); method public static java.time.chrono.MinguoDate from(java.time.temporal.TemporalAccessor); method public java.time.chrono.MinguoChronology getChronology(); method public java.time.chrono.MinguoEra getEra(); @@ -64737,7 +64997,7 @@ package java.time.chrono { } public final class ThaiBuddhistDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster { - method public final java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); + method public java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime); method public static java.time.chrono.ThaiBuddhistDate from(java.time.temporal.TemporalAccessor); method public java.time.chrono.ThaiBuddhistChronology getChronology(); method public java.time.chrono.ThaiBuddhistEra getEra(); @@ -64789,8 +65049,8 @@ package java.time.format { method public T parse(java.lang.CharSequence, java.time.temporal.TemporalQuery); method public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery...); method public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition); - method public static final java.time.temporal.TemporalQuery parsedExcessDays(); - method public static final java.time.temporal.TemporalQuery parsedLeapSecond(); + method public static java.time.temporal.TemporalQuery parsedExcessDays(); + method public static java.time.temporal.TemporalQuery parsedLeapSecond(); method public java.text.Format toFormat(); method public java.text.Format toFormat(java.time.temporal.TemporalQuery); method public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology); @@ -66239,15 +66499,15 @@ package java.util { method public java.lang.String getCountry(); method public static java.util.Locale getDefault(); method public static java.util.Locale getDefault(java.util.Locale.Category); - method public final java.lang.String getDisplayCountry(); + method public java.lang.String getDisplayCountry(); method public java.lang.String getDisplayCountry(java.util.Locale); - method public final java.lang.String getDisplayLanguage(); + method public java.lang.String getDisplayLanguage(); method public java.lang.String getDisplayLanguage(java.util.Locale); - method public final java.lang.String getDisplayName(); + method public java.lang.String getDisplayName(); method public java.lang.String getDisplayName(java.util.Locale); method public java.lang.String getDisplayScript(); method public java.lang.String getDisplayScript(java.util.Locale); - method public final java.lang.String getDisplayVariant(); + method public java.lang.String getDisplayVariant(); method public java.lang.String getDisplayVariant(java.util.Locale); method public java.lang.String getExtension(char); method public java.util.Set getExtensionKeys(); @@ -66268,7 +66528,6 @@ package java.util { method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale); method public java.util.Locale stripExtensions(); method public java.lang.String toLanguageTag(); - method public final java.lang.String toString(); field public static final java.util.Locale CANADA; field public static final java.util.Locale CANADA_FRENCH; field public static final java.util.Locale CHINA; @@ -70454,7 +70713,6 @@ package javax.crypto { public class ExemptionMechanism { ctor protected ExemptionMechanism(javax.crypto.ExemptionMechanismSpi, java.security.Provider, java.lang.String); - method protected void finalize(); method public final byte[] genExemptionBlob() throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException; method public final int genExemptionBlob(byte[]) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException; method public final int genExemptionBlob(byte[], int) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException; diff --git a/api/system-current.txt b/api/system-current.txt index 396ff1a9aa334b1938a50c3fae5fcf0ad0a80029..2d3b65a19b26236300da322562692310a421916b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -29,6 +29,9 @@ package android { field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE"; field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"; field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE"; + field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE"; + field public static final java.lang.String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE"; + field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE"; field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT"; field public static final java.lang.String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE"; field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED"; @@ -772,6 +775,7 @@ package android.content { public abstract class Context { method public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle); method public abstract android.content.Context createCredentialProtectedStorageContext(); + method public android.content.Context createPackageContextAsUser(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract java.io.File getPreloadsFileCache(); method public abstract boolean isCredentialProtectedStorage(); method public abstract void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle); @@ -821,8 +825,16 @@ package android.content { field public static final java.lang.String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED"; field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST"; field public static final java.lang.String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS"; + field public static final java.lang.String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE"; field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET"; + field public static final java.lang.String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION"; field public static final java.lang.String EXTRA_INSTANT_APP_BUNDLES = "android.intent.extra.INSTANT_APP_BUNDLES"; + field public static final java.lang.String EXTRA_INSTANT_APP_EXTRAS = "android.intent.extra.INSTANT_APP_EXTRAS"; + field public static final java.lang.String EXTRA_INSTANT_APP_FAILURE = "android.intent.extra.INSTANT_APP_FAILURE"; + field public static final java.lang.String EXTRA_INSTANT_APP_HOSTNAME = "android.intent.extra.INSTANT_APP_HOSTNAME"; + field public static final java.lang.String EXTRA_INSTANT_APP_SUCCESS = "android.intent.extra.INSTANT_APP_SUCCESS"; + field public static final java.lang.String EXTRA_INSTANT_APP_TOKEN = "android.intent.extra.INSTANT_APP_TOKEN"; + field public static final java.lang.String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE"; field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID"; field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES"; field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME"; @@ -830,6 +842,7 @@ package android.content { field public static final java.lang.String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK"; field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED"; field public static final java.lang.String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP"; + field public static final java.lang.String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE"; } public class IntentFilter implements android.os.Parcelable { @@ -842,7 +855,9 @@ package android.content { package android.content.pm { public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + method public boolean isInstantApp(); field public java.lang.String credentialProtectedDataDir; + field public int targetSandboxVersion; } public final class InstantAppInfo implements android.os.Parcelable { @@ -1128,6 +1143,15 @@ package android.hardware.camera2.params { package android.hardware.display { + public final class AmbientBrightnessDayStats implements android.os.Parcelable { + method public int describeContents(); + method public float[] getBucketBoundaries(); + method public java.time.LocalDate getLocalDate(); + method public float[] getStats(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public final class BrightnessChangeEvent implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -1135,11 +1159,14 @@ package android.hardware.display { field public final float batteryLevel; field public final float brightness; field public final int colorTemperature; + field public final boolean isDefaultBrightnessConfig; + field public final boolean isUserSetBrightness; field public final float lastBrightness; field public final long[] luxTimestamps; field public final float[] luxValues; field public final boolean nightMode; field public final java.lang.String packageName; + field public final float powerBrightnessFactor; field public final long timeStamp; } @@ -1997,6 +2024,7 @@ package android.hardware.radio { method public int describeContents(); method public android.hardware.radio.RadioManager.BandDescriptor[] getBands(); method public int getClassId(); + method public java.util.Map getDabFrequencyTable(); method public int getId(); method public java.lang.String getImplementor(); method public int getNumAudioSources(); @@ -2488,6 +2516,7 @@ package android.media { method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException; method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException; method public int requestAudioFocus(android.media.AudioFocusRequest, android.media.audiopolicy.AudioPolicy); + method public void setFocusRequestResult(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy); method public void unregisterAudioPolicyAsync(android.media.audiopolicy.AudioPolicy); field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1 field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4 @@ -2679,10 +2708,10 @@ package android.media.soundtrigger { package android.media.tv { public final class TvContentRatingSystemInfo implements android.os.Parcelable { - method public static final android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo); + method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo); method public int describeContents(); - method public final android.net.Uri getXmlUri(); - method public final boolean isSystemDefined(); + method public android.net.Uri getXmlUri(); + method public boolean isSystemDefined(); method public void writeToParcel(android.os.Parcel, int); } @@ -4094,6 +4123,7 @@ package android.provider { public static final class Settings.Global extends android.provider.Settings.NameValueTable { method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean); method public static void resetToDefaults(android.content.ContentResolver, java.lang.String); + field public static final java.lang.String AUTOFILL_COMPAT_ALLOWED_PACKAGES = "autofill_compat_allowed_packages"; field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update"; field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on"; field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess"; @@ -4464,6 +4494,24 @@ package android.service.settings.suggestions { } +package android.service.textclassifier { + + public abstract class TextClassifierService extends android.app.Service { + ctor public TextClassifierService(); + method public final android.os.IBinder onBind(android.content.Intent); + method public abstract void onClassifyText(java.lang.CharSequence, int, int, android.view.textclassifier.TextClassification.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback); + method public abstract void onGenerateLinks(java.lang.CharSequence, android.view.textclassifier.TextLinks.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback); + method public abstract void onSuggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback); + field public static final java.lang.String SERVICE_INTERFACE = "android.service.textclassifier.TextClassifierService"; + } + + public static abstract interface TextClassifierService.Callback { + method public abstract void onFailure(java.lang.CharSequence); + method public abstract void onSuccess(T); + } + +} + package android.service.trust { public class TrustAgentService extends android.app.Service { @@ -4645,15 +4693,15 @@ package android.telecom { } public final deprecated class Phone { - method public final void addListener(android.telecom.Phone.Listener); - method public final boolean canAddCall(); - method public final deprecated android.telecom.AudioState getAudioState(); - method public final android.telecom.CallAudioState getCallAudioState(); - method public final java.util.List getCalls(); - method public final void removeListener(android.telecom.Phone.Listener); + method public void addListener(android.telecom.Phone.Listener); + method public boolean canAddCall(); + method public deprecated android.telecom.AudioState getAudioState(); + method public android.telecom.CallAudioState getCallAudioState(); + method public java.util.List getCalls(); + method public void removeListener(android.telecom.Phone.Listener); method public void requestBluetoothAudio(java.lang.String); - method public final void setAudioRoute(int); - method public final void setMuted(boolean); + method public void setAudioRoute(int); + method public void setMuted(boolean); } public static abstract class Phone.Listener { @@ -5101,16 +5149,669 @@ package android.telephony.data { package android.telephony.ims { + public final class ImsCallForwardInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getCondition(); + method public java.lang.String getNumber(); + method public int getServiceClass(); + method public int getStatus(); + method public int getTimeSeconds(); + method public int getToA(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class ImsCallProfile implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.String getCallExtra(java.lang.String); + method public java.lang.String getCallExtra(java.lang.String, java.lang.String); + method public boolean getCallExtraBoolean(java.lang.String); + method public boolean getCallExtraBoolean(java.lang.String, boolean); + method public int getCallExtraInt(java.lang.String); + method public int getCallExtraInt(java.lang.String, int); + method public android.os.Bundle getCallExtras(); + method public int getCallType(); + method public static int getCallTypeFromVideoState(int); + method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); + method public int getRestrictCause(); + method public int getServiceType(); + method public static int getVideoStateFromCallType(int); + method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile); + method public boolean isVideoCall(); + method public boolean isVideoPaused(); + method public static int presentationToOir(int); + method public void setCallExtra(java.lang.String, java.lang.String); + method public void setCallExtraBoolean(java.lang.String, boolean); + method public void setCallExtraInt(java.lang.String, int); + method public void updateCallExtras(android.telephony.ims.ImsCallProfile); + method public void updateCallType(android.telephony.ims.ImsCallProfile); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2 + field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3 + field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0 + field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1 + field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3 + field public static final int CALL_TYPE_VOICE = 2; // 0x2 + field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1 + field public static final int CALL_TYPE_VS = 8; // 0x8 + field public static final int CALL_TYPE_VS_RX = 10; // 0xa + field public static final int CALL_TYPE_VS_TX = 9; // 0x9 + field public static final int CALL_TYPE_VT = 4; // 0x4 + field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7 + field public static final int CALL_TYPE_VT_RX = 6; // 0x6 + field public static final int CALL_TYPE_VT_TX = 5; // 0x5 + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DIALSTRING_NORMAL = 0; // 0x0 + field public static final int DIALSTRING_SS_CONF = 1; // 0x1 + field public static final int DIALSTRING_USSD = 2; // 0x2 + field public static final java.lang.String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo"; + field public static final java.lang.String EXTRA_CALL_RAT_TYPE = "CallRadioTech"; + field public static final java.lang.String EXTRA_CHILD_NUMBER = "ChildNum"; + field public static final java.lang.String EXTRA_CNA = "cna"; + field public static final java.lang.String EXTRA_CNAP = "cnap"; + field public static final java.lang.String EXTRA_CODEC = "Codec"; + field public static final java.lang.String EXTRA_DIALSTRING = "dialstring"; + field public static final java.lang.String EXTRA_DISPLAY_TEXT = "DisplayText"; + field public static final java.lang.String EXTRA_IS_CALL_PULL = "CallPull"; + field public static final java.lang.String EXTRA_OI = "oi"; + field public static final java.lang.String EXTRA_OIR = "oir"; + field public static final java.lang.String EXTRA_REMOTE_URI = "remote_uri"; + field public static final java.lang.String EXTRA_USSD = "ussd"; + field public static final int OIR_DEFAULT = 0; // 0x0 + field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2 + field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4 + field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1 + field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3 + field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2 + field public static final int SERVICE_TYPE_NONE = 0; // 0x0 + field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1 + } + + public class ImsCallSessionListener { + method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState); + method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo); + method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo); + method public void callSessionHeld(android.telephony.ims.ImsCallProfile); + method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionInitiated(android.telephony.ims.ImsCallProfile); + method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionInviteParticipantsRequestDelivered(); + method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionMayHandover(int, int); + method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase); + method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionMultipartyStateChanged(boolean); + method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile); + method public void callSessionRemoveParticipantsRequestDelivered(); + method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionResumed(android.telephony.ims.ImsCallProfile); + method public void callSessionRttMessageReceived(java.lang.String); + method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionRttModifyResponseReceived(int); + method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification); + method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo); + method public void callSessionTtyModeReceived(int); + method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionUpdated(android.telephony.ims.ImsCallProfile); + method public void callSessionUssdMessageReceived(int, java.lang.String); + } + + public final class ImsConferenceState implements android.os.Parcelable { + method public int describeContents(); + method public static int getConnectionStateForStatus(java.lang.String); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final java.lang.String DISPLAY_TEXT = "display-text"; + field public static final java.lang.String ENDPOINT = "endpoint"; + field public static final java.lang.String SIP_STATUS_CODE = "sipstatuscode"; + field public static final java.lang.String STATUS = "status"; + field public static final java.lang.String STATUS_ALERTING = "alerting"; + field public static final java.lang.String STATUS_CONNECTED = "connected"; + field public static final java.lang.String STATUS_CONNECT_FAIL = "connect-fail"; + field public static final java.lang.String STATUS_DIALING_IN = "dialing-in"; + field public static final java.lang.String STATUS_DIALING_OUT = "dialing-out"; + field public static final java.lang.String STATUS_DISCONNECTED = "disconnected"; + field public static final java.lang.String STATUS_DISCONNECTING = "disconnecting"; + field public static final java.lang.String STATUS_MUTED_VIA_FOCUS = "muted-via-focus"; + field public static final java.lang.String STATUS_ON_HOLD = "on-hold"; + field public static final java.lang.String STATUS_PENDING = "pending"; + field public static final java.lang.String STATUS_SEND_ONLY = "sendonly"; + field public static final java.lang.String STATUS_SEND_RECV = "sendrecv"; + field public static final java.lang.String USER = "user"; + field public final java.util.HashMap mParticipants; + } + + public final class ImsExternalCallState implements android.os.Parcelable { + method public int describeContents(); + method public android.net.Uri getAddress(); + method public int getCallId(); + method public int getCallState(); + method public int getCallType(); + method public boolean isCallHeld(); + method public boolean isCallPullable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_STATE_CONFIRMED = 1; // 0x1 + field public static final int CALL_STATE_TERMINATED = 2; // 0x2 + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class ImsReasonInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getCode(); + method public int getExtraCode(); + method public java.lang.String getExtraMessage(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CODE_ACCESS_CLASS_BLOCKED = 1512; // 0x5e8 + field public static final int CODE_ANSWERED_ELSEWHERE = 1014; // 0x3f6 + field public static final int CODE_BLACKLISTED_CALL_ID = 506; // 0x1fa + field public static final int CODE_CALL_BARRED = 240; // 0xf0 + field public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100; // 0x44c + field public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; // 0x3f8 + field public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; // 0x3f7 + field public static final int CODE_DATA_DISABLED = 1406; // 0x57e + field public static final int CODE_DATA_LIMIT_REACHED = 1405; // 0x57d + field public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246; // 0xf6 + field public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247; // 0xf7 + field public static final int CODE_DIAL_MODIFIED_TO_SS = 245; // 0xf5 + field public static final int CODE_DIAL_MODIFIED_TO_USSD = 244; // 0xf4 + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248; // 0xf8 + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249; // 0xf9 + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250; // 0xfa + field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251; // 0xfb + field public static final int CODE_ECBM_NOT_SUPPORTED = 901; // 0x385 + field public static final int CODE_EMERGENCY_PERM_FAILURE = 364; // 0x16c + field public static final int CODE_EMERGENCY_TEMP_FAILURE = 363; // 0x16b + field public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400; // 0x578 + field public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402; // 0x57a + field public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401; // 0x579 + field public static final int CODE_FDN_BLOCKED = 241; // 0xf1 + field public static final int CODE_IKEV2_AUTH_FAILURE = 1408; // 0x580 + field public static final int CODE_IMEI_NOT_ACCEPTED = 243; // 0xf3 + field public static final int CODE_IWLAN_DPD_FAILURE = 1300; // 0x514 + field public static final int CODE_LOCAL_CALL_BUSY = 142; // 0x8e + field public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146; // 0x92 + field public static final int CODE_LOCAL_CALL_DECLINE = 143; // 0x8f + field public static final int CODE_LOCAL_CALL_EXCEEDED = 141; // 0x8d + field public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145; // 0x91 + field public static final int CODE_LOCAL_CALL_TERMINATED = 148; // 0x94 + field public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144; // 0x90 + field public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147; // 0x93 + field public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108; // 0x6c + field public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149; // 0x95 + field public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101; // 0x65 + field public static final int CODE_LOCAL_ILLEGAL_STATE = 102; // 0x66 + field public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106; // 0x6a + field public static final int CODE_LOCAL_INTERNAL_ERROR = 103; // 0x67 + field public static final int CODE_LOCAL_LOW_BATTERY = 112; // 0x70 + field public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124; // 0x7c + field public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122; // 0x7a + field public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121; // 0x79 + field public static final int CODE_LOCAL_NETWORK_ROAMING = 123; // 0x7b + field public static final int CODE_LOCAL_NOT_REGISTERED = 132; // 0x84 + field public static final int CODE_LOCAL_NO_PENDING_CALL = 107; // 0x6b + field public static final int CODE_LOCAL_POWER_OFF = 111; // 0x6f + field public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131; // 0x83 + field public static final int CODE_LOW_BATTERY = 505; // 0x1f9 + field public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403; // 0x57b + field public static final int CODE_MEDIA_INIT_FAILED = 401; // 0x191 + field public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403; // 0x193 + field public static final int CODE_MEDIA_NO_DATA = 402; // 0x192 + field public static final int CODE_MEDIA_UNSPECIFIED = 404; // 0x194 + field public static final int CODE_MULTIENDPOINT_NOT_SUPPORTED = 902; // 0x386 + field public static final int CODE_NETWORK_DETACH = 1513; // 0x5e9 + field public static final int CODE_NETWORK_REJECT = 1504; // 0x5e0 + field public static final int CODE_NETWORK_RESP_TIMEOUT = 1503; // 0x5df + field public static final int CODE_NO_VALID_SIM = 1501; // 0x5dd + field public static final int CODE_OEM_CAUSE_1 = 61441; // 0xf001 + field public static final int CODE_OEM_CAUSE_10 = 61450; // 0xf00a + field public static final int CODE_OEM_CAUSE_11 = 61451; // 0xf00b + field public static final int CODE_OEM_CAUSE_12 = 61452; // 0xf00c + field public static final int CODE_OEM_CAUSE_13 = 61453; // 0xf00d + field public static final int CODE_OEM_CAUSE_14 = 61454; // 0xf00e + field public static final int CODE_OEM_CAUSE_15 = 61455; // 0xf00f + field public static final int CODE_OEM_CAUSE_2 = 61442; // 0xf002 + field public static final int CODE_OEM_CAUSE_3 = 61443; // 0xf003 + field public static final int CODE_OEM_CAUSE_4 = 61444; // 0xf004 + field public static final int CODE_OEM_CAUSE_5 = 61445; // 0xf005 + field public static final int CODE_OEM_CAUSE_6 = 61446; // 0xf006 + field public static final int CODE_OEM_CAUSE_7 = 61447; // 0xf007 + field public static final int CODE_OEM_CAUSE_8 = 61448; // 0xf008 + field public static final int CODE_OEM_CAUSE_9 = 61449; // 0xf009 + field public static final int CODE_RADIO_ACCESS_FAILURE = 1505; // 0x5e1 + field public static final int CODE_RADIO_INTERNAL_ERROR = 1502; // 0x5de + field public static final int CODE_RADIO_LINK_FAILURE = 1506; // 0x5e2 + field public static final int CODE_RADIO_LINK_LOST = 1507; // 0x5e3 + field public static final int CODE_RADIO_OFF = 1500; // 0x5dc + field public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511; // 0x5e7 + field public static final int CODE_RADIO_RELEASE_NORMAL = 1510; // 0x5e6 + field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5 + field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4 + field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8 + field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c + field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea + field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151 + field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b + field public static final int CODE_SIP_BUSY = 338; // 0x152 + field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156 + field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c + field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a + field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154 + field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d + field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155 + field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e + field public static final int CODE_SIP_REDIRECTED = 321; // 0x141 + field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153 + field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f + field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162 + field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f + field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161 + field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160 + field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150 + field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169 + field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2 + field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1 + field public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; // 0x4b3 + field public static final int CODE_TIMEOUT_1XX_WAITING = 201; // 0xc9 + field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca + field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb + field public static final int CODE_UNSPECIFIED = 0; // 0x0 + field public static final int CODE_USER_DECLINE = 504; // 0x1f8 + field public static final int CODE_USER_IGNORE = 503; // 0x1f7 + field public static final int CODE_USER_NOANSWER = 502; // 0x1f6 + field public static final int CODE_USER_TERMINATED = 501; // 0x1f5 + field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe + field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335 + field public static final int CODE_UT_NETWORK_ERROR = 804; // 0x324 + field public static final int CODE_UT_NOT_SUPPORTED = 801; // 0x321 + field public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803; // 0x323 + field public static final int CODE_UT_SERVICE_UNAVAILABLE = 802; // 0x322 + field public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822; // 0x336 + field public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825; // 0x339 + field public static final int CODE_UT_SS_MODIFIED_TO_SS = 824; // 0x338 + field public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823; // 0x337 + field public static final int CODE_WIFI_LOST = 1407; // 0x57f + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3 + field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1 + field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2 + field public static final java.lang.String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service"; + } + public class ImsService extends android.app.Service { ctor public ImsService(); + method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); + method public android.telephony.ims.feature.RcsFeature createRcsFeature(int); + method public void disableIms(int); + method public void enableIms(int); + method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; + method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); + method public void readyForFeatureCreation(); + } + + public final class ImsSsData implements android.os.Parcelable { + ctor public ImsSsData(); + method public int describeContents(); + method public boolean isTypeBarring(); + method public boolean isTypeCf(); + method public boolean isTypeClip(); + method public boolean isTypeClir(); + method public boolean isTypeColp(); + method public boolean isTypeColr(); + method public boolean isTypeCw(); + method public boolean isTypeIcb(); + method public boolean isTypeInterrogation(); + method public boolean isTypeUnConditional(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int SS_ACTIVATION = 0; // 0x0 + field public static final int SS_ALL_BARRING = 18; // 0x12 + field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3 + field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5 + field public static final int SS_ALL_TELESEVICES = 1; // 0x1 + field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0 + field public static final int SS_BAIC = 16; // 0x10 + field public static final int SS_BAIC_ROAMING = 17; // 0x11 + field public static final int SS_BAOC = 13; // 0xd + field public static final int SS_BAOIC = 14; // 0xe + field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf + field public static final int SS_CFU = 0; // 0x0 + field public static final int SS_CFUT = 6; // 0x6 + field public static final int SS_CF_ALL = 4; // 0x4 + field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5 + field public static final int SS_CF_BUSY = 1; // 0x1 + field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3 + field public static final int SS_CF_NO_REPLY = 2; // 0x2 + field public static final int SS_CLIP = 7; // 0x7 + field public static final int SS_CLIR = 8; // 0x8 + field public static final int SS_CNAP = 11; // 0xb + field public static final int SS_COLP = 9; // 0x9 + field public static final int SS_COLR = 10; // 0xa + field public static final int SS_DEACTIVATION = 1; // 0x1 + field public static final int SS_ERASURE = 4; // 0x4 + field public static final int SS_INCOMING_BARRING = 20; // 0x14 + field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16 + field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15 + field public static final int SS_INTERROGATION = 2; // 0x2 + field public static final int SS_OUTGOING_BARRING = 19; // 0x13 + field public static final int SS_REGISTRATION = 3; // 0x3 + field public static final int SS_SMS_SERVICES = 4; // 0x4 + field public static final int SS_TELEPHONY = 2; // 0x2 + field public static final int SS_WAIT = 12; // 0xc + } + + public final class ImsSsInfo implements android.os.Parcelable { + ctor public ImsSsInfo(); + method public int describeContents(); + method public java.lang.String getIcbNum(); + method public int getStatus(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DISABLED = 0; // 0x0 + field public static final int ENABLED = 1; // 0x1 + field public static final int NOT_REGISTERED = -1; // 0xffffffff + } + + public final class ImsStreamMediaProfile implements android.os.Parcelable { + method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile); + method public int describeContents(); + method public int getAudioDirection(); + method public int getAudioQuality(); + method public int getRttMode(); + method public int getVideoDirection(); + method public int getVideoQuality(); + method public boolean isRttCall(); + method public void setRttMode(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final int AUDIO_QUALITY_AMR = 1; // 0x1 + field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2 + field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4 + field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5 + field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7 + field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6 + field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14 + field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11 + field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13 + field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12 + field public static final int AUDIO_QUALITY_G711A = 13; // 0xd + field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf + field public static final int AUDIO_QUALITY_G711U = 11; // 0xb + field public static final int AUDIO_QUALITY_G722 = 14; // 0xe + field public static final int AUDIO_QUALITY_G723 = 12; // 0xc + field public static final int AUDIO_QUALITY_G729 = 16; // 0x10 + field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8 + field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9 + field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa + field public static final int AUDIO_QUALITY_NONE = 0; // 0x0 + field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3 + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DIRECTION_INACTIVE = 0; // 0x0 + field public static final int DIRECTION_INVALID = -1; // 0xffffffff + field public static final int DIRECTION_RECEIVE = 1; // 0x1 + field public static final int DIRECTION_SEND = 2; // 0x2 + field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3 + field public static final int RTT_MODE_DISABLED = 0; // 0x0 + field public static final int RTT_MODE_FULL = 1; // 0x1 + field public static final int VIDEO_QUALITY_NONE = 0; // 0x0 + field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1 + field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2 + field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4 + field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8 + field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10 + } + + public final class ImsSuppServiceNotification implements android.os.Parcelable { + ctor public ImsSuppServiceNotification(int, int, int, int, java.lang.String, java.lang.String[]); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public final int code; + field public final java.lang.String[] history; + field public final int index; + field public final int notificationType; + field public final java.lang.String number; + field public final int type; + } + + public class ImsUtListener { + method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData); + method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]); + method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]); + method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]); + method public void onUtConfigurationQueried(int, android.os.Bundle); + method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUtConfigurationUpdated(int); + } + + public abstract class ImsVideoCallProvider { + ctor public ImsVideoCallProvider(); + method public void changeCallDataUsage(long); + method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); + method public void changePeerDimensions(int, int); + method public void changeVideoQuality(int); + method public void handleCallSessionEvent(int); + method public abstract void onRequestCallDataUsage(); + method public abstract void onRequestCameraCapabilities(); + method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile); + method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile); + method public abstract void onSetCamera(java.lang.String); + method public void onSetCamera(java.lang.String, int); + method public abstract void onSetDeviceOrientation(int); + method public abstract void onSetDisplaySurface(android.view.Surface); + method public abstract void onSetPauseImage(android.net.Uri); + method public abstract void onSetPreviewSurface(android.view.Surface); + method public abstract void onSetZoom(float); + method public void receiveSessionModifyRequest(android.telecom.VideoProfile); + method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile); } } -package android.telephony.ims.internal.stub { +package android.telephony.ims.feature { - public class SmsImplBase { - ctor public SmsImplBase(); + public final class CapabilityChangeRequest implements android.os.Parcelable { + method public void addCapabilitiesToDisableForTech(int, int); + method public void addCapabilitiesToEnableForTech(int, int); + method public int describeContents(); + method public java.util.List getCapabilitiesToDisable(); + method public java.util.List getCapabilitiesToEnable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static class CapabilityChangeRequest.CapabilityPair { + ctor public CapabilityChangeRequest.CapabilityPair(int, int); + method public int getCapability(); + method public int getRadioTech(); + } + + public abstract class ImsFeature { + ctor public ImsFeature(); + method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public abstract void onFeatureReady(); + method public abstract void onFeatureRemoved(); + method public final void setFeatureState(int); + field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff + field public static final int CAPABILITY_SUCCESS = 0; // 0x0 + field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0 + field public static final int FEATURE_MMTEL = 1; // 0x1 + field public static final int FEATURE_RCS = 2; // 0x2 + field public static final int STATE_INITIALIZING = 1; // 0x1 + field public static final int STATE_READY = 2; // 0x2 + field public static final int STATE_UNAVAILABLE = 0; // 0x0 + } + + protected static class ImsFeature.CapabilityCallbackProxy { + method public void onChangeCapabilityConfigurationError(int, int, int); + } + + public class MmTelFeature extends android.telephony.ims.feature.ImsFeature { + ctor public MmTelFeature(); + method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public android.telephony.ims.ImsCallProfile createCallProfile(int, int); + method public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(android.telephony.ims.ImsCallProfile); + method public android.telephony.ims.stub.ImsEcbmImplBase getEcbm(); + method public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint(); + method public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation(); + method public android.telephony.ims.stub.ImsUtImplBase getUt(); + method public final void notifyCapabilitiesStatusChanged(android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); + method public final void notifyIncomingCall(android.telephony.ims.stub.ImsCallSessionImplBase, android.os.Bundle); + method public final void notifyVoiceMessageCountUpdate(int); + method public void onFeatureReady(); + method public void onFeatureRemoved(); + method public boolean queryCapabilityConfiguration(int, int); + method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); + method public void setUiTtyMode(int, android.os.Message); + method public int shouldProcessCall(java.lang.String[]); + field public static final int PROCESS_CALL_CSFB = 1; // 0x1 + field public static final int PROCESS_CALL_EMERGENCY_CSFB = 2; // 0x2 + field public static final int PROCESS_CALL_IMS = 0; // 0x0 + } + + public static class MmTelFeature.MmTelCapabilities { + ctor public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities); + ctor public MmTelFeature.MmTelCapabilities(int); + method public final void addCapabilities(int); + method public final boolean isCapable(int); + method public final void removeCapabilities(int); + field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8 + field public static final int CAPABILITY_TYPE_UT = 4; // 0x4 + field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2 + field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 + } + + public static abstract class MmTelFeature.MmTelCapabilities.MmTelCapability implements java.lang.annotation.Annotation { + } + + public static abstract class MmTelFeature.ProcessCallResult implements java.lang.annotation.Annotation { + } + + public class RcsFeature extends android.telephony.ims.feature.ImsFeature { + ctor public RcsFeature(); + method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public void onFeatureReady(); + method public void onFeatureRemoved(); + } + +} + +package android.telephony.ims.stub { + + public class ImsCallSessionImplBase implements java.lang.AutoCloseable { + ctor public ImsCallSessionImplBase(); + method public void accept(int, android.telephony.ims.ImsStreamMediaProfile); + method public void close(); + method public void extendToConference(java.lang.String[]); + method public java.lang.String getCallId(); + method public android.telephony.ims.ImsCallProfile getCallProfile(); + method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider(); + method public android.telephony.ims.ImsCallProfile getLocalCallProfile(); + method public java.lang.String getProperty(java.lang.String); + method public android.telephony.ims.ImsCallProfile getRemoteCallProfile(); + method public int getState(); + method public void hold(android.telephony.ims.ImsStreamMediaProfile); + method public void inviteParticipants(java.lang.String[]); + method public boolean isInCall(); + method public boolean isMultiparty(); + method public void merge(); + method public void reject(int); + method public void removeParticipants(java.lang.String[]); + method public void resume(android.telephony.ims.ImsStreamMediaProfile); + method public void sendDtmf(char, android.os.Message); + method public void sendRttMessage(java.lang.String); + method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile); + method public void sendRttModifyResponse(boolean); + method public void sendUssd(java.lang.String); + method public void setListener(android.telephony.ims.ImsCallSessionListener); + method public void setMute(boolean); + method public void start(java.lang.String, android.telephony.ims.ImsCallProfile); + method public void startConference(java.lang.String[], android.telephony.ims.ImsCallProfile); + method public void startDtmf(char); + method public void stopDtmf(); + method public void terminate(int); + method public void update(int, android.telephony.ims.ImsStreamMediaProfile); + field public static final int USSD_MODE_NOTIFY = 0; // 0x0 + field public static final int USSD_MODE_REQUEST = 1; // 0x1 + } + + public static class ImsCallSessionImplBase.State { + method public static java.lang.String toString(int); + field public static final int ESTABLISHED = 4; // 0x4 + field public static final int ESTABLISHING = 3; // 0x3 + field public static final int IDLE = 0; // 0x0 + field public static final int INITIATED = 1; // 0x1 + field public static final int INVALID = -1; // 0xffffffff + field public static final int NEGOTIATING = 2; // 0x2 + field public static final int REESTABLISHING = 6; // 0x6 + field public static final int RENEGOTIATING = 5; // 0x5 + field public static final int TERMINATED = 8; // 0x8 + field public static final int TERMINATING = 7; // 0x7 + } + + public class ImsConfigImplBase { + ctor public ImsConfigImplBase(); + method public int getConfigInt(int); + method public java.lang.String getConfigString(int); + method public final void notifyProvisionedValueChanged(int, int); + method public final void notifyProvisionedValueChanged(int, java.lang.String); + method public int setConfig(int, int); + method public int setConfig(int, java.lang.String); + field public static final int CONFIG_RESULT_FAILED = 1; // 0x1 + field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0 + field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff + } + + public class ImsEcbmImplBase { + ctor public ImsEcbmImplBase(); + method public final void enteredEcbm(); + method public void exitEmergencyCallbackMode(); + method public final void exitedEcbm(); + } + + public final class ImsFeatureConfiguration implements android.os.Parcelable { + ctor public ImsFeatureConfiguration(); + method public int describeContents(); + method public int[] getServiceFeatures(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static class ImsFeatureConfiguration.Builder { + ctor public ImsFeatureConfiguration.Builder(); + method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int); + method public android.telephony.ims.stub.ImsFeatureConfiguration build(); + } + + public class ImsMultiEndpointImplBase { + ctor public ImsMultiEndpointImplBase(); + method public final void onImsExternalCallStateUpdate(java.util.List); + method public void requestImsExternalCallStateInfo(); + } + + public class ImsRegistrationImplBase { + ctor public ImsRegistrationImplBase(); + method public final void onDeregistered(android.telephony.ims.ImsReasonInfo); + method public final void onRegistered(int); + method public final void onRegistering(int); + method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]); + method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo); + field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1 + field public static final int REGISTRATION_TECH_LTE = 0; // 0x0 + field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff + } + + public class ImsSmsImplBase { + ctor public ImsSmsImplBase(); method public void acknowledgeSms(int, int, int); method public void acknowledgeSmsReport(int, int, int); method public java.lang.String getSmsFormat(); @@ -5129,6 +5830,29 @@ package android.telephony.ims.internal.stub { field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1 } + public class ImsUtImplBase { + ctor public ImsUtImplBase(); + method public void close(); + method public int queryCallBarring(int); + method public int queryCallBarringForServiceClass(int, int); + method public int queryCallForward(int, java.lang.String); + method public int queryCallWaiting(); + method public int queryClip(); + method public int queryClir(); + method public int queryColp(); + method public int queryColr(); + method public void setListener(android.telephony.ims.ImsUtListener); + method public int transact(android.os.Bundle); + method public int updateCallBarring(int, int, java.lang.String[]); + method public int updateCallBarringForServiceClass(int, int, java.lang.String[], int); + method public int updateCallForward(int, int, java.lang.String, int, int); + method public int updateCallWaiting(boolean, int); + method public int updateClip(boolean); + method public int updateClir(int); + method public int updateColp(boolean); + method public int updateColr(int); + } + } package android.telephony.mbms { @@ -5181,11 +5905,11 @@ package android.telephony.mbms.vendor { method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; method public void dispose(int) throws android.os.RemoteException; method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; - method public int getDownloadStatus(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException; method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException; method public java.util.List listPendingDownloads(int) throws android.os.RemoteException; method public void onAppCallbackDied(int, int); method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException; + method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException; method public int requestUpdateFileServices(int, java.util.List) throws android.os.RemoteException; method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException; diff --git a/api/system-removed.txt b/api/system-removed.txt index b63703dc0035daee45b3dcfdfa8d390909c9d0c7..48f43e0880daea0e55f600bbdf16726967b50e5d 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -1,13 +1,5 @@ package android.app { - public abstract deprecated class EphemeralResolverService extends android.app.InstantAppResolverService { - ctor public EphemeralResolverService(); - method public android.os.Looper getLooper(); - method public abstract deprecated java.util.List onEphemeralResolveInfoList(int[], int); - method public android.content.pm.EphemeralResolveInfo onGetEphemeralIntentFilter(java.lang.String); - method public java.util.List onGetEphemeralResolveInfo(int[]); - } - public class Notification implements android.os.Parcelable { method public static java.lang.Class getNotificationStyleClass(java.lang.String); } @@ -31,10 +23,7 @@ package android.content { public class Intent implements java.lang.Cloneable android.os.Parcelable { field public static final deprecated java.lang.String ACTION_DEVICE_INITIALIZATION_WIZARD = "android.intent.action.DEVICE_INITIALIZATION_WIZARD"; - field public static final deprecated java.lang.String ACTION_EPHEMERAL_RESOLVER_SETTINGS = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS"; - field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE"; field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR"; - field public static final deprecated java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE"; field public static final deprecated java.lang.String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE"; field public static final deprecated java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator"; field public static final deprecated java.lang.String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator"; @@ -62,45 +51,6 @@ package android.content { } -package android.content.pm { - - public final deprecated class EphemeralIntentFilter implements android.os.Parcelable { - ctor public EphemeralIntentFilter(java.lang.String, java.util.List); - method public int describeContents(); - method public java.util.List getFilters(); - method public java.lang.String getSplitName(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - } - - public final deprecated class EphemeralResolveInfo implements android.os.Parcelable { - ctor public deprecated EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List); - ctor public deprecated EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List); - ctor public EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List, int); - ctor public EphemeralResolveInfo(java.lang.String, java.lang.String, java.util.List); - method public int describeContents(); - method public byte[] getDigestBytes(); - method public int getDigestPrefix(); - method public deprecated java.util.List getFilters(); - method public java.util.List getIntentFilters(); - method public java.lang.String getPackageName(); - method public int getVersionCode(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - field public static final java.lang.String SHA_ALGORITHM = "SHA-256"; - } - - public static final class EphemeralResolveInfo.EphemeralDigest implements android.os.Parcelable { - ctor public EphemeralResolveInfo.EphemeralDigest(java.lang.String); - method public int describeContents(); - method public byte[][] getDigestBytes(); - method public int[] getDigestPrefix(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - } - -} - package android.media.tv { public final class TvInputManager { diff --git a/api/test-current.txt b/api/test-current.txt index 4e8f904b96b7a17d3a2257733a2ee19e3d8f1b63..c30c0566b50d8677bd6dda93b5818d4ca2356aa6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -183,10 +183,7 @@ package android.content { } public abstract class Context { - method public abstract int getUserId(); - } - - public class ContextWrapper extends android.content.Context { + method public android.os.UserHandle getUser(); method public int getUserId(); } @@ -214,6 +211,7 @@ package android.content.pm { method public abstract boolean isPermissionReviewModeEnabled(); field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption"; + field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000 } public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { @@ -298,6 +296,15 @@ package android.hardware.camera2 { package android.hardware.display { + public final class AmbientBrightnessDayStats implements android.os.Parcelable { + method public int describeContents(); + method public float[] getBucketBoundaries(); + method public java.time.LocalDate getLocalDate(); + method public float[] getStats(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public final class BrightnessChangeEvent implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -305,11 +312,14 @@ package android.hardware.display { field public final float batteryLevel; field public final float brightness; field public final int colorTemperature; + field public final boolean isDefaultBrightnessConfig; + field public final boolean isUserSetBrightness; field public final float lastBrightness; field public final long[] luxTimestamps; field public final float[] luxValues; field public final boolean nightMode; field public final java.lang.String packageName; + field public final float powerBrightnessFactor; field public final long timeStamp; } @@ -565,6 +575,14 @@ package android.service.autofill { method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception; } + public final class DateTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation { + method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception; + } + + public final class DateValueSanitizer extends android.service.autofill.InternalSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer { + method public android.view.autofill.AutofillValue sanitize(android.view.autofill.AutofillValue); + } + public final class FillResponse implements android.os.Parcelable { method public int getFlags(); } @@ -599,7 +617,8 @@ package android.service.autofill { } public abstract interface ValueFinder { - method public abstract java.lang.String findByAutofillId(android.view.autofill.AutofillId); + method public default java.lang.String findByAutofillId(android.view.autofill.AutofillId); + method public abstract android.view.autofill.AutofillValue findRawValueByAutofillId(android.view.autofill.AutofillId); } } @@ -731,11 +750,11 @@ package android.telephony.mbms.vendor { method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; method public void dispose(int) throws android.os.RemoteException; method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; - method public int getDownloadStatus(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException; method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException; method public java.util.List listPendingDownloads(int) throws android.os.RemoteException; method public void onAppCallbackDied(int, int); method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException; + method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException; method public int requestUpdateFileServices(int, java.util.List) throws android.os.RemoteException; method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException; @@ -986,8 +1005,8 @@ package android.view { } public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable { - method public final void setActionButton(int); - method public final void setButtonState(int); + method public void setActionButton(int); + method public void setButtonState(int); } public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback { @@ -1035,6 +1054,14 @@ package android.view.autofill { } +package android.view.inputmethod { + + public final class InputMethodManager { + method public boolean isInputMethodPickerShown(); + } + +} + package android.widget { public abstract class AbsListView extends android.widget.AdapterView implements android.widget.Filter.FilterListener android.text.TextWatcher android.view.ViewTreeObserver.OnGlobalLayoutListener android.view.ViewTreeObserver.OnTouchModeChangeListener { diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java index f75678b7fa1e99aff0ea507938fc789e0919f0f8..6e0bd3a81d84086e529034fb6f8d23570369b2d4 100644 --- a/cmds/content/src/com/android/commands/content/Content.java +++ b/cmds/content/src/com/android/commands/content/Content.java @@ -26,6 +26,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.FileUtils; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; @@ -34,6 +35,7 @@ import android.text.TextUtils; import libcore.io.Streams; +import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -583,7 +585,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { try (ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null, null)) { - Streams.copy(new FileInputStream(fd.getFileDescriptor()), System.out); + FileUtils.copy(fd.getFileDescriptor(), FileDescriptor.out); } } } @@ -596,7 +598,7 @@ public class Content { @Override public void onExecute(IContentProvider provider) throws Exception { try (ParcelFileDescriptor fd = provider.openFile(null, mUri, "w", null, null)) { - Streams.copy(System.in, new FileOutputStream(fd.getFileDescriptor())); + FileUtils.copy(FileDescriptor.in, fd.getFileDescriptor()); } } } diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java index 47581e10e937669bcb524eafb6261acca34fdbdd..7c1a5557a1e99f2adf3ada321af0c26cb7ce5d6c 100644 --- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java +++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java @@ -46,6 +46,7 @@ public final class Dpm extends BaseCommand { private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner"; private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin"; private static final String COMMAND_CLEAR_FREEZE_PERIOD_RECORD = "clear-freeze-period-record"; + private static final String COMMAND_FORCE_SECURITY_LOGS = "force-security-logs"; private IDevicePolicyManager mDevicePolicyManager; private int mUserId = UserHandle.USER_SYSTEM; @@ -76,11 +77,15 @@ public final class Dpm extends BaseCommand { "\n" + "dpm remove-active-admin: Disables an active admin, the admin must have declared" + " android:testOnly in the application in its manifest. This will also remove" + - " device and profile owners\n" + + " device and profile owners.\n" + "\n" + "dpm " + COMMAND_CLEAR_FREEZE_PERIOD_RECORD + ": clears framework-maintained " + "record of past freeze periods that the device went through. For use during " + - "feature development to prevent triggering restriction on setting freeze periods"); + "feature development to prevent triggering restriction on setting freeze " + + "periods.\n" + + "\n" + + "dpm " + COMMAND_FORCE_SECURITY_LOGS + ": makes all security logs available to " + + "the DPC and triggers DeviceAdminReceiver.onSecurityLogsAvailable() if needed."); } @Override @@ -109,11 +114,26 @@ public final class Dpm extends BaseCommand { case COMMAND_CLEAR_FREEZE_PERIOD_RECORD: runClearFreezePeriodRecord(); break; + case COMMAND_FORCE_SECURITY_LOGS: + runForceSecurityLogs(); + break; default: throw new IllegalArgumentException ("unknown command '" + command + "'"); } } + private void runForceSecurityLogs() throws RemoteException, InterruptedException { + while (true) { + final long toWait = mDevicePolicyManager.forceSecurityLogs(); + if (toWait == 0) { + break; + } + System.out.println("We have to wait for " + toWait + " milliseconds..."); + Thread.sleep(toWait); + } + System.out.println("Success"); + } + private void parseArgs(boolean canHaveName) { String opt; while ((opt = nextOption()) != null) { diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp index 44adaecfe97f136a1dff4fcc7e99085c8fb02fc7..3f0e331c8b55d39552d9942f54bf63aabcae0f85 100644 --- a/cmds/incidentd/src/Privacy.cpp +++ b/cmds/incidentd/src/Privacy.cpp @@ -65,7 +65,7 @@ PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) bool PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; } -PrivacySpec new_spec_from_args(int dest) +PrivacySpec PrivacySpec::new_spec(int dest) { switch (dest) { case android::os::DEST_AUTOMATIC: @@ -77,4 +77,7 @@ PrivacySpec new_spec_from_args(int dest) } } -PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); } \ No newline at end of file +PrivacySpec PrivacySpec::get_default_dropbox_spec() +{ + return PrivacySpec(android::os::DEST_AUTOMATIC); +} diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h index 9e15ff43be06d5cb5facb52aba4d95fee6d0a6f4..4f3db678f765d6928efda3e78b6d5ba87e1ef470 100644 --- a/cmds/incidentd/src/Privacy.h +++ b/cmds/incidentd/src/Privacy.h @@ -65,8 +65,6 @@ public: const uint8_t dest; PrivacySpec() : dest(DEST_DEFAULT_VALUE) {} - PrivacySpec(uint8_t dest) : dest(dest) {} - bool operator<(const PrivacySpec& other) const; // check permission of a policy, if returns true, don't strip the data. @@ -74,9 +72,12 @@ public: // if returns true, no data need to be stripped. bool RequireAll() const; -}; -PrivacySpec new_spec_from_args(int dest); -PrivacySpec get_default_dropbox_spec(); + // Constructs spec using static methods below. + static PrivacySpec new_spec(int dest); + static PrivacySpec get_default_dropbox_spec(); +private: + PrivacySpec(uint8_t dest) : dest(dest) {} +}; #endif // PRIVACY_H diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp index bd559d6980f1d04d0c55baf058e91108bb1430b4..b9f479bd683f2010e444ad17942aca2afef1d61c 100644 --- a/cmds/incidentd/src/Reporter.cpp +++ b/cmds/incidentd/src/Reporter.cpp @@ -64,7 +64,8 @@ ReportRequest::ok() ReportRequestSet::ReportRequestSet() :mRequests(), mSections(), - mMainFd(-1) + mMainFd(-1), + mMainDest(-1) { } @@ -86,6 +87,12 @@ ReportRequestSet::setMainFd(int fd) mMainFd = fd; } +void +ReportRequestSet::setMainDest(int dest) +{ + mMainDest = dest; +} + bool ReportRequestSet::containsSection(int id) { return mSections.containsSection(id); @@ -125,12 +132,14 @@ Reporter::runReport() status_t err = NO_ERROR; bool needMainFd = false; int mainFd = -1; + int mainDest = -1; HeaderSection headers; // See if we need the main file for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) { if ((*it)->fd < 0 && mainFd < 0) { needMainFd = true; + mainDest = (*it)->args.dest(); break; } } @@ -154,6 +163,7 @@ Reporter::runReport() // Add to the set batch.setMainFd(mainFd); + batch.setMainDest(mainDest); } // Tell everyone that we're starting. diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h index 2615c6202d3ddd336c6b2c5dbdd1f0b934afb917..f30ecf0dd648fd46fb2a7e8ce9d6371e18f16f50 100644 --- a/cmds/incidentd/src/Reporter.h +++ b/cmds/incidentd/src/Reporter.h @@ -53,6 +53,7 @@ public: void add(const sp& request); void setMainFd(int fd); + void setMainDest(int dest); typedef vector>::iterator iterator; @@ -61,10 +62,12 @@ public: int mainFd() { return mMainFd; } bool containsSection(int id); + int mainDest() { return mMainDest; } private: vector> mRequests; IncidentReportArgs mSections; int mMainFd; + int mMainDest; }; // ================================================================================ diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 0827785811b66fe9ae11650bcdaf38b06176bd7a..faeab87f81780ae7bf74e45fbac64ffcae86ac11 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -152,36 +152,40 @@ write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* re // The streaming ones, group requests by spec in order to save unnecessary strip operations map>> requestsBySpec; - for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) { + for (auto it = requests->begin(); it != requests->end(); it++) { sp request = *it; if (!request->ok() || !request->args.containsSection(id)) { continue; // skip invalid request } - PrivacySpec spec = new_spec_from_args(request->args.dest()); + PrivacySpec spec = PrivacySpec::new_spec(request->args.dest()); requestsBySpec[spec].push_back(request); } - for (map>>::iterator mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) { + for (auto mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) { PrivacySpec spec = mit->first; err = privacyBuffer.strip(spec); if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted. if (privacyBuffer.size() == 0) continue; - for (vector>::iterator it = mit->second.begin(); it != mit->second.end(); it++) { + for (auto it = mit->second.begin(); it != mit->second.end(); it++) { sp request = *it; err = write_section_header(request->fd, id, privacyBuffer.size()); if (err != NO_ERROR) { request->err = err; continue; } err = privacyBuffer.flush(request->fd); if (err != NO_ERROR) { request->err = err; continue; } writeable++; - ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, privacyBuffer.size(), request->fd, spec.dest); + ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, + privacyBuffer.size(), request->fd, spec.dest); } privacyBuffer.clear(); } // The dropbox file if (requests->mainFd() >= 0) { - err = privacyBuffer.strip(get_default_dropbox_spec()); + PrivacySpec spec = requests->mainDest() < 0 ? + PrivacySpec::get_default_dropbox_spec() : + PrivacySpec::new_spec(requests->mainDest()); + err = privacyBuffer.strip(spec); if (err != NO_ERROR) return err; // the buffer data is corrupted. if (privacyBuffer.size() == 0) goto DONE; @@ -190,7 +194,8 @@ write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* re err = privacyBuffer.flush(requests->mainFd()); if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; } writeable++; - ALOGD("Section %d flushed %zu bytes to dropbox %d", id, privacyBuffer.size(), requests->mainFd()); + ALOGD("Section %d flushed %zu bytes to dropbox %d with spec %d", id, + privacyBuffer.size(), requests->mainFd(), spec.dest); } DONE: diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp index 32b9e42d270cc09c3855a3f62af151f29c0f13c0..c7bfe555574358711d38464f76b6c6bc4b5520f0 100644 --- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp +++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp @@ -73,7 +73,7 @@ public: } void assertStrip(uint8_t dest, string expected, Privacy* policy) { - PrivacySpec spec(dest); + PrivacySpec spec = PrivacySpec::new_spec(dest); EncodedBuffer::iterator bufData = buffer.data(); PrivacyBuffer privacyBuf(policy, bufData); ASSERT_EQ(privacyBuf.strip(spec), NO_ERROR); @@ -224,7 +224,8 @@ TEST_F(PrivacyBufferTest, ClearAndStrip) { Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL }; EncodedBuffer::iterator bufData = buffer.data(); PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData); - PrivacySpec spec1(DEST_EXPLICIT), spec2(DEST_LOCAL); + PrivacySpec spec1 = PrivacySpec::new_spec(DEST_EXPLICIT); + PrivacySpec spec2 = PrivacySpec::new_spec(DEST_LOCAL); ASSERT_EQ(privacyBuf.strip(spec1), NO_ERROR); assertBuffer(privacyBuf, STRING_FIELD_0); diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java index 360b2308b1c7c38afb887b82fc00d88e719ea831..b76d6694ca2dbf6a3b2a69d6aea926fd81c25560 100644 --- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java +++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java @@ -19,6 +19,7 @@ package com.android.commands.requestsync; import android.accounts.Account; import android.content.ContentResolver; +import android.content.SyncRequest; import android.os.Bundle; import java.net.URISyntaxException; @@ -28,12 +29,31 @@ public class RequestSync { private String[] mArgs; private int mNextArg; private String mCurArgData; + private boolean mIsForegroundRequest; enum Operation { REQUEST_SYNC { @Override void invoke(RequestSync caller) { - ContentResolver.requestSync(caller.mAccount, caller.mAuthority, caller.mExtras); + if (caller.mIsForegroundRequest) { + caller.mExtras.putBoolean( + ContentResolver.SYNC_VIRTUAL_EXTRAS_FORCE_FG_SYNC, true); + } else { + caller.mExtras.putBoolean( + ContentResolver.SYNC_VIRTUAL_EXTRAS_FORCE_BG_SYNC, true); + System.out.println( + "Making a sync request as a background app.\n" + + "Note: request may be throttled by App Standby.\n" + + "To override this behavior and run a sync immediately," + + " pass a -f option.\n"); + } + final SyncRequest request = + new SyncRequest.Builder() + .setSyncAdapter(caller.mAccount, caller.mAuthority) + .setExtras(caller.mExtras) + .syncOnce() + .build(); + ContentResolver.requestSync(request); } }, ADD_PERIODIC_SYNC { @@ -191,6 +211,10 @@ public class RequestSync { final String key = nextArgRequired(); final String value = nextArgRequired(); mExtras.putBoolean(key, Boolean.valueOf(value)); + + } else if (opt.equals("-f") || opt.equals("--foreground")) { + mIsForegroundRequest = true; + } else { System.err.println("Error: Unknown option: " + opt); showUsage(); @@ -267,6 +291,9 @@ public class RequestSync { " -n|--account-name \n" + " -t|--account-type \n" + " -a|--authority \n" + + " App-standby related options\n" + + "\n" + + " -f|--foreground (Exempt a sync from app standby)\n" + " ContentResolver extra options:\n" + " --is|--ignore-settings: Add SYNC_EXTRAS_IGNORE_SETTINGS\n" + " --ib|--ignore-backoff: Add SYNC_EXTRAS_IGNORE_BACKOFF\n" + diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index eabbb96a392ef10e6c2ec2ba031c1a6ae7821648..b0019ac90708b58fb3e2fc16e68e4f55afbed45f 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -38,8 +38,11 @@ statsd_common_src := \ src/external/StatsPuller.cpp \ src/external/StatsCompanionServicePuller.cpp \ src/external/SubsystemSleepStatePuller.cpp \ + src/external/ResourceHealthManagerPuller.cpp \ src/external/CpuTimePerUidPuller.cpp \ src/external/CpuTimePerUidFreqPuller.cpp \ + src/external/KernelUidCpuActiveTimeReader.cpp \ + src/external/KernelUidCpuClusterTimeReader.cpp \ src/external/StatsPullerManagerImpl.cpp \ src/logd/LogEvent.cpp \ src/logd/LogListener.cpp \ @@ -75,7 +78,8 @@ statsd_common_aidl_includes := \ $(LOCAL_PATH)/../../core/java statsd_common_static_libraries := \ - libplatformprotos + libhealthhalutils \ + libplatformprotos \ statsd_common_shared_libraries := \ libbase \ @@ -93,6 +97,7 @@ statsd_common_shared_libraries := \ libhidlbase \ libhidltransport \ libhwbinder \ + android.hardware.health@2.0 \ android.hardware.power@1.0 \ android.hardware.power@1.1 \ libmemunreachable @@ -165,6 +170,7 @@ LOCAL_CFLAGS += \ LOCAL_SRC_FILES := \ $(statsd_common_src) \ + tests/dimension_test.cpp \ tests/AnomalyMonitor_test.cpp \ tests/anomaly/AnomalyTracker_test.cpp \ tests/ConfigManager_test.cpp \ @@ -190,7 +196,8 @@ LOCAL_SRC_FILES := \ tests/e2e/WakelockDuration_e2e_test.cpp \ tests/e2e/MetricConditionLink_e2e_test.cpp \ tests/e2e/Attribution_e2e_test.cpp \ - tests/e2e/GaugeMetric_e2e_test.cpp + tests/e2e/GaugeMetric_e2e_test.cpp \ + tests/e2e/DimensionInCondition_e2e_test.cpp LOCAL_STATIC_LIBRARIES := \ $(statsd_common_static_libraries) \ diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp index 288ebe9dbbe9883a217f7ffd7b22a2f665ae2556..f0eaeff88d34f236033848d76bbe2a9fb424e89f 100644 --- a/cmds/statsd/src/HashableDimensionKey.cpp +++ b/cmds/statsd/src/HashableDimensionKey.cpp @@ -67,20 +67,23 @@ android::hash_t hashDimensionsValue(const DimensionsValue& value) { return hashDimensionsValue(0, value); } -using std::string; +android::hash_t hashMetricDimensionKey(int64_t seed, const MetricDimensionKey& dimensionKey) { + android::hash_t hash = seed; + hash = android::JenkinsHashMix(hash, std::hash{}(dimensionKey)); + return JenkinsHashWhiten(hash); +} +using std::string; string HashableDimensionKey::toString() const { - string flattened; - DimensionsValueToString(getDimensionsValue(), &flattened); - return flattened; + return DimensionsValueToString(getDimensionsValue()); } -bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2) { +bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) { if (s1.field() != s2.field()) { return false; } - if (s1.value_case() != s1.value_case()) { + if (s1.value_case() != s2.value_case()) { return false; } switch (s1.value_case()) { @@ -102,8 +105,8 @@ bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2 } bool allMatched = true; for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) { - allMatched &= compareDimensionsValue(s1.value_tuple().dimensions_value(i), - s2.value_tuple().dimensions_value(i)); + allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i), + s2.value_tuple().dimensions_value(i)); } return allMatched; } @@ -113,14 +116,72 @@ bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2 } } +bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) { + if (s1.field() != s2.field()) { + return s1.field() < s2.field(); + } + if (s1.value_case() != s2.value_case()) { + return s1.value_case() < s2.value_case(); + } + switch (s1.value_case()) { + case DimensionsValue::ValueCase::kValueStr: + return s1.value_str() < s2.value_str(); + case DimensionsValue::ValueCase::kValueInt: + return s1.value_int() < s2.value_int(); + case DimensionsValue::ValueCase::kValueLong: + return s1.value_long() < s2.value_long(); + case DimensionsValue::ValueCase::kValueBool: + return (int)s1.value_bool() < (int)s2.value_bool(); + case DimensionsValue::ValueCase::kValueFloat: + return s1.value_float() < s2.value_float(); + case DimensionsValue::ValueCase::kValueTuple: + { + if (s1.value_tuple().dimensions_value_size() != + s2.value_tuple().dimensions_value_size()) { + return s1.value_tuple().dimensions_value_size() < + s2.value_tuple().dimensions_value_size(); + } + for (int i = 0; i < s1.value_tuple().dimensions_value_size(); ++i) { + if (EqualsTo(s1.value_tuple().dimensions_value(i), + s2.value_tuple().dimensions_value(i))) { + continue; + } else { + return LessThan(s1.value_tuple().dimensions_value(i), + s2.value_tuple().dimensions_value(i)); + } + } + return false; + } + case DimensionsValue::ValueCase::VALUE_NOT_SET: + default: + return false; + } +} + bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const { - return compareDimensionsValue(getDimensionsValue(), that.getDimensionsValue()); + return EqualsTo(getDimensionsValue(), that.getDimensionsValue()); }; bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const { + return LessThan(getDimensionsValue(), that.getDimensionsValue()); +}; + +string MetricDimensionKey::toString() const { + string flattened = mDimensionKeyInWhat.toString(); + flattened += mDimensionKeyInCondition.toString(); + return flattened; +} + +bool MetricDimensionKey::operator==(const MetricDimensionKey& that) const { + return mDimensionKeyInWhat == that.getDimensionKeyInWhat() && + mDimensionKeyInCondition == that.getDimensionKeyInCondition(); +}; + +bool MetricDimensionKey::operator<(const MetricDimensionKey& that) const { return toString().compare(that.toString()) < 0; }; + } // namespace statsd } // namespace os } // namespace android \ No newline at end of file diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h index 85c317f8cf1f35f597332b70ffc8639b44d4b8cc..a31d7a6d85c6cf74a02b7e749a4c327ed6605065 100644 --- a/cmds/statsd/src/HashableDimensionKey.h +++ b/cmds/statsd/src/HashableDimensionKey.h @@ -41,6 +41,10 @@ public: return mDimensionsValue; } + inline DimensionsValue* getMutableDimensionsValue() { + return &mDimensionsValue; + } + bool operator==(const HashableDimensionKey& that) const; bool operator<(const HashableDimensionKey& that) const; @@ -53,8 +57,52 @@ private: DimensionsValue mDimensionsValue; }; +class MetricDimensionKey { + public: + explicit MetricDimensionKey(const HashableDimensionKey& dimensionKeyInWhat, + const HashableDimensionKey& dimensionKeyInCondition) + : mDimensionKeyInWhat(dimensionKeyInWhat), + mDimensionKeyInCondition(dimensionKeyInCondition) {}; + + MetricDimensionKey(){}; + + MetricDimensionKey(const MetricDimensionKey& that) + : mDimensionKeyInWhat(that.getDimensionKeyInWhat()), + mDimensionKeyInCondition(that.getDimensionKeyInCondition()) {}; + + MetricDimensionKey& operator=(const MetricDimensionKey& from) = default; + + std::string toString() const; + + inline const HashableDimensionKey& getDimensionKeyInWhat() const { + return mDimensionKeyInWhat; + } + + inline const HashableDimensionKey& getDimensionKeyInCondition() const { + return mDimensionKeyInCondition; + } + + bool hasDimensionKeyInCondition() const { + return mDimensionKeyInCondition.getDimensionsValue().has_field(); + } + + bool operator==(const MetricDimensionKey& that) const; + + bool operator<(const MetricDimensionKey& that) const; + + inline const char* c_str() const { + return toString().c_str(); + } + private: + HashableDimensionKey mDimensionKeyInWhat; + HashableDimensionKey mDimensionKeyInCondition; +}; + +bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2); + android::hash_t hashDimensionsValue(int64_t seed, const DimensionsValue& value); android::hash_t hashDimensionsValue(const DimensionsValue& value); +android::hash_t hashMetricDimensionKey(int64_t see, const MetricDimensionKey& dimensionKey); } // namespace statsd } // namespace os @@ -63,6 +111,7 @@ android::hash_t hashDimensionsValue(const DimensionsValue& value); namespace std { using android::os::statsd::HashableDimensionKey; +using android::os::statsd::MetricDimensionKey; template <> struct hash { @@ -71,4 +120,14 @@ struct hash { } }; -} // namespace std +template <> +struct hash { + std::size_t operator()(const MetricDimensionKey& key) const { + android::hash_t hash = hashDimensionsValue( + key.getDimensionKeyInWhat().getDimensionsValue()); + hash = android::JenkinsHashMix(hash, + hashDimensionsValue(key.getDimensionKeyInCondition().getDimensionsValue())); + return android::JenkinsHashWhiten(hash); + } +}; +} // namespace std \ No newline at end of file diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 3e71b5368134a55235cb227f322319a3552ce336..a4066aa7bca55fd9bb4480ca92cd5aa767bc5417 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -91,23 +91,22 @@ void StatsLogProcessor::onAnomalyAlarmFired( } void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const { - std::vector uidFields; + std::set uidFields; if (android::util::kAtomsWithAttributionChain.find(event->GetTagId()) != android::util::kAtomsWithAttributionChain.end()) { - findFields( - event->getFieldValueMap(), - buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY), - &uidFields); + FieldMatcher matcher; + buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY, &matcher); + findFields(event->getFieldValueMap(), matcher, &uidFields); } else if (android::util::kAtomsWithUidField.find(event->GetTagId()) != android::util::kAtomsWithUidField.end()) { - findFields( - event->getFieldValueMap(), - buildSimpleAtomFieldMatcher(event->GetTagId(), 1 /* uid is always the 1st field. */), - &uidFields); + FieldMatcher matcher; + buildSimpleAtomFieldMatcher( + event->GetTagId(), 1 /* uid is always the 1st field. */, &matcher); + findFields(event->getFieldValueMap(), matcher, &uidFields); } - for (size_t i = 0; i < uidFields.size(); ++i) { - DimensionsValue* value = event->findFieldValueOrNull(uidFields[i]); + for (const auto& uidField : uidFields) { + DimensionsValue* value = event->findFieldValueOrNull(uidField); if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) { const int uid = mUidMap->getHostUidOrSelf(value->value_int()); value->set_value_int(uid); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index c19ff63e28588b6140b0d6e8392616b62d92f4cd..7642aafaab437af666634a597487f6996df0c1a9 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -104,7 +104,10 @@ private: FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks); FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice); FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent); - + FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricNoLink); + FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricWithLink); + FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink); + FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink); }; } // namespace statsd diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index f545bb0738e9d95eba1614e7706b34098a45b3a2..32da94f862c59b76363ee026e78562f871f689e5 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -235,6 +236,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector& if (!args[0].compare(String8("write-to-disk"))) { return cmd_write_data_to_disk(out); } + + if (!args[0].compare(String8("log-app-hook"))) { + return cmd_log_app_hook(out, args); + } } print_cmd_help(out); @@ -272,6 +277,15 @@ void StatsService::print_cmd_help(FILE* out) { fprintf(out, " Flushes all data on memory to disk.\n"); fprintf(out, "\n"); fprintf(out, "\n"); + fprintf(out, "usage: adb shell cmd stats log-app-hook [UID] LABEL STATE\n"); + fprintf(out, " Writes an AppHook event to the statslog buffer.\n"); + fprintf(out, " UID The uid to use. It is only possible to pass a UID\n"); + fprintf(out, " parameter on eng builds. If UID is omitted the calling\n"); + fprintf(out, " uid is used.\n"); + fprintf(out, " LABEL Integer in [0, 15], as per atoms.proto.\n"); + fprintf(out, " STATE Integer in [0, 3], as per atoms.proto.\n"); + fprintf(out, "\n"); + fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats config remove [UID] [NAME]\n"); fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n"); fprintf(out, "\n"); @@ -523,6 +537,42 @@ status_t StatsService::cmd_write_data_to_disk(FILE* out) { return NO_ERROR; } +status_t StatsService::cmd_log_app_hook(FILE* out, const Vector& args) { + bool good = false; + int32_t uid; + int32_t label; + int32_t state; + const int argCount = args.size(); + if (argCount == 3) { + // Automatically pick the UID + uid = IPCThreadState::self()->getCallingUid(); + label = atoi(args[1].c_str()); + state = atoi(args[2].c_str()); + good = true; + } else if (argCount == 4) { + uid = atoi(args[1].c_str()); + // If it's a userdebug or eng build, then the shell user can impersonate other uids. + // Otherwise, the uid must match the actual caller's uid. + if (mEngBuild || (uid >= 0 && (uid_t)uid == IPCThreadState::self()->getCallingUid())) { + label = atoi(args[2].c_str()); + state = atoi(args[3].c_str()); + good = true; + } else { + fprintf(out, + "Selecting a UID for writing AppHook can only be dumped for other UIDs on eng" + " or userdebug builds.\n"); + } + } + if (good) { + fprintf(out, "Logging AppHook(%d, %d, %d) to statslog.\n", uid, label, state); + android::util::stats_write(android::util::APP_HOOK, uid, label, state); + } else { + print_cmd_help(out); + return UNKNOWN_ERROR; + } + return NO_ERROR; +} + status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector& args) { int s = atoi(args[1].c_str()); vector > stats; @@ -551,6 +601,12 @@ status_t StatsService::cmd_dump_memory_info(FILE* out) { return NO_ERROR; } +status_t StatsService::cmd_clear_puller_cache(FILE* out) { + mStatsPullerManager.ClearPullerCache(); + fprintf(out, "Puller cached data removed!\n"); + return NO_ERROR; +} + Status StatsService::informAllUidData(const vector& uid, const vector& version, const vector& app) { VLOG("StatsService::informAllUidData was called"); diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index be20893994f105f179c05281f70ed06f066f92ef..109752b0295fa4b34b1d21b4020f3a9bc253c033 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -182,6 +182,11 @@ private: */ status_t cmd_write_data_to_disk(FILE* out); + /** + * Write an AppHook event to the StatsLog buffer, as though StatsLog.write(APP_HOOK). + */ + status_t cmd_log_app_hook(FILE* out, const Vector& args); + /** * Print contents of a pulled metrics source. */ @@ -197,6 +202,11 @@ private: */ status_t cmd_dump_memory_info(FILE* out); + /* + * Clear all puller cached data + */ + status_t cmd_clear_puller_cache(FILE* out); + /** * Update a configuration. */ diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index ded6c4c660be5940c57cc6d6a8dd5d59237f47ae..c84a5b4509b03f6569b1c55e2660b58379543533 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -96,7 +96,7 @@ void AnomalyTracker::flushPastBuckets(const int64_t& latestPastBucketNum) { } } -void AnomalyTracker::addPastBucket(const HashableDimensionKey& key, const int64_t& bucketValue, +void AnomalyTracker::addPastBucket(const MetricDimensionKey& key, const int64_t& bucketValue, const int64_t& bucketNum) { flushPastBuckets(bucketNum); @@ -147,7 +147,7 @@ void AnomalyTracker::addBucketToSum(const shared_ptr& bucket) { } } -int64_t AnomalyTracker::getPastBucketValue(const HashableDimensionKey& key, +int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key, const int64_t& bucketNum) const { const auto& bucket = mPastBuckets[index(bucketNum)]; if (bucket == nullptr) { @@ -157,7 +157,7 @@ int64_t AnomalyTracker::getPastBucketValue(const HashableDimensionKey& key, return itr == bucket->end() ? 0 : itr->second; } -int64_t AnomalyTracker::getSumOverPastBuckets(const HashableDimensionKey& key) const { +int64_t AnomalyTracker::getSumOverPastBuckets(const MetricDimensionKey& key) const { const auto& itr = mSumOverPastBuckets.find(key); if (itr != mSumOverPastBuckets.end()) { return itr->second; @@ -165,7 +165,7 @@ int64_t AnomalyTracker::getSumOverPastBuckets(const HashableDimensionKey& key) c return 0; } -bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const HashableDimensionKey& key, +bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const MetricDimensionKey& key, const int64_t& currentBucketValue) { if (currentBucketNum > mMostRecentBucketNum + 1) { // TODO: This creates a needless 0 entry in mSumOverPastBuckets. Fix this. @@ -175,7 +175,7 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const Hashab && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); } -void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const HashableDimensionKey& key) { +void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key) { // TODO: Why receive timestamp? RefractoryPeriod should always be based on real time right now. if (isInRefractoryPeriod(timestampNs, key)) { VLOG("Skipping anomaly declaration since within refractory period"); @@ -199,14 +199,14 @@ void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const HashableD StatsdStats::getInstance().noteAnomalyDeclared(mConfigKey, mAlert.id()); - // TODO: This should also take in the const HashableDimensionKey& key? + // TODO: This should also take in the const MetricDimensionKey& key? android::util::stats_write(android::util::ANOMALY_DETECTED, mConfigKey.GetUid(), mConfigKey.GetId(), mAlert.id()); } void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum, - const HashableDimensionKey& key, + const MetricDimensionKey& key, const int64_t& currentBucketValue) { if (detectAnomaly(currBucketNum, key, currentBucketValue)) { declareAnomaly(timestampNs, key); @@ -214,7 +214,7 @@ void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs, } bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs, - const HashableDimensionKey& key) { + const MetricDimensionKey& key) { const auto& it = mRefractoryPeriodEndsSec.find(key); if (it != mRefractoryPeriodEndsSec.end()) { if ((timestampNs / NS_PER_SEC) <= it->second) { @@ -226,7 +226,7 @@ bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs, return false; } -void AnomalyTracker::informSubscribers(const HashableDimensionKey& key) { +void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) { VLOG("informSubscribers called."); if (mSubscriptions.empty()) { ALOGE("Attempt to call with no subscribers."); diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h index 472c02c7ee7f20e7839a5a5670b47a530db28778..f01a97f86cf6c39ae9c1064dfb3cffb829b7b181 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.h +++ b/cmds/statsd/src/anomaly/AnomalyTracker.h @@ -48,19 +48,19 @@ public: // Adds a bucket. // Bucket index starts from 0. void addPastBucket(std::shared_ptr bucketValues, const int64_t& bucketNum); - void addPastBucket(const HashableDimensionKey& key, const int64_t& bucketValue, + void addPastBucket(const MetricDimensionKey& key, const int64_t& bucketValue, const int64_t& bucketNum); // Returns true if detected anomaly for the existing buckets on one or more dimension keys. - bool detectAnomaly(const int64_t& currBucketNum, const HashableDimensionKey& key, + bool detectAnomaly(const int64_t& currBucketNum, const MetricDimensionKey& key, const int64_t& currentBucketValue); // Informs incidentd about the detected alert. - void declareAnomaly(const uint64_t& timestampNs, const HashableDimensionKey& key); + void declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key); // Detects the alert and informs the incidentd when applicable. void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum, - const HashableDimensionKey& key, + const MetricDimensionKey& key, const int64_t& currentBucketValue); // Init the AnomalyMonitor which is shared across anomaly trackers. @@ -69,10 +69,10 @@ public: } // Helper function to return the sum value of past buckets at given dimension. - int64_t getSumOverPastBuckets(const HashableDimensionKey& key) const; + int64_t getSumOverPastBuckets(const MetricDimensionKey& key) const; // Helper function to return the value for a past bucket. - int64_t getPastBucketValue(const HashableDimensionKey& key, const int64_t& bucketNum) const; + int64_t getPastBucketValue(const MetricDimensionKey& key, const int64_t& bucketNum) const; // Returns the anomaly threshold. inline int64_t getAnomalyThreshold() const { @@ -81,7 +81,7 @@ public: // Returns the refractory period timestamp (in seconds) for the given key. // If there is no stored refractory period ending timestamp, returns 0. - uint32_t getRefractoryPeriodEndsSec(const HashableDimensionKey& key) const { + uint32_t getRefractoryPeriodEndsSec(const MetricDimensionKey& key) const { const auto& it = mRefractoryPeriodEndsSec.find(key); return it != mRefractoryPeriodEndsSec.end() ? it->second : 0; } @@ -124,7 +124,7 @@ protected: // declared for that dimension) ends, in seconds. Only anomalies that occur after this period // ends will be declared. // Entries may be, but are not guaranteed to be, removed after the period is finished. - unordered_map mRefractoryPeriodEndsSec; + unordered_map mRefractoryPeriodEndsSec; void flushPastBuckets(const int64_t& currBucketNum); @@ -135,7 +135,7 @@ protected: // and remove any items with value 0. void subtractBucketFromSum(const shared_ptr& bucket); - bool isInRefractoryPeriod(const uint64_t& timestampNs, const HashableDimensionKey& key); + bool isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key); // Calculates the corresponding bucket index within the circular array. size_t index(int64_t bucketNum) const; @@ -144,7 +144,7 @@ protected: virtual void resetStorage(); // Informs the subscribers that an anomaly has occurred. - void informSubscribers(const HashableDimensionKey& key); + void informSubscribers(const MetricDimensionKey& key); FRIEND_TEST(AnomalyTrackerTest, TestConsecutiveBuckets); FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets); diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp index 7576a38db51d73d563dd4c8c90e6217be0c36f4b..bbee9fa5358c249adbcd740d5644dfe2e20c3e10 100644 --- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp @@ -37,8 +37,8 @@ void DurationAnomalyTracker::resetStorage() { if (!mAlarms.empty()) VLOG("AnomalyTracker.resetStorage() called but mAlarms is NOT empty!"); } -void DurationAnomalyTracker::declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey, - const uint64_t& timestampNs) { +void DurationAnomalyTracker::declareAnomalyIfAlarmExpired(const MetricDimensionKey& dimensionKey, + const uint64_t& timestampNs) { auto itr = mAlarms.find(dimensionKey); if (itr == mAlarms.end()) { return; @@ -51,7 +51,7 @@ void DurationAnomalyTracker::declareAnomalyIfAlarmExpired(const HashableDimensio } } -void DurationAnomalyTracker::startAlarm(const HashableDimensionKey& dimensionKey, +void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, const uint64_t& timestampNs) { uint32_t timestampSec = static_cast(timestampNs / NS_PER_SEC); @@ -66,7 +66,7 @@ void DurationAnomalyTracker::startAlarm(const HashableDimensionKey& dimensionKey } } -void DurationAnomalyTracker::stopAlarm(const HashableDimensionKey& dimensionKey) { +void DurationAnomalyTracker::stopAlarm(const MetricDimensionKey& dimensionKey) { auto itr = mAlarms.find(dimensionKey); if (itr != mAlarms.end()) { mAlarms.erase(dimensionKey); @@ -77,7 +77,7 @@ void DurationAnomalyTracker::stopAlarm(const HashableDimensionKey& dimensionKey) } void DurationAnomalyTracker::stopAllAlarms() { - std::set keys; + std::set keys; for (auto itr = mAlarms.begin(); itr != mAlarms.end(); ++itr) { keys.insert(itr->first); } @@ -95,7 +95,7 @@ void DurationAnomalyTracker::informAlarmsFired(const uint64_t& timestampNs, // seldomly called. The alternative would be having AnomalyAlarms store information about the // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that is // rarely ever called. - unordered_map> matchedAlarms; + unordered_map> matchedAlarms; for (const auto& kv : mAlarms) { if (firedAlarms.count(kv.second) > 0) { matchedAlarms.insert({kv.first, kv.second}); diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h index 33e55ab850c9069a4976610f254df891ffddb2f1..052fdf5762892753c9873d8d5214af28173a6750 100644 --- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h +++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h @@ -32,10 +32,10 @@ public: virtual ~DurationAnomalyTracker(); // Starts the alarm at the given timestamp. - void startAlarm(const HashableDimensionKey& dimensionKey, const uint64_t& eventTime); + void startAlarm(const MetricDimensionKey& dimensionKey, const uint64_t& eventTime); // Stops the alarm. - void stopAlarm(const HashableDimensionKey& dimensionKey); + void stopAlarm(const MetricDimensionKey& dimensionKey); // Stop all the alarms owned by this tracker. void stopAllAlarms(); @@ -46,7 +46,7 @@ public: } // Declares the anomaly when the alarm expired given the current timestamp. - void declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey, + void declareAnomalyIfAlarmExpired(const MetricDimensionKey& dimensionKey, const uint64_t& timestampNs); // Declares an anomaly for each alarm in firedAlarms that belongs to this DurationAnomalyTracker @@ -59,7 +59,7 @@ public: protected: // The alarms owned by this tracker. The alarm monitor also shares the alarm pointers when they // are still active. - std::unordered_map> mAlarms; + std::unordered_map> mAlarms; // Anomaly alarm monitor. sp mAnomalyMonitor; diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index b32af027f2fd8dcb695bfb23fd9883e8467a3f05..e58c53506c54e569ffa7b58042a1036d2f66450b 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -93,11 +93,16 @@ message Atom { WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53; LmkStateChanged lmk_state_changed = 54; AppStartMemoryStateCaptured app_start_memory_state_captured = 55; + ShutdownSequenceReported shutdown_sequence_reported = 56; + BootSequenceReported boot_sequence_reported = 57; + DaveyOccurred davey_occurred = 58; + OverlayStateChanged overlay_state_changed = 59; + ForegroundServiceStateChanged foreground_service_state_changed = 60; // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15. } // Pulled events will start at field 10000. - // Next: 10019 + // Next: 10021 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001; @@ -118,6 +123,8 @@ message Atom { CpuActiveTime cpu_active_time = 10016; CpuClusterTime cpu_cluster_time = 10017; DiskSpace disk_space = 10018; + RemainingBatteryCapacity remaining_battery_capacity = 10019; + FullBatteryCapacity full_battery_capacity = 10020; } } @@ -668,6 +675,67 @@ message WifiMulticastLockStateChanged { optional State state = 2; } +/** + * Logs shutdown reason and duration on next boot. + * + * Logged from: + * frameworks/base/core/java/com/android/server/BootReceiver.java + */ +message ShutdownSequenceReported { + // True if shutdown is for a reboot. Default: false if we do not know. + optional bool reboot = 1; + + // Reason for shutdown. Eg: userrequested. Default: "". + optional string reason = 2; + + // Beginning of shutdown time in ms using wall clock time since unix epoch. + // Default: 0 if no start time received. + optional int64 start_time_ms = 3; + + // Duration of shutdown in ms. Default: 0 if no duration received. + optional int64 duration_ms = 4; +} + + +/** + * Logs boot reason and duration. + * + * Logged from: + * system/core/bootstat/bootstat.cpp + */ +message BootSequenceReported { + // Reason for bootloader boot. Eg. reboot. See bootstat.cpp for larger list + // Default: "" if not available. + optional string bootloader_reason = 1; + + // Reason for system boot. Eg. bootloader, reboot,userrequested + // Default: "" if not available. + optional string system_reason = 2; + + // End of boot time in ms from unix epoch using system wall clock. + optional int64 end_time_ms = 3; + + // Total boot duration in ms. + optional int64 total_duration_ms = 4; + + // Bootloader duration in ms. + optional int64 bootloader_duration_ms = 5; + + // Time since last boot in ms. Default: 0 if not available. + optional int64 time_since_last_boot = 6; +} + +/** + * Logs the duration of a davey (jank of >=700ms) when it occurs + * + * Logged from: + * frameworks/base/libs/hwui/JankTracker.cpp + */ +message DaveyOccurred { + // Amount of time it took to render the frame. Should be >=700ms. + optional int64 jank_duration_ms = 1; +} + /** * Logs phone signal strength changes. * @@ -705,8 +773,8 @@ message SettingChanged { // The tag used with the is_default for resetting sets of settings. This is generally null. optional string tag = 5; - // 1 indicates that this setting with tag should be resettable. - optional int32 is_default = 6; + // True if this setting with tag should be resettable. + optional bool is_default = 6; // The user ID associated. Defined in android/os/UserHandle.java optional int32 user = 7; @@ -912,6 +980,44 @@ message PictureInPictureStateChanged { optional State state = 4; } +/** + * Logs overlay action + * Logged from: + * services/core/java/com/android/server/wm/Session.java + */ +message OverlayStateChanged { + optional int32 uid = 1; + + optional string package_name = 2; + + optional bool using_alert_window = 3; + + enum State { + ENTERED = 1; + EXITED = 2; + } + optional State state = 4; +} + +/* + * Logs foreground service starts and stops. + * Note that this is not when a service starts or stops, but when it is + * considered foreground. + * Logged from + * //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java + */ +message ForegroundServiceStateChanged { + optional int32 uid = 1; + // package_name + "/" + class_name + optional string short_name = 2; + + enum State { + ENTER = 1; + EXIT = 2; + } + optional State state = 3; +} + /** * Pulls bytes transferred via wifi (Sum of foreground and background usage). * @@ -1053,9 +1159,12 @@ message IsolatedUidChanged { optional int32 isolated_uid = 2; - // 1 denotes we're creating an isolated uid and 0 denotes removal. We expect an isolated uid to - // be removed before if it's used for another parent uid. - optional int32 is_create = 3; + // We expect an isolated uid to be removed before if it's used for another parent uid. + enum Event { + REMOVED = 0; + CREATED = 1; + } + optional Event event = 3; } /** @@ -1358,3 +1467,20 @@ message DiskSpace { // available bytes in download cache or temp directories optional uint64 temp_available_bytes = 3; } + +/** + * Pulls battery coulomb counter, which is the remaining battery charge in uAh. + * Logged from: frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp + */ +message RemainingBatteryCapacity { + optional int32 charge_uAh = 1; +} + +/** + * Pulls battery capacity, which is the battery capacity when full in uAh. + * Logged from: frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp + */ +message FullBatteryCapacity { + optional int32 capacity_uAh = 1; +} + diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp index ea6586c25d80707bbeaa4b3fbabdf209a8ac1115..4c20ccb61afe506397cd5cc4babc4ff2d77b1a70 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp +++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp @@ -78,6 +78,7 @@ bool CombinationConditionTracker::init(const vector& allConditionConf return false; } + bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers, conditionIdIndexMap, stack); @@ -88,8 +89,10 @@ bool CombinationConditionTracker::init(const vector& allConditionConf ALOGW("Child initialization success %lld ", (long long)child); } + if (allConditionTrackers[childIndex]->isSliced()) { + setSliced(true); + } mChildren.push_back(childIndex); - mTrackerIndex.insert(childTracker->getLogTrackerIndex().begin(), childTracker->getLogTrackerIndex().end()); } @@ -105,11 +108,15 @@ bool CombinationConditionTracker::init(const vector& allConditionConf void CombinationConditionTracker::isConditionMet( const ConditionKey& conditionParameters, const vector>& allConditions, - vector& conditionCache) const { + const FieldMatcher& dimensionFields, + vector& conditionCache, + std::unordered_set &dimensionsKeySet) const { + // So far, this is fine as there is at most one child having sliced output. for (const int childIndex : mChildren) { if (conditionCache[childIndex] == ConditionState::kNotEvaluated) { allConditions[childIndex]->isConditionMet(conditionParameters, allConditions, - conditionCache); + dimensionFields, conditionCache, + dimensionsKeySet); } } conditionCache[mIndex] = @@ -127,6 +134,7 @@ void CombinationConditionTracker::evaluateCondition( } for (const int childIndex : mChildren) { + // So far, this is fine as there is at most one child having sliced output. if (nonSlicedConditionCache[childIndex] == ConditionState::kNotEvaluated) { const sp& child = mAllConditions[childIndex]; child->evaluateCondition(event, eventMatcherValues, mAllConditions, @@ -159,6 +167,24 @@ void CombinationConditionTracker::evaluateCondition( } } +ConditionState CombinationConditionTracker::getMetConditionDimension( + const std::vector>& allConditions, + const FieldMatcher& dimensionFields, + std::unordered_set &dimensionsKeySet) const { + vector conditionCache(allConditions.size(), ConditionState::kNotEvaluated); + // So far, this is fine as there is at most one child having sliced output. + for (const int childIndex : mChildren) { + conditionCache[childIndex] = conditionCache[childIndex] | + allConditions[childIndex]->getMetConditionDimension( + allConditions, dimensionFields, dimensionsKeySet); + } + evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache); + if (conditionCache[mIndex] == ConditionState::kTrue && dimensionsKeySet.empty()) { + dimensionsKeySet.insert(DEFAULT_DIMENSION_KEY); + } + return conditionCache[mIndex]; +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h index dfd3837f31f49200ae9b0c121e3fa03e9fa8e065..0b7f9492d628dfb335628bebeed14b7138596955 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.h +++ b/cmds/statsd/src/condition/CombinationConditionTracker.h @@ -41,12 +41,20 @@ public: std::vector& conditionCache, std::vector& changedCache) override; - void isConditionMet(const ConditionKey& conditionParameters, - const std::vector>& allConditions, - std::vector& conditionCache) const override; + void isConditionMet( + const ConditionKey& conditionParameters, + const std::vector>& allConditions, + const FieldMatcher& dimensionFields, + std::vector& conditionCache, + std::unordered_set &dimensionsKeySet) const override; + ConditionState getMetConditionDimension( + const std::vector>& allConditions, + const FieldMatcher& dimensionFields, + std::unordered_set &dimensionsKeySet) const override; private: LogicalOperation mLogicalOperation; + // Store index of the children Predicates. // We don't store string name of the Children, because we want to get rid of the hash map to // map the name to object. We don't want to store smart pointers to children, because it diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h index 773860f429b10f750ac988f66366b0ac5e344f72..81abbdb36ee4af68f52335830f62ede8f6a18bf9 100644 --- a/cmds/statsd/src/condition/ConditionTracker.h +++ b/cmds/statsd/src/condition/ConditionTracker.h @@ -24,6 +24,7 @@ #include #include +#include #include namespace android { @@ -84,10 +85,19 @@ public: // [allConditions]: all condition trackers. This is needed because the condition evaluation is // done recursively // [conditionCache]: the cache holding the condition evaluation values. + // [dimensionsKeySet]: the dimensions where the sliced condition is true. For combination + // condition, it assumes that only one child predicate is sliced. virtual void isConditionMet( const ConditionKey& conditionParameters, const std::vector>& allConditions, - std::vector& conditionCache) const = 0; + const FieldMatcher& dimensionFields, + std::vector& conditionCache, + std::unordered_set &dimensionsKeySet) const = 0; + + virtual ConditionState getMetConditionDimension( + const std::vector>& allConditions, + const FieldMatcher& dimensionFields, + std::unordered_set &dimensionsKeySet) const = 0; // return the list of LogMatchingTracker index that this ConditionTracker uses. virtual const std::set& getLogTrackerIndex() const { @@ -98,6 +108,10 @@ public: mSliced = mSliced | sliced; } + bool isSliced() const { + return mSliced; + } + protected: const int64_t mConditionId; diff --git a/cmds/statsd/src/condition/ConditionWizard.cpp b/cmds/statsd/src/condition/ConditionWizard.cpp index d99c2ccd1fdae7b4d2fcb88a34efc966596af3e3..0427700fec91f13be332f8dba69436851161cd43 100644 --- a/cmds/statsd/src/condition/ConditionWizard.cpp +++ b/cmds/statsd/src/condition/ConditionWizard.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ #include "ConditionWizard.h" +#include namespace android { namespace os { @@ -23,14 +24,26 @@ using std::map; using std::string; using std::vector; -ConditionState ConditionWizard::query(const int index, - const ConditionKey& parameters) { +ConditionState ConditionWizard::query( + const int index, const ConditionKey& parameters, + const FieldMatcher& dimensionFields, + std::unordered_set *dimensionKeySet) { + vector cache(mAllConditions.size(), ConditionState::kNotEvaluated); - mAllConditions[index]->isConditionMet(parameters, mAllConditions, cache); + mAllConditions[index]->isConditionMet( + parameters, mAllConditions, dimensionFields, cache, *dimensionKeySet); return cache[index]; } +ConditionState ConditionWizard::getMetConditionDimension( + const int index, const FieldMatcher& dimensionFields, + std::unordered_set *dimensionsKeySet) const { + + return mAllConditions[index]->getMetConditionDimension(mAllConditions, dimensionFields, + *dimensionsKeySet); +} + } // namespace statsd } // namespace os } // namespace android \ No newline at end of file diff --git a/cmds/statsd/src/condition/ConditionWizard.h b/cmds/statsd/src/condition/ConditionWizard.h index 4ff5c07e210f12483bc36b9816d30807747385ab..b38b59ff4cd0bd1f00f59f600136d5a4c3fb6256 100644 --- a/cmds/statsd/src/condition/ConditionWizard.h +++ b/cmds/statsd/src/condition/ConditionWizard.h @@ -41,7 +41,14 @@ public: // the conditionParameters contains the parameters for it's children SimpleConditionTrackers. virtual ConditionState query( const int conditionIndex, - const ConditionKey& conditionParameters); + const ConditionKey& conditionParameters, + const FieldMatcher& dimensionFields, + std::unordered_set *dimensionKeySet); + + virtual ConditionState getMetConditionDimension( + const int index, + const FieldMatcher& dimensionFields, + std::unordered_set *dimensionsKeySet) const; private: std::vector> mAllConditions; diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index 7a1bb0c71373afd57d2dc57b346982afb1822a5c..25265d5dabd746729326f047b674630f1bda2b09 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -104,6 +104,9 @@ bool SimpleConditionTracker::init(const vector& allConditionConfig, vector& stack) { // SimpleConditionTracker does not have dependency on other conditions, thus we just return // if the initialization was successful. + if (mOutputDimensions.has_field() || mOutputDimensions.child_size() > 0) { + setSliced(true); + } return mInitialized; } @@ -234,11 +237,12 @@ void SimpleConditionTracker::handleConditionEvent(const HashableDimensionKey& ou conditionChangedCache[mIndex] == true); } -void SimpleConditionTracker::evaluateCondition(const LogEvent& event, - const vector& eventMatcherValues, - const vector>& mAllConditions, - vector& conditionCache, - vector& conditionChangedCache) { +void SimpleConditionTracker::evaluateCondition( + const LogEvent& event, + const vector& eventMatcherValues, + const vector>& mAllConditions, + vector& conditionCache, + vector& conditionChangedCache) { if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { // it has been evaluated. VLOG("Yes, already evaluated, %lld %d", @@ -271,7 +275,7 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, if (mSliced) { // if the condition result is sliced. metrics won't directly get value from the // cache, so just set any value other than kNotEvaluated. - conditionCache[mIndex] = ConditionState::kUnknown; + conditionCache[mIndex] = mInitialValue; } else { const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); if (itr == mSlicedConditionState.end()) { @@ -289,7 +293,8 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, } // outputKey is the output values. e.g, uid:1234 - const std::vector outputValues = getDimensionKeys(event, mOutputDimensions); + std::vector outputValues; + getDimensionKeys(event, mOutputDimensions, &outputValues); if (outputValues.size() == 0) { // The original implementation would generate an empty string dimension hash when condition // is not sliced. @@ -309,10 +314,8 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, vector dimensionalConditionCache(conditionCache.size(), ConditionState::kNotEvaluated); vector dimensionalConditionChangedCache(conditionChangedCache.size(), false); - handleConditionEvent(HashableDimensionKey(outputValue), matchedState == 1, dimensionalConditionCache, dimensionalConditionChangedCache); - OrConditionState(dimensionalConditionCache, &conditionCache); OrBooleanVector(dimensionalConditionChangedCache, &conditionChangedCache); } @@ -322,49 +325,112 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, void SimpleConditionTracker::isConditionMet( const ConditionKey& conditionParameters, const vector>& allConditions, - vector& conditionCache) const { + const FieldMatcher& dimensionFields, + vector& conditionCache, + std::unordered_set &dimensionsKeySet) const { + if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { + // it has been evaluated. + VLOG("Yes, already evaluated, %lld %d", + (long long)mConditionId, conditionCache[mIndex]); + return; + } const auto pair = conditionParameters.find(mConditionId); - if (pair == conditionParameters.end() && mOutputDimensions.child_size() > 0) { - ALOGE("Predicate %lld output has dimension, but it's not specified in the query!", - (long long)mConditionId); - conditionCache[mIndex] = mInitialValue; + if (pair == conditionParameters.end()) { + ConditionState conditionState = ConditionState::kNotEvaluated; + if (dimensionFields.has_field() && dimensionFields.child_size() > 0 && + dimensionFields.field() == mOutputDimensions.field()) { + conditionState = conditionState | getMetConditionDimension( + allConditions, dimensionFields, dimensionsKeySet); + } else { + conditionState = conditionState | mInitialValue; + if (!mSliced) { + const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); + if (itr != mSlicedConditionState.end()) { + ConditionState sliceState = + itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; + conditionState = conditionState | sliceState; + } + } + } + conditionCache[mIndex] = conditionState; return; } - std::vector defaultKeys = {DEFAULT_DIMENSION_KEY}; + std::vector defaultKeys = { DEFAULT_DIMENSION_KEY }; const std::vector &keys = (pair == conditionParameters.end()) ? defaultKeys : pair->second; ConditionState conditionState = ConditionState::kNotEvaluated; - for (const auto& key : keys) { + for (size_t i = 0; i < keys.size(); ++i) { + const HashableDimensionKey& key = keys[i]; auto startedCountIt = mSlicedConditionState.find(key); if (startedCountIt != mSlicedConditionState.end()) { - conditionState = conditionState | - (startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse); + ConditionState sliceState = + startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; + conditionState = conditionState | sliceState; + if (sliceState == ConditionState::kTrue && dimensionFields.has_field()) { + HashableDimensionKey dimensionKey; + if (getSubDimension(startedCountIt->first.getDimensionsValue(), dimensionFields, + dimensionKey.getMutableDimensionsValue())) { + dimensionsKeySet.insert(dimensionKey); + } + } } else { // For unseen key, check whether the require dimensions are subset of sliced condition // output. - bool seenDimension = false; + conditionState = conditionState | mInitialValue; for (const auto& slice : mSlicedConditionState) { - if (IsSubDimension(slice.first.getDimensionsValue(), - key.getDimensionsValue())) { - seenDimension = true; - conditionState = conditionState | - (slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse); - } - if (conditionState == ConditionState::kTrue) { - break; + ConditionState sliceState = + slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse; + if (IsSubDimension(slice.first.getDimensionsValue(), key.getDimensionsValue())) { + conditionState = conditionState | sliceState; + if (sliceState == ConditionState::kTrue && dimensionFields.has_field()) { + HashableDimensionKey dimensionKey; + if (getSubDimension(slice.first.getDimensionsValue(), + dimensionFields, dimensionKey.getMutableDimensionsValue())) { + dimensionsKeySet.insert(dimensionKey); + } + } } } - if (!seenDimension) { - conditionState = conditionState | mInitialValue; - } } } conditionCache[mIndex] = conditionState; VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]); } +ConditionState SimpleConditionTracker::getMetConditionDimension( + const std::vector>& allConditions, + const FieldMatcher& dimensionFields, + std::unordered_set &dimensionsKeySet) const { + ConditionState conditionState = mInitialValue; + if (!dimensionFields.has_field() || + !mOutputDimensions.has_field() || + dimensionFields.field() != mOutputDimensions.field()) { + const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); + if (itr != mSlicedConditionState.end()) { + ConditionState sliceState = + itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; + conditionState = conditionState | sliceState; + } + return conditionState; + } + + for (const auto& slice : mSlicedConditionState) { + ConditionState sliceState = + slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse; + DimensionsValue dimensionsValue; + conditionState = conditionState | sliceState; + HashableDimensionKey dimensionKey; + if (sliceState == ConditionState::kTrue && + getSubDimension(slice.first.getDimensionsValue(), dimensionFields, + dimensionKey.getMutableDimensionsValue())) { + dimensionsKeySet.insert(dimensionKey); + } + } + return conditionState; +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h index 815b445a8c5bfe19c5270167af114c4fc685cd54..ce9a02d4a795357694831cace5d4817c7d72d518 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.h +++ b/cmds/statsd/src/condition/SimpleConditionTracker.h @@ -48,7 +48,14 @@ public: void isConditionMet(const ConditionKey& conditionParameters, const std::vector>& allConditions, - std::vector& conditionCache) const override; + const FieldMatcher& dimensionFields, + std::vector& conditionCache, + std::unordered_set &dimensionsKeySet) const override; + + ConditionState getMetConditionDimension( + const std::vector>& allConditions, + const FieldMatcher& dimensionFields, + std::unordered_set &dimensionsKeySet) const override; private: const ConfigKey mConfigKey; @@ -73,7 +80,8 @@ private: void handleStopAll(std::vector& conditionCache, std::vector& changedCache); - void handleConditionEvent(const HashableDimensionKey& outputKey, bool matchStart, + void handleConditionEvent(const HashableDimensionKey& outputKey, + bool matchStart, std::vector& conditionCache, std::vector& changedCache); diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp index ddfb8d12a33596d7b861d30455ba3852994190fe..0ab33cfbaea11d9c890d5696ab13a49cb3fd0d76 100644 --- a/cmds/statsd/src/condition/condition_util.cpp +++ b/cmds/statsd/src/condition/condition_util.cpp @@ -116,28 +116,33 @@ void OrBooleanVector(const std::vector& ref, vector * ored) { } } -void getFieldsFromFieldMatcher(const FieldMatcher& matcher, const Field& parentField, - std::vector *allFields) { - Field newParent = parentField; - Field* leaf = getSingleLeaf(&newParent); - leaf->set_field(matcher.field()); +void getFieldsFromFieldMatcher(const FieldMatcher& matcher, Field* rootField, Field* leafField, + std::vector *allFields) { + if (matcher.has_position()) { + leafField->set_position_index(0); + } if (matcher.child_size() == 0) { - allFields->push_back(newParent); + allFields->push_back(*rootField); return; } for (int i = 0; i < matcher.child_size(); ++i) { - leaf->add_child(); - getFieldsFromFieldMatcher(matcher.child(i), newParent, allFields); + Field* newLeafField = leafField->add_child(); + newLeafField->set_field(matcher.child(i).field()); + getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields); } } void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector *allFields) { - Field parentField; - getFieldsFromFieldMatcher(matcher, parentField, allFields); + if (!matcher.has_field()) { + return; + } + Field rootField; + rootField.set_field(matcher.field()); + getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields); } void flattenValueLeaves(const DimensionsValue& value, - std::vector *allLaves) { + std::vector *allLaves) { switch (value.value_case()) { case DimensionsValue::ValueCase::kValueStr: case DimensionsValue::ValueCase::kValueInt: @@ -145,7 +150,7 @@ void flattenValueLeaves(const DimensionsValue& value, case DimensionsValue::ValueCase::kValueBool: case DimensionsValue::ValueCase::kValueFloat: case DimensionsValue::ValueCase::VALUE_NOT_SET: - allLaves->push_back(value); + allLaves->push_back(&value); break; case DimensionsValue::ValueCase::kValueTuple: for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) { @@ -155,45 +160,44 @@ void flattenValueLeaves(const DimensionsValue& value, } } -std::vector getDimensionKeysForCondition( - const LogEvent& event, const MetricConditionLink& link) { +void getDimensionKeysForCondition( + const LogEvent& event, const MetricConditionLink& link, + std::vector *hashableDimensionKeys) { std::vector whatFields; getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields); std::vector conditionFields; getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields); - std::vector hashableDimensionKeys; - // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and // directly construct the full condition value tree. - std::vector whatValues = getDimensionKeys(event, link.fields_in_what()); + std::vector whatValues; + getDimensionKeys(event, link.fields_in_what(), &whatValues); for (size_t i = 0; i < whatValues.size(); ++i) { - std::vector whatLeaves; + std::vector whatLeaves; flattenValueLeaves(whatValues[i], &whatLeaves); if (whatLeaves.size() != whatFields.size() || whatLeaves.size() != conditionFields.size()) { ALOGE("Dimensions between what and condition not equal."); - return hashableDimensionKeys; + return; } FieldValueMap conditionValueMap; for (size_t j = 0; j < whatLeaves.size(); ++j) { - if (!setFieldInLeafValueProto(conditionFields[j], &whatLeaves[j])) { + DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]]; + *conditionValue = *whatLeaves[i]; + if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) { ALOGE("Not able to reset the field for condition leaf value."); - return hashableDimensionKeys; + return; } - conditionValueMap.insert(std::make_pair(conditionFields[j], whatLeaves[j])); } - std::vector conditionValues; - findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValues); - if (conditionValues.size() != 1) { + std::vector conditionValueTrees; + findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees); + if (conditionValueTrees.size() != 1) { ALOGE("Not able to find unambiguous field value in condition atom."); continue; } - hashableDimensionKeys.push_back(HashableDimensionKey(conditionValues[0])); + hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0])); } - - return hashableDimensionKeys; } } // namespace statsd diff --git a/cmds/statsd/src/condition/condition_util.h b/cmds/statsd/src/condition/condition_util.h index 598027b7e366094a6ca1aa1ac7002107979308af..a7288beb69ca41b6f8411de86d0e9c2031bfba0e 100644 --- a/cmds/statsd/src/condition/condition_util.h +++ b/cmds/statsd/src/condition/condition_util.h @@ -40,8 +40,9 @@ ConditionState evaluateCombinationCondition(const std::vector& children, const LogicalOperation& operation, const std::vector& conditionCache); -std::vector getDimensionKeysForCondition( - const LogEvent& event, const MetricConditionLink& link); +void getDimensionKeysForCondition( + const LogEvent& event, const MetricConditionLink& link, + std::vector *dimensionKeys); } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp index bb7a044fa8cef5c1c88ce4f640a2841302a08fce..8a2e87128319cc250ee807a866226912ff0e5931 100644 --- a/cmds/statsd/src/dimension.cpp +++ b/cmds/statsd/src/dimension.cpp @@ -38,7 +38,7 @@ DimensionsValue getSingleLeafValue(const DimensionsValue& value) { return *leafValue; } -void appendLeafNodeToParent(const Field& field, +void appendLeafNodeToTree(const Field& field, const DimensionsValue& value, DimensionsValue* parentValue) { if (field.child_size() <= 0) { @@ -58,24 +58,24 @@ void appendLeafNodeToParent(const Field& field, parentValue->mutable_value_tuple()->add_dimensions_value(); idx = parentValue->mutable_value_tuple()->dimensions_value_size() - 1; } - appendLeafNodeToParent( + appendLeafNodeToTree( field.child(0), value, parentValue->mutable_value_tuple()->mutable_dimensions_value(idx)); } -void addNodeToRootDimensionsValues(const Field& field, - const DimensionsValue& node, - std::vector* rootValues) { - if (rootValues == nullptr) { +void appendLeafNodeToTrees(const Field& field, + const DimensionsValue& node, + std::vector* rootTrees) { + if (rootTrees == nullptr) { return; } - if (rootValues->empty()) { - DimensionsValue rootValue; - appendLeafNodeToParent(field, node, &rootValue); - rootValues->push_back(rootValue); + if (rootTrees->empty()) { + DimensionsValue tree; + appendLeafNodeToTree(field, node, &tree); + rootTrees->push_back(tree); } else { - for (size_t i = 0; i < rootValues->size(); ++i) { - appendLeafNodeToParent(field, node, &rootValues->at(i)); + for (size_t i = 0; i < rootTrees->size(); ++i) { + appendLeafNodeToTree(field, node, &rootTrees->at(i)); } } } @@ -85,22 +85,25 @@ namespace { void findDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector* rootDimensionsValues); void findNonRepeatedDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector* rootValues) { if (matcher.child_size() > 0) { + Field* newLeafField = leafField->add_child(); for (const auto& childMatcher : matcher.child()) { - Field childField = field; - appendLeaf(&childField, childMatcher.field()); - findDimensionsValues(fieldValueMap, childMatcher, childField, rootValues); + newLeafField->set_field(childMatcher.field()); + findDimensionsValues(fieldValueMap, childMatcher, rootField, newLeafField, rootValues); } + leafField->clear_child(); } else { - auto ret = fieldValueMap.equal_range(field); + auto ret = fieldValueMap.equal_range(*rootField); int found = 0; for (auto it = ret.first; it != ret.second; ++it) { found++; @@ -113,40 +116,43 @@ void findNonRepeatedDimensionsValues( ALOGE("Found multiple values for optional field."); return; } - addNodeToRootDimensionsValues(field, ret.first->second, rootValues); + appendLeafNodeToTrees(*rootField, ret.first->second, rootValues); } } void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector* rootValues) { if (matcher.position() == Position::FIRST) { - Field first_field = field; - setPositionForLeaf(&first_field, 0); - findNonRepeatedDimensionsValues(fieldValueMap, matcher, first_field, rootValues); + leafField->set_position_index(0); + findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, rootValues); + leafField->clear_position_index(); } else { - auto itLower = fieldValueMap.lower_bound(field); + auto itLower = fieldValueMap.lower_bound(*rootField); if (itLower == fieldValueMap.end()) { return; } - Field next_field = field; - getNextField(&next_field); - auto itUpper = fieldValueMap.lower_bound(next_field); + const int leafFieldNum = leafField->field(); + leafField->set_field(leafFieldNum + 1); + auto itUpper = fieldValueMap.lower_bound(*rootField); + // Resets the field number. + leafField->set_field(leafFieldNum); switch (matcher.position()) { case Position::LAST: { itUpper--; if (itUpper != fieldValueMap.end()) { - Field last_field = field; - int last_index = getPositionByReferenceField(field, itUpper->first); + int last_index = getPositionByReferenceField(*rootField, itUpper->first); if (last_index < 0) { return; } - setPositionForLeaf(&last_field, last_index); + leafField->set_position_index(last_index); findNonRepeatedDimensionsValues( - fieldValueMap, matcher, last_field, rootValues); + fieldValueMap, matcher, rootField, leafField, rootValues); + leafField->clear_position_index(); } } break; @@ -154,20 +160,20 @@ void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap, { std::set indexes; for (auto it = itLower; it != itUpper; ++it) { - int index = getPositionByReferenceField(field, it->first); + int index = getPositionByReferenceField(*rootField, it->first); if (index >= 0) { indexes.insert(index); } } if (!indexes.empty()) { - Field any_field = field; std::vector allValues; for (const int index : indexes) { - setPositionForLeaf(&any_field, index); + leafField->set_position_index(index); std::vector newValues = *rootValues; findNonRepeatedDimensionsValues( - fieldValueMap, matcher, any_field, &newValues); + fieldValueMap, matcher, rootField, leafField, &newValues); allValues.insert(allValues.end(), newValues.begin(), newValues.end()); + leafField->clear_position_index(); } rootValues->clear(); rootValues->insert(rootValues->end(), allValues.begin(), allValues.end()); @@ -183,12 +189,15 @@ void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap, void findDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector* rootDimensionsValues) { if (!matcher.has_position()) { - findNonRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues); + findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, + rootDimensionsValues); } else { - findRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues); + findRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, + rootDimensionsValues); } } @@ -198,59 +207,55 @@ void findDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, std::vector* rootDimensionsValues) { - findDimensionsValues(fieldValueMap, matcher, - buildSimpleAtomField(matcher.field()), rootDimensionsValues); + Field rootField; + buildSimpleAtomField(matcher.field(), &rootField); + findDimensionsValues(fieldValueMap, matcher, &rootField, &rootField, rootDimensionsValues); } -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId) { - FieldMatcher matcher; - matcher.set_field(tagId); - return matcher; +void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher) { + matcher->set_field(tagId); } -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum) { - FieldMatcher matcher; - matcher.set_field(tagId); - matcher.add_child()->set_field(atomFieldNum); - return matcher; +void buildSimpleAtomFieldMatcher(const int tagId, const int fieldNum, FieldMatcher* matcher) { + matcher->set_field(tagId); + matcher->add_child()->set_field(fieldNum); } constexpr int ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO = 1; constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1; constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2; -FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position) { - FieldMatcher matcher; - matcher.set_field(tagId); - auto child = matcher.add_child(); +void buildAttributionUidFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher) { + matcher->set_field(tagId); + auto child = matcher->add_child(); child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO); child->set_position(position); child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); - return matcher; } -FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position) { - FieldMatcher matcher; - matcher.set_field(tagId); - FieldMatcher* child = matcher.add_child(); +void buildAttributionTagFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher) { + matcher->set_field(tagId); + FieldMatcher* child = matcher->add_child(); child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO); child->set_position(position); child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); - return matcher; } -FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position) { - FieldMatcher matcher; - matcher.set_field(tagId); - FieldMatcher* child = matcher.add_child(); +void buildAttributionFieldMatcher(const int tagId, const Position position, FieldMatcher* matcher) { + matcher->set_field(tagId); + FieldMatcher* child = matcher->add_child(); child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO); child->set_position(position); child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); - return matcher; } void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) { + if (!value.has_field()) { + return; + } *flattened += std::to_string(value.field()); *flattened += ":"; switch (value.value_case()) { @@ -284,28 +289,6 @@ void DimensionsValueToString(const DimensionsValue& value, std::string *flattene } } -void getDimensionsValueLeafNodes( - const DimensionsValue& value, std::vector *leafNodes) { - switch (value.value_case()) { - case DimensionsValue::ValueCase::kValueStr: - case DimensionsValue::ValueCase::kValueInt: - case DimensionsValue::ValueCase::kValueLong: - case DimensionsValue::ValueCase::kValueBool: - case DimensionsValue::ValueCase::kValueFloat: - leafNodes->push_back(value); - break; - case DimensionsValue::ValueCase::kValueTuple: - for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) { - getDimensionsValueLeafNodes(value.value_tuple().dimensions_value(i), leafNodes); - } - break; - case DimensionsValue::ValueCase::VALUE_NOT_SET: - break; - default: - break; - } -} - std::string DimensionsValueToString(const DimensionsValue& value) { std::string flatten; DimensionsValueToString(value, &flatten); @@ -372,6 +355,46 @@ long getLongFromDimenValue(const DimensionsValue& dimensionValue) { } } +bool getSubDimension(const DimensionsValue& dimension, const FieldMatcher& matcher, + DimensionsValue* subDimension) { + if (!matcher.has_field()) { + return false; + } + if (matcher.field() != dimension.field()) { + return false; + } + if (matcher.child_size() <= 0) { + if (dimension.value_case() == DimensionsValue::ValueCase::kValueTuple || + dimension.value_case() == DimensionsValue::ValueCase::VALUE_NOT_SET) { + return false; + } + *subDimension = dimension; + return true; + } else { + if (dimension.value_case() != DimensionsValue::ValueCase::kValueTuple) { + return false; + } + bool found_value = true; + auto value_tuple = dimension.value_tuple(); + subDimension->set_field(dimension.field()); + for (int i = 0; found_value && i < matcher.child_size(); ++i) { + int j = 0; + for (; j < value_tuple.dimensions_value_size(); ++j) { + if (value_tuple.dimensions_value(j).field() == matcher.child(i).field()) { + break; + } + } + if (j < value_tuple.dimensions_value_size()) { + found_value &= getSubDimension(value_tuple.dimensions_value(j), matcher.child(i), + subDimension->mutable_value_tuple()->add_dimensions_value()); + } else { + found_value = false; + } + } + return found_value; + } +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/dimension.h b/cmds/statsd/src/dimension.h index d0f96a2abe6b4f593a7827f7321746399951b198..138c6e9b0160c3fd2642f1af149f38ea6d18e56d 100644 --- a/cmds/statsd/src/dimension.h +++ b/cmds/statsd/src/dimension.h @@ -33,8 +33,7 @@ const DimensionsValue* getSingleLeafValue(const DimensionsValue* value); DimensionsValue getSingleLeafValue(const DimensionsValue& value); // Appends the leaf node to the parent tree. -void appendLeafNodeToParent(const Field& field, const DimensionsValue& value, - DimensionsValue* parentValue); +void appendLeafNodeToTree(const Field& field, const DimensionsValue& value, DimensionsValue* tree); // Constructs the DimensionsValue protos from the FieldMatcher. Each DimensionsValue proto // represents a tree. When the input proto has repeated fields and the input "dimensions" wants @@ -45,13 +44,16 @@ void findDimensionsValues( std::vector* rootDimensionsValues); // Utils to build FieldMatcher proto for simple one-depth atoms. -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum); -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId); +void buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum, FieldMatcher* matcher); +void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher); // Utils to build FieldMatcher proto for attribution nodes. -FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position); -FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position); -FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position); +void buildAttributionUidFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher); +void buildAttributionTagFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher); +void buildAttributionFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher); // Utils to print pretty string for DimensionsValue proto. std::string DimensionsValueToString(const DimensionsValue& value); @@ -61,6 +63,9 @@ bool IsSubDimension(const DimensionsValue& dimension, const DimensionsValue& sub // Helper function to get long value from the DimensionsValue proto. long getLongFromDimenValue(const DimensionsValue& dimensionValue); + +bool getSubDimension(const DimensionsValue& dimension, const FieldMatcher& matcher, + DimensionsValue* subDimension); } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72fb5ffd4b90f71ce92f8768fc729a74be9a6519 --- /dev/null +++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#define DEBUG true // STOPSHIP if true +#include "Log.h" + +#include +#include +#include "external/ResourceHealthManagerPuller.h" +#include "external/StatsPuller.h" + +#include "ResourceHealthManagerPuller.h" +#include "logd/LogEvent.h" +#include "statslog.h" + +using android::hardware::hidl_vec; +using android::hardware::health::V2_0::get_health_service; +using android::hardware::health::V2_0::HealthInfo; +using android::hardware::health::V2_0::IHealth; +using android::hardware::health::V2_0::Result; +using android::hardware::Return; +using android::hardware::Void; + +using std::make_shared; +using std::shared_ptr; + +namespace android { +namespace os { +namespace statsd { + +sp gHealthHal = nullptr; + +bool getHealthHal() { + if (gHealthHal == nullptr) { + gHealthHal = get_health_service(); + + } + return gHealthHal != nullptr; +} + +ResourceHealthManagerPuller::ResourceHealthManagerPuller(int tagId) : StatsPuller(tagId) { +} + +// TODO: add other health atoms (eg. Temperature). +bool ResourceHealthManagerPuller::PullInternal(vector>* data) { + if (!getHealthHal()) { + ALOGE("Health Hal not loaded"); + return false; + } + + uint64_t timestamp = time(nullptr) * NS_PER_SEC; + + data->clear(); + bool result_success = true; + + Return ret = gHealthHal->getHealthInfo([&](Result r, HealthInfo v) { + if (r != Result::SUCCESS) { + result_success = false; + return; + } + if (mTagId == android::util::REMAINING_BATTERY_CAPACITY) { + auto ptr = make_shared(android::util::REMAINING_BATTERY_CAPACITY, timestamp); + ptr->write(v.legacy.batteryChargeCounter); + ptr->init(); + data->push_back(ptr); + } else if (mTagId == android::util::FULL_BATTERY_CAPACITY) { + auto ptr = make_shared(android::util::FULL_BATTERY_CAPACITY, timestamp); + ptr->write(v.legacy.batteryFullCharge); + ptr->init(); + data->push_back(ptr); + } else { + ALOGE("Unsupported tag in ResourceHealthManagerPuller: %d", mTagId); + } + }); + if (!result_success || !ret.isOk()) { + ALOGE("getHealthHal() failed: health HAL service not available. Description: %s", + ret.description().c_str()); + if (!ret.isOk() && ret.isDeadObject()) { + gHealthHal = nullptr; + } + return false; + } + return true; +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.h b/cmds/statsd/src/external/ResourceHealthManagerPuller.h new file mode 100644 index 0000000000000000000000000000000000000000..9b238eaf5f83966f44a88fed3886ee1e5f708ab7 --- /dev/null +++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "StatsPuller.h" + +namespace android { +namespace os { +namespace statsd { + +/** + * Reads Ihealth.hal + */ +class ResourceHealthManagerPuller : public StatsPuller { +public: + ResourceHealthManagerPuller(int tagId); + bool PullInternal(vector>* data) override; +}; + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp index cadc535f2469e79e8b77cb02566f255eb476c430..da14434737afbf543089f25c478ae92c185c9b38 100644 --- a/cmds/statsd/src/external/StatsPuller.cpp +++ b/cmds/statsd/src/external/StatsPuller.cpp @@ -59,6 +59,11 @@ bool StatsPuller::Pull(std::vector>* data) { return ret; } +void StatsPuller::ClearCache() { + lock_guard lock(mLock); + mCachedData.clear(); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h index 47cc9f01e0547aafd296fc46805b8a6aa2310513..bc7c45f535d1f810cf041b3e05db0c58c28c3f14 100644 --- a/cmds/statsd/src/external/StatsPuller.h +++ b/cmds/statsd/src/external/StatsPuller.h @@ -38,6 +38,8 @@ public: bool Pull(std::vector>* data); + void ClearCache(); + protected: // The atom tag id this puller pulls const int mTagId; diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 00a1475c0829c3a1a428df6046d9c6ef79404de8..4826d963a3ededc358b3e06664e81e4aeb646cbd 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -50,10 +50,14 @@ class StatsPullerManager { return mPullerManager.Pull(tagId, data); } - virtual void SetTimeBaseSec(const long timeBaseSec) { + void SetTimeBaseSec(const long timeBaseSec) { mPullerManager.SetTimeBaseSec(timeBaseSec); } + void ClearPullerCache() { + mPullerManager.ClearPullerCache(); + } + private: StatsPullerManagerImpl & mPullerManager = StatsPullerManagerImpl::GetInstance(); diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp index 148c9ae9b249a847d9205331918902a4cc83470f..71b0abe25d28279a93d1782edbc15f9daf28d4dd 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp @@ -23,10 +23,11 @@ #include #include "CpuTimePerUidFreqPuller.h" #include "CpuTimePerUidPuller.h" -#include "SubsystemSleepStatePuller.h" +#include "ResourceHealthManagerPuller.h" #include "StatsCompanionServicePuller.h" #include "StatsPullerManagerImpl.h" #include "StatsService.h" +#include "SubsystemSleepStatePuller.h" #include "logd/LogEvent.h" #include "statslog.h" @@ -83,7 +84,10 @@ StatsPullerManagerImpl::StatsPullerManagerImpl() make_shared(android::util::WIFI_ACTIVITY_ENERGY_INFO)}); mPullers.insert({android::util::MODEM_ACTIVITY_INFO, make_shared(android::util::MODEM_ACTIVITY_INFO)}); - + mPullers.insert({android::util::REMAINING_BATTERY_CAPACITY, + make_shared(android::util::REMAINING_BATTERY_CAPACITY)}); + mPullers.insert({android::util::FULL_BATTERY_CAPACITY, + make_shared(android::util::FULL_BATTERY_CAPACITY)}); mStatsCompanionService = StatsService::getStatsCompanionService(); } @@ -195,6 +199,12 @@ void StatsPullerManagerImpl::OnAlarmFired() { } } +void StatsPullerManagerImpl::ClearPullerCache() { + for (auto puller : mPullers) { + puller.second->ClearCache(); + } +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.h b/cmds/statsd/src/external/StatsPullerManagerImpl.h index 7c59f6659d1f1b84c88c20e8efa5e65d63dc7bd8..fba3ade8c1bb69dd3f82b2baa376dc8eeab1c8d6 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.h +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.h @@ -49,6 +49,8 @@ public: void SetTimeBaseSec(long timeBaseSec) {mTimeBaseSec = timeBaseSec;}; + void ClearPullerCache(); + private: StatsPullerManagerImpl(); diff --git a/cmds/statsd/src/field_util.cpp b/cmds/statsd/src/field_util.cpp index 4ff4f74f7979311200cd36a357a4044cbe160f4f..acf64fe12e6db75b06d83916b0c3974e6e04406d 100644 --- a/cmds/statsd/src/field_util.cpp +++ b/cmds/statsd/src/field_util.cpp @@ -102,24 +102,13 @@ bool setFieldInLeafValueProto(const Field &field, DimensionsValue* leafValue) { } } -Field buildAtomField(const int tagId, const Field &atomField) { - Field field; - *field.add_child() = atomField; - field.set_field(tagId); - return field; +void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field *field) { + field->set_field(tagId); + field->add_child()->set_field(atomFieldNum); } -Field buildSimpleAtomField(const int tagId, const int atomFieldNum) { - Field field; - field.set_field(tagId); - field.add_child()->set_field(atomFieldNum); - return field; -} - -Field buildSimpleAtomField(const int tagId) { - Field field; - field.set_field(tagId); - return field; +void buildSimpleAtomField(const int tagId, Field *field) { + field->set_field(tagId); } void appendLeaf(Field *parent, int node_field_num) { @@ -145,18 +134,6 @@ void appendLeaf(Field *parent, int node_field_num, int position) { } } - -void getNextField(Field* field) { - if (field->child_size() <= 0) { - field->set_field(field->field() + 1); - return; - } - if (field->child_size() != 1) { - return; - } - getNextField(field->mutable_child(0)); -} - void increasePosition(Field *field) { if (!field->has_position_index()) { field->set_position_index(0); @@ -176,34 +153,30 @@ int getPositionByReferenceField(const Field& ref, const Field& field_with_index) return getPositionByReferenceField(ref.child(0), field_with_index.child(0)); } -void setPositionForLeaf(Field *field, int index) { - if (field->child_size() <= 0) { - field->set_position_index(index); - } else { - setPositionForLeaf(field->mutable_child(0), index); - } -} - namespace { + void findFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, - std::vector* rootFields); + Field* rootField, + Field* leafField, + std::set* rootFields); void findNonRepeatedFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, - std::vector* rootFields) { + Field* rootField, + Field* leafField, + std::set* rootFields) { if (matcher.child_size() > 0) { + Field* newLeafField = leafField->add_child(); for (const auto& childMatcher : matcher.child()) { - Field childField = field; - appendLeaf(&childField, childMatcher.field()); - findFields(fieldValueMap, childMatcher, childField, rootFields); + newLeafField->set_field(childMatcher.field()); + findFields(fieldValueMap, childMatcher, rootField, newLeafField, rootFields); } + leafField->clear_child(); } else { - auto ret = fieldValueMap.equal_range(field); + auto ret = fieldValueMap.equal_range(*rootField); int found = 0; for (auto it = ret.first; it != ret.second; ++it) { found++; @@ -216,38 +189,42 @@ void findNonRepeatedFields( ALOGE("Found multiple values for optional field."); return; } - rootFields->push_back(ret.first->first); + rootFields->insert(ret.first->first); } } void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, std::vector* rootFields) { + Field* rootField, Field* leafField, + std::set* rootFields) { if (matcher.position() == Position::FIRST) { - Field first_field = field; - setPositionForLeaf(&first_field, 0); - findNonRepeatedFields(fieldValueMap, matcher, first_field, rootFields); + leafField->set_position_index(0); + findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields); + leafField->clear_position_index(); } else { - auto itLower = fieldValueMap.lower_bound(field); + auto itLower = fieldValueMap.lower_bound(*rootField); if (itLower == fieldValueMap.end()) { return; } - Field next_field = field; - getNextField(&next_field); - auto itUpper = fieldValueMap.lower_bound(next_field); + + const int leafFieldNum = leafField->field(); + leafField->set_field(leafFieldNum + 1); + auto itUpper = fieldValueMap.lower_bound(*rootField); + // Resets the field number. + leafField->set_field(leafFieldNum); switch (matcher.position()) { case Position::LAST: { itUpper--; if (itUpper != fieldValueMap.end()) { - Field last_field = field; - int last_index = getPositionByReferenceField(field, itUpper->first); + int last_index = getPositionByReferenceField(*rootField, itUpper->first); if (last_index < 0) { return; } - setPositionForLeaf(&last_field, last_index); + leafField->set_position_index(last_index); findNonRepeatedFields( - fieldValueMap, matcher, last_field, rootFields); + fieldValueMap, matcher, rootField, leafField, rootFields); + leafField->clear_position_index(); } } break; @@ -255,17 +232,17 @@ void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& { std::set indexes; for (auto it = itLower; it != itUpper; ++it) { - int index = getPositionByReferenceField(field, it->first); + int index = getPositionByReferenceField(*rootField, it->first); if (index >= 0) { indexes.insert(index); } } if (!indexes.empty()) { - Field any_field = field; for (const int index : indexes) { - setPositionForLeaf(&any_field, index); + leafField->set_position_index(index); findNonRepeatedFields( - fieldValueMap, matcher, any_field, rootFields); + fieldValueMap, matcher, rootField, leafField, rootFields); + leafField->clear_position_index(); } } } @@ -279,12 +256,13 @@ void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& void findFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, - std::vector* rootFields) { + Field* rootField, + Field* leafField, + std::set* rootFields) { if (!matcher.has_position()) { - findNonRepeatedFields(fieldValueMap, matcher, field, rootFields); + findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields); } else { - findRepeatedFields(fieldValueMap, matcher, field, rootFields); + findRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields); } } @@ -293,17 +271,24 @@ void findFields( void findFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - std::vector* rootFields) { - return findFields(fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), rootFields); + std::set* rootFields) { + if (!matcher.has_field() || fieldValueMap.empty()) { + return; + } + Field rootField; + buildSimpleAtomField(matcher.field(), &rootField); + return findFields(fieldValueMap, matcher, &rootField, &rootField, rootFields); } void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap) { - std::vector rootFields; + if (!matcher.has_field()) { + return; + } + std::set rootFields; findFields(*fieldValueMap, matcher, &rootFields); - std::set rootFieldSet(rootFields.begin(), rootFields.end()); auto it = fieldValueMap->begin(); while (it != fieldValueMap->end()) { - if (rootFieldSet.find(it->first) == rootFieldSet.end()) { + if (rootFields.find(it->first) == rootFields.end()) { it = fieldValueMap->erase(it); } else { it++; diff --git a/cmds/statsd/src/field_util.h b/cmds/statsd/src/field_util.h index a4dfdddf210b6d2825efe9e8e12ccf8d71519285..b04465dc986251188e77ed054b6e949dbaf42221 100644 --- a/cmds/statsd/src/field_util.h +++ b/cmds/statsd/src/field_util.h @@ -20,7 +20,8 @@ #include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h" #include "frameworks/base/cmds/statsd/src/stats_log.pb.h" -#include +#include +#include namespace android { namespace os { @@ -54,15 +55,9 @@ Field* getSingleLeaf(Field* field); void appendLeaf(Field *parent, int node_field_num); void appendLeaf(Field *parent, int node_field_num, int position); -// Given the field sorting logic, this function is to increase the "field" at the leaf node. -void getNextField(Field* field); - // Increase the position index for the node. If the "position_index" is not set, set it as 0. void increasePosition(Field *field); -// Finds the leaf node and set the index there. -void setPositionForLeaf(Field *field, int index); - // Returns true if the matcher has specified at least one leaf node. bool hasLeafNode(const FieldMatcher& matcher); @@ -72,15 +67,13 @@ bool hasLeafNode(const FieldMatcher& matcher); int getPositionByReferenceField(const Field& reference, const Field& field_with_index); // Utils to build the Field proto for simple atom fields. -Field buildAtomField(const int tagId, const Field &atomField); -Field buildSimpleAtomField(const int tagId, const int atomFieldNum); -Field buildSimpleAtomField(const int tagId); +void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field* field); +void buildSimpleAtomField(const int tagId, Field* field); // Find out all the fields specified by the matcher. void findFields( - const FieldValueMap& fieldValueMap, - const FieldMatcher& matcher, - std::vector* rootFields); + const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, + std::set* rootFields); // Filter out the fields not in the field matcher. void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap); diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index 1ca793c818783d638e5341078cd5a5d6fe9eb307..1dcd8534db79fb76170cdb89e0f2b2140811b65e 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -62,13 +62,14 @@ void LogEvent::init() { const char* buffer; size_t len = android_log_write_list_buffer(mContext, &buffer); // turns to reader mode - mContext = create_android_log_parser(buffer, len); - init(mContext); - // destroy the context to save memory. - if (mContext) { + android_log_context contextForRead = create_android_log_parser(buffer, len); + if (contextForRead) { + init(contextForRead); + // destroy the context to save memory. // android_log_destroy will set mContext to NULL - android_log_destroy(&mContext); + android_log_destroy(&contextForRead); } + android_log_destroy(&mContext); } } @@ -188,6 +189,9 @@ void increaseField(Field *field, bool is_child) { * of the elements that are written to the log. */ void LogEvent::init(android_log_context context) { + if (!context) { + return; + } android_log_list_element elem; // TODO: The log is actually structured inside one list. This is convenient // because we'll be able to use it to put the attribution (WorkSource) block first @@ -198,7 +202,8 @@ void LogEvent::init(android_log_context context) { int seenListStart = 0; - Field field; + Field fieldTree; + Field* atomField = fieldTree.add_child(); do { elem = android_log_read_next(context); switch ((int)elem.type) { @@ -206,51 +211,37 @@ void LogEvent::init(android_log_context context) { // elem at [0] is EVENT_TYPE_LIST, [1] is the tag id. if (i == 1) { mTagId = elem.data.int32; + fieldTree.set_field(mTagId); } else { - increaseField(&field, seenListStart > 0/* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_int(elem.data.int32); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0/* is_child */); + mFieldValueMap[fieldTree].set_value_int(elem.data.int32); } break; case EVENT_TYPE_FLOAT: { - increaseField(&field, seenListStart > 0/* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_float(elem.data.float32); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0/* is_child */); + mFieldValueMap[fieldTree].set_value_float(elem.data.float32); } break; case EVENT_TYPE_STRING: { - increaseField(&field, seenListStart > 0/* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_str(string(elem.data.string, elem.len).c_str()); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0/* is_child */); + mFieldValueMap[fieldTree].set_value_str( + string(elem.data.string, elem.len).c_str()); } break; case EVENT_TYPE_LONG: { - increaseField(&field, seenListStart > 0 /* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_long(elem.data.int64); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0 /* is_child */); + mFieldValueMap[fieldTree].set_value_long(elem.data.int64); } break; case EVENT_TYPE_LIST: if (i >= 1) { if (seenListStart > 0) { - increasePosition(&field); + increasePosition(atomField); } else { - increaseField(&field, false /* is_child */); + increaseField(atomField, false /* is_child */); } seenListStart++; if (seenListStart >= 3) { @@ -262,10 +253,10 @@ void LogEvent::init(android_log_context context) { case EVENT_TYPE_LIST_STOP: seenListStart--; if (seenListStart == 0) { - field.clear_position_index(); + atomField->clear_position_index(); } else { - if (field.child_size() > 0) { - field.mutable_child(0)->clear_field(); + if (atomField->child_size() > 0) { + atomField->mutable_child(0)->clear_field(); } } break; @@ -393,14 +384,9 @@ bool LogEvent::GetAtomDimensionsValueProto(const FieldMatcher& matcher, bool LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField, DimensionsValue* dimensionsValue) const { - return GetAtomDimensionsValueProto( - buildSimpleAtomFieldMatcher(mTagId, atomField), dimensionsValue); -} - -DimensionsValue LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField) const { - DimensionsValue dimensionsValue; - GetSimpleAtomDimensionsValueProto(atomField, &dimensionsValue); - return dimensionsValue; + FieldMatcher matcher; + buildSimpleAtomFieldMatcher(mTagId, atomField, &matcher); + return GetAtomDimensionsValueProto(matcher, dimensionsValue); } DimensionsValue* LogEvent::findFieldValueOrNull(const Field& field) { diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index 5a4efd4b54a44d2325bde4224036d235967faa91..eb2c00845d00e4089421b1d270dca9aef74b87fe 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -92,7 +92,6 @@ public: * Get a DimensionsValue proto objects from Field. */ bool GetSimpleAtomDimensionsValueProto(size_t field, DimensionsValue* dimensionsValue) const; - DimensionsValue GetSimpleAtomDimensionsValueProto(size_t atomField) const; /** * Write test data to the LogEvent. This can only be used when the LogEvent is constructed diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp index 48f62e70256093e018a25c1a5650e42662fa188e..fae91729fe4ff7b8918080fb5c44c8cbcfd57314 100644 --- a/cmds/statsd/src/matchers/matcher_util.cpp +++ b/cmds/statsd/src/matchers/matcher_util.cpp @@ -93,25 +93,28 @@ bool combinationMatch(const vector& children, const LogicalOperation& opera return matched; } -bool matchesNonRepeatedField( - const UidMap& uidMap, - const FieldValueMap& fieldMap, - const FieldValueMatcher&matcher, - const Field& field) { +namespace { + +bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap, + const FieldValueMatcher&matcher, Field* rootField, Field* leafField); + +bool matchesNonRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, + const FieldValueMatcher&matcher, Field* rootField, Field* leafField) { if (matcher.value_matcher_case() == FieldValueMatcher::ValueMatcherCase::VALUE_MATCHER_NOT_SET) { return !fieldMap.empty() && fieldMap.begin()->first.field() == matcher.field(); } else if (matcher.value_matcher_case() == FieldValueMatcher::ValueMatcherCase::kMatchesTuple) { bool allMatched = true; + Field* newLeafField = leafField->add_child(); for (int i = 0; allMatched && i < matcher.matches_tuple().field_value_matcher_size(); ++i) { const auto& childMatcher = matcher.matches_tuple().field_value_matcher(i); - Field childField = field; - appendLeaf(&childField, childMatcher.field()); - allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, childField); + newLeafField->set_field(childMatcher.field()); + allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, rootField, newLeafField); } + leafField->clear_child(); return allMatched; } else { - auto ret = fieldMap.equal_range(field); + auto ret = fieldMap.equal_range(*rootField); int found = 0; for (auto it = ret.first; it != ret.second; ++it) { found++; @@ -126,43 +129,60 @@ bool matchesNonRepeatedField( } bool matched = false; switch (matcher.value_matcher_case()) { - case FieldValueMatcher::ValueMatcherCase::kEqBool: - // Logd does not support bool, it is int instead. - matched = ((ret.first->second.value_int() > 0) == matcher.eq_bool()); - break; - case FieldValueMatcher::ValueMatcherCase::kEqString: - { - if (IsAttributionUidField(field)) { - const int uid = ret.first->second.value_int(); - std::set packageNames = + case FieldValueMatcher::ValueMatcherCase::kEqBool: { + // Logd does not support bool, it is int instead. + matched = ((ret.first->second.value_int() > 0) == matcher.eq_bool()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kEqString: { + if (IsAttributionUidField(*rootField)) { + const int uid = ret.first->second.value_int(); + std::set packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/); - matched = packageNames.find(matcher.eq_string()) != packageNames.end(); - } else { - matched = (ret.first->second.value_str() == matcher.eq_string()); - } - } - break; - case FieldValueMatcher::ValueMatcherCase::kEqInt: - matched = (ret.first->second.value_int() == matcher.eq_int()); - break; - case FieldValueMatcher::ValueMatcherCase::kLtInt: - matched = (ret.first->second.value_int() < matcher.lt_int()); - break; - case FieldValueMatcher::ValueMatcherCase::kGtInt: - matched = (ret.first->second.value_int() > matcher.gt_int()); - break; - case FieldValueMatcher::ValueMatcherCase::kLtFloat: - matched = (ret.first->second.value_float() < matcher.lt_float()); - break; - case FieldValueMatcher::ValueMatcherCase::kGtFloat: - matched = (ret.first->second.value_float() > matcher.gt_float()); - break; - case FieldValueMatcher::ValueMatcherCase::kLteInt: - matched = (ret.first->second.value_int() <= matcher.lte_int()); - break; - case FieldValueMatcher::ValueMatcherCase::kGteInt: - matched = (ret.first->second.value_int() >= matcher.gte_int()); - break; + matched = packageNames.find(matcher.eq_string()) != packageNames.end(); + } else { + matched = (ret.first->second.value_str() == matcher.eq_string()); + } + break; + } + case FieldValueMatcher::ValueMatcherCase::kEqInt: { + int64_t val = ret.first->second.has_value_int() ? + ret.first->second.value_int() : ret.first->second.value_long(); + matched = (val == matcher.eq_int()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kLtInt: { + int64_t val = ret.first->second.has_value_int() ? + ret.first->second.value_int() : ret.first->second.value_long(); + matched = (val < matcher.lt_int()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kGtInt: { + int64_t val = ret.first->second.has_value_int() ? + ret.first->second.value_int() : ret.first->second.value_long(); + matched = (val > matcher.gt_int()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kLtFloat: { + matched = (ret.first->second.value_float() < matcher.lt_float()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kGtFloat: { + matched = (ret.first->second.value_float() > matcher.gt_float()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kLteInt: { + int64_t val = ret.first->second.has_value_int() ? + ret.first->second.value_int() : ret.first->second.value_long(); + matched = (val <= matcher.lte_int()); + break; + } + case FieldValueMatcher::ValueMatcherCase::kGteInt: { + int64_t val = ret.first->second.has_value_int() ? + ret.first->second.value_int() : ret.first->second.value_long(); + matched = (val >= matcher.gte_int()); + break; + } default: break; } @@ -171,19 +191,25 @@ bool matchesNonRepeatedField( } bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, - const FieldValueMatcher&matcher, const Field& field) { + const FieldValueMatcher&matcher, + Field* rootField, Field* leafField) { if (matcher.position() == Position::FIRST) { - Field first_field = field; - setPositionForLeaf(&first_field, 0); - return matchesNonRepeatedField(uidMap, fieldMap, matcher, first_field); + leafField->set_position_index(0); + bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); + leafField->clear_position_index(); + return res; } else { - auto itLower = fieldMap.lower_bound(field); + auto itLower = fieldMap.lower_bound(*rootField); if (itLower == fieldMap.end()) { return false; } - Field next_field = field; - getNextField(&next_field); - auto itUpper = fieldMap.lower_bound(next_field); + + const int leafFieldNum = leafField->field(); + leafField->set_field(leafFieldNum + 1); + auto itUpper = fieldMap.lower_bound(*rootField); + // Resets the field number. + leafField->set_field(leafFieldNum); + switch (matcher.position()) { case Position::LAST: { @@ -191,31 +217,31 @@ bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, if (itUpper == fieldMap.end()) { return false; } else { - Field last_field = field; - int last_index = getPositionByReferenceField(field, itUpper->first); + int last_index = getPositionByReferenceField(*rootField, itUpper->first); if (last_index < 0) { return false; } - setPositionForLeaf(&last_field, last_index); - return matchesNonRepeatedField(uidMap, fieldMap, matcher, last_field); + leafField->set_position_index(last_index); + bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); + leafField->clear_position_index(); + return res; } } break; case Position::ANY: { - std::set indexes; + bool matched = false; for (auto it = itLower; it != itUpper; ++it) { - int index = getPositionByReferenceField(field, it->first); + int index = getPositionByReferenceField(*rootField, it->first); if (index >= 0) { - indexes.insert(index); + leafField->set_position_index(index); + matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); + leafField->clear_position_index(); + if (matched) { + break; + } } } - bool matched = false; - for (const int index : indexes) { - Field any_field = field; - setPositionForLeaf(&any_field, index); - matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, any_field); - } return matched; } default: @@ -226,14 +252,16 @@ bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, } bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap, - const FieldValueMatcher&matcher, const Field& field) { + const FieldValueMatcher&matcher, Field* rootField, Field* leafField) { if (!matcher.has_position()) { - return matchesNonRepeatedField(uidMap, fieldMap, matcher, field); + return matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); } else { - return matchesRepeatedField(uidMap, fieldMap, matcher, field); + return matchesRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); } } +} // namespace + bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, const LogEvent& event) { if (simpleMatcher.field_value_matcher_size() <= 0) { @@ -247,13 +275,15 @@ bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, *root_field_matcher.mutable_matches_tuple()->add_field_value_matcher() = simpleMatcher.field_value_matcher(i); } - return matchFieldSimple(uidMap, event.getFieldValueMap(), root_field_matcher, root_field); + return matchFieldSimple( + uidMap, event.getFieldValueMap(), root_field_matcher, &root_field, &root_field); } -vector getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher) { - vector values; - findDimensionsValues(event.getFieldValueMap(), matcher, &values); - return values; +void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher, + std::vector *dimensionKeys) { + if (matcher.has_field()) { + findDimensionsValues(event.getFieldValueMap(), matcher, dimensionKeys); + } } } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h index 704cb4c22e00174a5f0ce998748c53b4185bc2f5..a45a9fb26a13500b88c3250f3169941d1e1176d0 100644 --- a/cmds/statsd/src/matchers/matcher_util.h +++ b/cmds/statsd/src/matchers/matcher_util.h @@ -42,13 +42,11 @@ enum MatchingState { bool combinationMatch(const std::vector& children, const LogicalOperation& operation, const std::vector& matcherResults); -bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& dimensionsMap, - const FieldValueMatcher& matcher, const Field& field); - bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper); -std::vector getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher); +void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher, + std::vector *dimensionKeys); } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index 0455f6a210a9b4404ff6a9619f0f5caa75012a04..ae4df3ee92f07eae50f43e51f2ed4ad4c7373de5 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -21,6 +21,7 @@ #include "guardrail/StatsdStats.h" #include "stats_util.h" #include "stats_log_util.h" +#include "dimension.h" #include #include @@ -71,13 +72,15 @@ CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric } // TODO: use UidMap if uid->pkg_name is required - mDimensions = metric.dimensions_in_what(); + mDimensionsInWhat = metric.dimensions_in_what(); + mDimensionsInCondition = metric.dimensions_in_condition(); if (metric.links().size() > 0) { mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(), metric.links().end()); - mConditionSliced = true; } + mConditionSliced = (metric.links().size() > 0)|| + (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0); VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs); @@ -99,7 +102,10 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLog auto count_metrics = report->mutable_count_metrics(); for (const auto& counter : mPastBuckets) { CountMetricData* metricData = count_metrics->add_data(); - *metricData->mutable_dimensions_in_what() = counter.first.getDimensionsValue(); + *metricData->mutable_dimensions_in_what() = + counter.first.getDimensionKeyInWhat().getDimensionsValue(); + *metricData->mutable_dimensions_in_condition() = + counter.first.getDimensionKeyInCondition().getDimensionsValue(); for (const auto& bucket : counter.second) { CountBucketInfo* bucketInfo = metricData->add_bucket_info(); bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs); @@ -123,17 +129,26 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, VLOG("metric %lld dump report now...",(long long)mMetricId); for (const auto& counter : mPastBuckets) { - const HashableDimensionKey& hashableKey = counter.first; - VLOG(" dimension key %s", hashableKey.c_str()); + const MetricDimensionKey& dimensionKey = counter.first; + VLOG(" dimension key %s", dimensionKey.c_str()); long long wrapperToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); // First fill dimension. - long long dimensionToken = protoOutput->start( + long long dimensionInWhatToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT); - writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput); - protoOutput->end(dimensionToken); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput); + protoOutput->end(dimensionInWhatToken); + + if (dimensionKey.hasDimensionKeyInCondition()) { + long long dimensionInConditionToken = protoOutput->start( + FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput); + protoOutput->end(dimensionInConditionToken); + } // Then fill bucket_info (CountBucketInfo). for (const auto& bucket : counter.second) { @@ -166,7 +181,7 @@ void CountMetricProducer::onConditionChangedLocked(const bool conditionMet, mCondition = conditionMet; } -bool CountMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) { +bool CountMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) { if (mCurrentSlicedCounter->find(newKey) != mCurrentSlicedCounter->end()) { return false; } @@ -187,7 +202,7 @@ bool CountMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) } void CountMetricProducer::onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) { uint64_t eventTimeNs = event.GetTimestampNs(); diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h index 061b7a36817c249f30c8fef3633b72d2f3dfe7f3..8659d47735681d75716bf0523827ca9cc1aa4217 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.h +++ b/cmds/statsd/src/metrics/CountMetricProducer.h @@ -50,7 +50,7 @@ public: protected: void onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) override; @@ -74,14 +74,14 @@ private: void flushIfNeededLocked(const uint64_t& newEventTime); // TODO: Add a lock to mPastBuckets. - std::unordered_map> mPastBuckets; + std::unordered_map> mPastBuckets; // The current bucket. std::shared_ptr mCurrentSlicedCounter = std::make_shared(); static const size_t kBucketSize = sizeof(CountBucket{}); - bool hitGuardRailLocked(const HashableDimensionKey& newKey); + bool hitGuardRailLocked(const MetricDimensionKey& newKey); FRIEND_TEST(CountMetricProducerTest, TestNonDimensionalEvents); FRIEND_TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition); diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index bfab9e6e490fadd13704e9b3016d500d104abb61..efbdae15079217b6c818d07fd62dd42c611d467f 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -21,6 +21,7 @@ #include "guardrail/StatsdStats.h" #include "stats_util.h" #include "stats_log_util.h" +#include "dimension.h" #include #include @@ -81,13 +82,15 @@ DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const Durat } // TODO: use UidMap if uid->pkg_name is required - mDimensions = metric.dimensions_in_what(); + mDimensionsInWhat = metric.dimensions_in_what(); + mDimensionsInCondition = metric.dimensions_in_condition(); if (metric.links().size() > 0) { mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(), metric.links().end()); - mConditionSliced = true; } + mConditionSliced = (metric.links().size() > 0)|| + (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0); VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs); @@ -113,15 +116,17 @@ sp DurationMetricProducer::addAnomalyTracker(const Alert &alert) } unique_ptr DurationMetricProducer::createDurationTracker( - const HashableDimensionKey& eventKey) const { + const MetricDimensionKey& eventKey) const { switch (mAggregationType) { case DurationMetric_AggregationType_SUM: return make_unique( - mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested, + mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, + mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers); case DurationMetric_AggregationType_MAX_SPARSE: return make_unique( - mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested, + mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, + mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers); } } @@ -129,10 +134,34 @@ unique_ptr DurationMetricProducer::createDurationTracker( void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) { VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId); flushIfNeededLocked(eventTime); + // Now for each of the on-going event, check if the condition has changed for them. - for (auto& pair : mCurrentSlicedDuration) { + for (auto& pair : mCurrentSlicedDurationTrackerMap) { pair.second->onSlicedConditionMayChange(eventTime); } + + + std::unordered_set conditionDimensionsKeySet; + ConditionState conditionState = mWizard->getMetConditionDimension( + mConditionTrackerIndex, mDimensionsInCondition, &conditionDimensionsKeySet); + + bool condition = (conditionState == ConditionState::kTrue); + for (auto& pair : mCurrentSlicedDurationTrackerMap) { + conditionDimensionsKeySet.erase(pair.first.getDimensionKeyInCondition()); + } + std::unordered_set newKeys; + for (const auto& conditionDimensionsKey : conditionDimensionsKeySet) { + for (auto& pair : mCurrentSlicedDurationTrackerMap) { + auto newKey = + MetricDimensionKey(pair.first.getDimensionKeyInWhat(), conditionDimensionsKey); + if (newKeys.find(newKey) == newKeys.end()) { + mCurrentSlicedDurationTrackerMap[newKey] = pair.second->clone(eventTime); + mCurrentSlicedDurationTrackerMap[newKey]->setEventKey(newKey); + mCurrentSlicedDurationTrackerMap[newKey]->onSlicedConditionMayChange(eventTime); + } + newKeys.insert(newKey); + } + } } void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet, @@ -142,7 +171,7 @@ void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet, flushIfNeededLocked(eventTime); // TODO: need to populate the condition change time from the event which triggers the condition // change, instead of using current time. - for (auto& pair : mCurrentSlicedDuration) { + for (auto& pair : mCurrentSlicedDurationTrackerMap) { pair.second->onConditionChanged(conditionMet, eventTime); } } @@ -155,7 +184,10 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, Stats auto duration_metrics = report->mutable_duration_metrics(); for (const auto& pair : mPastBuckets) { DurationMetricData* metricData = duration_metrics->add_data(); - *metricData->mutable_dimensions_in_what() = pair.first.getDimensionsValue(); + *metricData->mutable_dimensions_in_what() = + pair.first.getDimensionKeyInWhat().getDimensionsValue(); + *metricData->mutable_dimensions_in_condition() = + pair.first.getDimensionKeyInCondition().getDimensionsValue(); for (const auto& bucket : pair.second) { auto bucketInfo = metricData->add_bucket_info(); bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs); @@ -179,8 +211,8 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, VLOG("metric %lld dump report now...", (long long)mMetricId); for (const auto& pair : mPastBuckets) { - const HashableDimensionKey& hashableKey = pair.first; - VLOG(" dimension key %s", hashableKey.c_str()); + const MetricDimensionKey& dimensionKey = pair.first; + VLOG(" dimension key %s", dimensionKey.c_str()); long long wrapperToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); @@ -188,9 +220,18 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, // First fill dimension. long long dimensionToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT); - writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput); protoOutput->end(dimensionToken); + if (dimensionKey.hasDimensionKeyInCondition()) { + long long dimensionInConditionToken = protoOutput->start( + FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput); + protoOutput->end(dimensionInConditionToken); + } + // Then fill bucket_info (DurationBucketInfo). for (const auto& bucket : pair.second) { long long bucketInfoToken = protoOutput->start( @@ -219,10 +260,11 @@ void DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTime) { return; } VLOG("flushing..........."); - for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end();) { + for (auto it = mCurrentSlicedDurationTrackerMap.begin(); + it != mCurrentSlicedDurationTrackerMap.end();) { if (it->second->flushIfNeeded(eventTime, &mPastBuckets)) { VLOG("erase bucket for key %s", it->first.c_str()); - it = mCurrentSlicedDuration.erase(it); + it = mCurrentSlicedDurationTrackerMap.erase(it); } else { ++it; } @@ -234,28 +276,28 @@ void DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTime) { } void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { - if (mCurrentSlicedDuration.size() == 0) { + if (mCurrentSlicedDurationTrackerMap.size() == 0) { return; } fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId, - (unsigned long)mCurrentSlicedDuration.size()); + (unsigned long)mCurrentSlicedDurationTrackerMap.size()); if (verbose) { - for (const auto& slice : mCurrentSlicedDuration) { + for (const auto& slice : mCurrentSlicedDurationTrackerMap) { fprintf(out, "\t%s\n", slice.first.c_str()); slice.second->dumpStates(out, verbose); } } } -bool DurationMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) { +bool DurationMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) { // the key is not new, we are good. - if (mCurrentSlicedDuration.find(newKey) != mCurrentSlicedDuration.end()) { + if (mCurrentSlicedDurationTrackerMap.find(newKey) != mCurrentSlicedDurationTrackerMap.end()) { return false; } // 1. Report the tuple count if the tuple count > soft limit - if (mCurrentSlicedDuration.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { - size_t newTupleCount = mCurrentSlicedDuration.size() + 1; + if (mCurrentSlicedDurationTrackerMap.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { + size_t newTupleCount = mCurrentSlicedDurationTrackerMap.size() + 1; StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount); // 2. Don't add more tuples, we are above the allowed threshold. Drop the data. if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) { @@ -268,29 +310,29 @@ bool DurationMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newK } void DurationMetricProducer::onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys, bool condition, const LogEvent& event) { flushIfNeededLocked(event.GetTimestampNs()); if (matcherIndex == mStopAllIndex) { - for (auto& pair : mCurrentSlicedDuration) { + for (auto& pair : mCurrentSlicedDurationTrackerMap) { pair.second->noteStopAll(event.GetTimestampNs()); } return; } - - if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end()) { + if (mCurrentSlicedDurationTrackerMap.find(eventKey) == mCurrentSlicedDurationTrackerMap.end()) { if (hitGuardRailLocked(eventKey)) { return; } - mCurrentSlicedDuration[eventKey] = createDurationTracker(eventKey); + mCurrentSlicedDurationTrackerMap[eventKey] = createDurationTracker(eventKey); } - auto it = mCurrentSlicedDuration.find(eventKey); + auto it = mCurrentSlicedDurationTrackerMap.find(eventKey); - std::vector values = getDimensionKeys(event, mInternalDimensions); + std::vector values; + getDimensionKeys(event, mInternalDimensions, &values); if (values.empty()) { if (matcherIndex == mStartIndex) { it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, @@ -301,10 +343,11 @@ void DurationMetricProducer::onMatchedLogEventInternalLocked( } else { for (const DimensionsValue& value : values) { if (matcherIndex == mStartIndex) { - it->second->noteStart(HashableDimensionKey(value), condition, - event.GetTimestampNs(), conditionKeys); + it->second->noteStart( + HashableDimensionKey(value), condition, event.GetTimestampNs(), conditionKeys); } else if (matcherIndex == mStopIndex) { - it->second->noteStop(HashableDimensionKey(value), event.GetTimestampNs(), false); + it->second->noteStop( + HashableDimensionKey(value), event.GetTimestampNs(), false); } } } diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h index d8cab92a2b84d11de74b3e74f76838b0ab3598ce..152e570df4675d1438167e49a412646f3fe64187 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.h +++ b/cmds/statsd/src/metrics/DurationMetricProducer.h @@ -50,7 +50,7 @@ public: protected: void onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys, bool condition, const LogEvent& event) override; @@ -92,21 +92,21 @@ private: // Save the past buckets and we can clear when the StatsLogReport is dumped. // TODO: Add a lock to mPastBuckets. - std::unordered_map> mPastBuckets; + std::unordered_map> mPastBuckets; // The current bucket. - std::unordered_map> - mCurrentSlicedDuration; + std::unordered_map> + mCurrentSlicedDurationTrackerMap; // Helper function to create a duration tracker given the metric aggregation type. std::unique_ptr createDurationTracker( - const HashableDimensionKey& eventKey) const; + const MetricDimensionKey& eventKey) const; // This hides the base class's std::vector> mAnomalyTrackers std::vector> mAnomalyTrackers; // Util function to check whether the specified dimension hits the guardrail. - bool hitGuardRailLocked(const HashableDimensionKey& newKey); + bool hitGuardRailLocked(const MetricDimensionKey& newKey); static const size_t kBucketSize = sizeof(DurationBucket{}); diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index 25c86d0d46f19fad70c5833083202f5bc7d5e4ab..820d5918a92ae57344db35580bf0680d6e16033d 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -128,7 +128,7 @@ void EventMetricProducer::onConditionChangedLocked(const bool conditionMet, } void EventMetricProducer::onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) { if (!condition) { diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h index 9da0dd0569d6605b1ab57cf5a29a85ebbe551bb6..935f206017fa20b0a222180f58617fa35e4dfeb9 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.h +++ b/cmds/statsd/src/metrics/EventMetricProducer.h @@ -45,7 +45,7 @@ protected: private: void onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) override; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 24dc5b0fba5324e867a9e21d93bf55da7f6459d6..d6cb1891288af35167a73cbf2074b54ffbb461ba 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -58,6 +58,7 @@ const int FIELD_ID_BUCKET_INFO = 3; const int FIELD_ID_START_BUCKET_NANOS = 1; const int FIELD_ID_END_BUCKET_NANOS = 2; const int FIELD_ID_ATOM = 3; +const int FIELD_ID_TIMESTAMP = 4; GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex, @@ -67,7 +68,7 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard), mStatsPullerManager(statsPullerManager), mPullTagId(pullTagId) { - mCurrentSlicedBucket = std::make_shared(); + mCurrentSlicedBucket = std::make_shared(); mCurrentSlicedBucketForAnomaly = std::make_shared(); int64_t bucketSizeMills = 0; if (metric.has_bucket()) { @@ -77,19 +78,22 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric } mBucketSizeNs = bucketSizeMills * 1000000; + mSamplingType = metric.sampling_type(); mFieldFilter = metric.gauge_fields_filter(); // TODO: use UidMap if uid->pkg_name is required - mDimensions = metric.dimensions_in_what(); + mDimensionsInWhat = metric.dimensions_in_what(); + mDimensionsInCondition = metric.dimensions_in_condition(); if (metric.links().size() > 0) { mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(), metric.links().end()); - mConditionSliced = true; } + mConditionSliced = (metric.links().size() > 0)|| + (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0); // Kicks off the puller immediately. - if (mPullTagId != -1) { + if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) { mStatsPullerManager->RegisterReceiver(mPullTagId, this, bucketSizeMills); } @@ -134,18 +138,27 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS); for (const auto& pair : mPastBuckets) { - const HashableDimensionKey& hashableKey = pair.first; + const MetricDimensionKey& dimensionKey = pair.first; - VLOG(" dimension key %s", hashableKey.c_str()); + VLOG(" dimension key %s", dimensionKey.c_str()); long long wrapperToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); // First fill dimension. long long dimensionToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT); - writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput); protoOutput->end(dimensionToken); + if (dimensionKey.hasDimensionKeyInCondition()) { + long long dimensionInConditionToken = protoOutput->start( + FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput); + protoOutput->end(dimensionInConditionToken); + } + // Then fill bucket_info (GaugeBucketInfo). for (const auto& bucket : pair.second) { long long bucketInfoToken = protoOutput->start( @@ -154,12 +167,23 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, (long long)bucket.mBucketStartNs); protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS, (long long)bucket.mBucketEndNs); - long long atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM); - writeFieldValueTreeToStream(*bucket.mGaugeFields, protoOutput); - protoOutput->end(atomToken); + + if (!bucket.mGaugeAtoms.empty()) { + long long atomsToken = + protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ATOM); + for (const auto& atom : bucket.mGaugeAtoms) { + writeFieldValueTreeToStream(*atom.mFields, protoOutput); + } + protoOutput->end(atomsToken); + + for (const auto& atom : bucket.mGaugeAtoms) { + protoOutput->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_TIMESTAMP, + (long long)atom.mTimestamps); + } + } protoOutput->end(bucketInfoToken); - VLOG("\t bucket [%lld - %lld] includes %d gauge fields.", (long long)bucket.mBucketStartNs, - (long long)bucket.mBucketEndNs, (int)bucket.mGaugeFields->size()); + VLOG("\t bucket [%lld - %lld] includes %d atoms.", (long long)bucket.mBucketStartNs, + (long long)bucket.mBucketEndNs, (int)bucket.mGaugeAtoms.size()); } protoOutput->end(wrapperToken); } @@ -181,14 +205,26 @@ void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet, if (mPullTagId == -1) { return; } - // No need to pull again. Either scheduled pull or condition on true happened - if (!mCondition) { - return; + + bool triggerPuller = false; + switch(mSamplingType) { + // When the metric wants to do random sampling and there is already one gauge atom for the + // current bucket, do not do it again. + case GaugeMetric::RANDOM_ONE_SAMPLE: { + triggerPuller = mCondition && mCurrentSlicedBucket->empty(); + break; + } + case GaugeMetric::ALL_CONDITION_CHANGES: { + triggerPuller = true; + break; + } + default: + break; } - // Already have gauge metric for the current bucket, do not do it again. - if (mCurrentSlicedBucket->size() > 0) { + if (!triggerPuller) { return; } + vector> allData; if (!mStatsPullerManager->Pull(mPullTagId, &allData)) { ALOGE("Stats puller failed for tag: %d", mPullTagId); @@ -223,7 +259,7 @@ void GaugeMetricProducer::onDataPulled(const std::vectorfind(newKey) != mCurrentSlicedBucket->end()) { return false; } @@ -243,7 +279,7 @@ bool GaugeMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) } void GaugeMetricProducer::onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) { if (condition == false) { @@ -257,20 +293,24 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked( } flushIfNeededLocked(eventTimeNs); - // For gauge metric, we just simply use the first gauge in the given bucket. - if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end()) { + // When gauge metric wants to randomly sample the output atom, we just simply use the first + // gauge in the given bucket. + if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end() && + mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) { return; } - std::shared_ptr gaugeFields = getGaugeFields(event); if (hitGuardRailLocked(eventKey)) { return; } - (*mCurrentSlicedBucket)[eventKey] = gaugeFields; + GaugeAtom gaugeAtom; + gaugeAtom.mFields = getGaugeFields(event); + gaugeAtom.mTimestamps = eventTimeNs; + (*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom); // Anomaly detection on gauge metric only works when there is one numeric // field specified. if (mAnomalyTrackers.size() > 0) { - if (gaugeFields->size() == 1) { - const DimensionsValue& dimensionsValue = gaugeFields->begin()->second; + if (gaugeAtom.mFields->size() == 1) { + const DimensionsValue& dimensionsValue = gaugeAtom.mFields->begin()->second; long gaugeVal = 0; if (dimensionsValue.has_value_int()) { gaugeVal = (long)dimensionsValue.value_int(); @@ -289,7 +329,10 @@ void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() { mCurrentSlicedBucketForAnomaly->clear(); status_t err = NO_ERROR; for (const auto& slice : *mCurrentSlicedBucket) { - const DimensionsValue& dimensionsValue = slice.second->begin()->second; + if (slice.second.empty() || slice.second.front().mFields->empty()) { + continue; + } + const DimensionsValue& dimensionsValue = slice.second.front().mFields->begin()->second; long gaugeVal = 0; if (dimensionsValue.has_value_int()) { gaugeVal = (long)dimensionsValue.value_int(); @@ -318,7 +361,7 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) { info.mBucketNum = mCurrentBucketNum; for (const auto& slice : *mCurrentSlicedBucket) { - info.mGaugeFields = slice.second; + info.mGaugeAtoms = slice.second; auto& bucketList = mPastBuckets[slice.first]; bucketList.push_back(info); VLOG("gauge metric %lld, dump key value: %s", @@ -334,7 +377,7 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) { } mCurrentSlicedBucketForAnomaly = std::make_shared(); - mCurrentSlicedBucket = std::make_shared(); + mCurrentSlicedBucket = std::make_shared(); // Adjusts the bucket start time int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index 1895edf8f72918b99d47de2304eab1e025f0eff3..86d0ccd241ebfcbbb8b99b037df9fd31837713b8 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -32,15 +32,20 @@ namespace android { namespace os { namespace statsd { +struct GaugeAtom { + std::shared_ptr mFields; + int64_t mTimestamps; +}; + struct GaugeBucket { int64_t mBucketStartNs; int64_t mBucketEndNs; - std::shared_ptr mGaugeFields; + std::vector mGaugeAtoms; uint64_t mBucketNum; }; -typedef std::unordered_map> - DimToGaugeFieldsMap; +typedef std::unordered_map> + DimToGaugeAtomsMap; // This gauge metric producer first register the puller to automatically pull the gauge at the // beginning of each bucket. If the condition is met, insert it to the bucket info. Otherwise @@ -48,7 +53,7 @@ typedef std::unordered_map> // producer always reports the guage at the earliest time of the bucket when the condition is met. class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver { public: - GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& countMetric, + GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex, const sp& wizard, const int pullTagId, const int64_t startTimeNs); @@ -59,7 +64,7 @@ public: protected: void onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) override; @@ -94,10 +99,10 @@ private: // Save the past buckets and we can clear when the StatsLogReport is dumped. // TODO: Add a lock to mPastBuckets. - std::unordered_map> mPastBuckets; + std::unordered_map> mPastBuckets; // The current bucket. - std::shared_ptr mCurrentSlicedBucket; + std::shared_ptr mCurrentSlicedBucket; // The current bucket for anomaly detection. std::shared_ptr mCurrentSlicedBucketForAnomaly; @@ -108,11 +113,13 @@ private: // Whitelist of fields to report. Empty means all are reported. FieldFilter mFieldFilter; + GaugeMetric::SamplingType mSamplingType; + // apply a whitelist on the original input std::shared_ptr getGaugeFields(const LogEvent& event); // Util function to check whether the specified dimension hits the guardrail. - bool hitGuardRailLocked(const HashableDimensionKey& newKey); + bool hitGuardRailLocked(const MetricDimensionKey& newKey); static const size_t kBucketSize = sizeof(GaugeBucket{}); diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index d620a7ebee00104b5d9f953c7045b0caea487438..85e655b08f4d962882fcc3c2eb021947a1cc9245 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -15,6 +15,8 @@ */ #include "MetricProducer.h" +#include "dimension.h" + namespace android { namespace os { namespace statsd { @@ -30,29 +32,51 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo bool condition; ConditionKey conditionKey; + + std::unordered_set dimensionKeysInCondition; if (mConditionSliced) { for (const auto& link : mConditionLinks) { - conditionKey.insert(std::make_pair(link.condition(), - getDimensionKeysForCondition(event, link))); - } - if (mWizard->query(mConditionTrackerIndex, conditionKey) != ConditionState::kTrue) { - condition = false; - } else { - condition = true; + getDimensionKeysForCondition(event, link, &conditionKey[link.condition()]); } + auto conditionState = + mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition, + &dimensionKeysInCondition); + condition = (conditionState == ConditionState::kTrue); } else { condition = mCondition; } - if (mDimensions.child_size() > 0) { - vector dimensionValues = getDimensionKeys(event, mDimensions); - for (const DimensionsValue& dimensionValue : dimensionValues) { + vector dimensionInWhatValues; + if (mDimensionsInWhat.has_field() && mDimensionsInWhat.child_size() > 0) { + getDimensionKeys(event, mDimensionsInWhat, &dimensionInWhatValues); + } + + if (dimensionInWhatValues.empty() && dimensionKeysInCondition.empty()) { + onMatchedLogEventInternalLocked( + matcherIndex, DEFAULT_METRIC_DIMENSION_KEY, conditionKey, condition, event); + } else if (dimensionKeysInCondition.empty()) { + for (const DimensionsValue& whatValue : dimensionInWhatValues) { + onMatchedLogEventInternalLocked( + matcherIndex, + MetricDimensionKey(HashableDimensionKey(whatValue), DEFAULT_DIMENSION_KEY), + conditionKey, condition, event); + } + } else if (dimensionInWhatValues.empty()) { + for (const auto& conditionDimensionKey : dimensionKeysInCondition) { onMatchedLogEventInternalLocked( - matcherIndex, HashableDimensionKey(dimensionValue), conditionKey, condition, event); + matcherIndex, + MetricDimensionKey(DEFAULT_DIMENSION_KEY, conditionDimensionKey), + conditionKey, condition, event); } } else { - onMatchedLogEventInternalLocked( - matcherIndex, DEFAULT_DIMENSION_KEY, conditionKey, condition, event); + for (const DimensionsValue& whatValue : dimensionInWhatValues) { + for (const auto& conditionDimensionKey : dimensionKeysInCondition) { + onMatchedLogEventInternalLocked( + matcherIndex, + MetricDimensionKey(HashableDimensionKey(whatValue), conditionDimensionKey), + conditionKey, condition, event); + } + } } } diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 6f33073c633c945a2c9944922e4a0f51b143cb77..3b1498f076329d3d17cb3664816ff2819bd487a7 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -91,6 +91,7 @@ public: std::lock_guard lock(mMutex); return onDumpReportLocked(dumpTimeNs, protoOutput); } + void onDumpReport(const uint64_t dumpTimeNs, StatsLogReport* report) { std::lock_guard lock(mMutex); return onDumpReportLocked(dumpTimeNs, report); @@ -156,7 +157,8 @@ protected: int mConditionTrackerIndex; - FieldMatcher mDimensions; // The dimension defined in statsd_config + FieldMatcher mDimensionsInWhat; // The dimensions_in_what defined in statsd_config + FieldMatcher mDimensionsInCondition; // The dimensions_in_condition defined in statsd_config std::vector mConditionLinks; @@ -178,7 +180,7 @@ protected: * [event]: the log event, just in case the metric needs its data, e.g., EventMetric. */ virtual void onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) = 0; diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index d0737de8acf3d83375e4af9f17c236d1588ef3ff..5f0619a21a44bbb1b445614d049b220e8f74ce75 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -28,6 +28,7 @@ #include "stats_util.h" #include +#include using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_MESSAGE; @@ -59,8 +60,9 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, // mConfigValid = false; // ALOGE("Log source white list is empty! This config won't get any data."); - mAllowedUid.push_back(1000); - mAllowedUid.push_back(0); + mAllowedUid.push_back(AID_ROOT); + mAllowedUid.push_back(AID_STATSD); + mAllowedUid.push_back(AID_SYSTEM); mAllowedLogSources.insert(mAllowedUid.begin(), mAllowedUid.end()); } else { for (const auto& source : config.allowed_log_source()) { @@ -189,26 +191,45 @@ void MetricsManager::onLogEvent(const LogEvent& event) { return; } - if (event.GetTagId() != android::util::APP_HOOK) { - std::lock_guard lock(mAllowedLogSourcesMutex); - if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { - VLOG("log source %d not on the whitelist", event.GetUid()); + if (event.GetTagId() == android::util::APP_HOOK) { // Check that app hook fields are valid. + // TODO: Find a way to make these checks easier to maintain if the app hooks get changed. + status_t err = NO_ERROR; + + // Uid is 3rd from last field and must match the caller's uid, + // unless that caller is statsd itself (statsd is allowed to spoof uids). + long appHookUid = event.GetLong(event.size()-2, &err); + int32_t loggerUid = event.GetUid(); + if (err != NO_ERROR || (loggerUid != appHookUid && loggerUid != AID_STATSD)) { + VLOG("AppHook has invalid uid: claimed %ld but caller is %d", appHookUid, loggerUid); return; } - } else { // Check that app hook fields are valid. - // TODO: Find a way to make these checks easier to maintain if the app hooks get changed. // Label is 2nd from last field and must be from [0, 15]. - status_t err = NO_ERROR; - long label = event.GetLong(event.size()-1, &err); - if (err != NO_ERROR || label < 0 || label > 15) { - VLOG("App hook does not have valid label %ld", label); + long appHookLabel = event.GetLong(event.size()-1, &err); + if (err != NO_ERROR || appHookLabel < 0 || appHookLabel > 15) { + VLOG("AppHook does not have valid label %ld", appHookLabel); return; } + // The state must be from 0,3. This part of code must be manually updated. - long apphookState = event.GetLong(event.size(), &err); - if (err != NO_ERROR || apphookState < 0 || apphookState > 3) { - VLOG("App hook does not have valid state %ld", apphookState); + long appHookState = event.GetLong(event.size(), &err); + if (err != NO_ERROR || appHookState < 0 || appHookState > 3) { + VLOG("AppHook does not have valid state %ld", appHookState); + return; + } + } else if (event.GetTagId() == android::util::DAVEY_OCCURRED) { + // Daveys can be logged from any app since they are logged in libs/hwui/JankTracker.cpp. + // Check that the davey duration is reasonable. Max length check is for privacy. + status_t err = NO_ERROR; + long duration = event.GetLong(event.size(), &err); + if (err != NO_ERROR || duration > 100000) { + VLOG("Davey duration is unreasonably long: %ld", duration); + return; + } + } else { + std::lock_guard lock(mAllowedLogSourcesMutex); + if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { + VLOG("log source %d not on the whitelist", event.GetUid()); return; } } diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 9cdbafc75fb15ecf1ca37f85afd568251dbd76b5..d4b9102d5ddc73d44f039efb5e4d07a010e95741 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -143,6 +143,10 @@ private: FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks); FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice); FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent); + FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricNoLink); + FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricWithLink); + FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink); + FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink); }; } // namespace statsd diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index ae0c673e3490722f54d3a1829733208dd8d8d441..c9cc7bb9c1d4528bdc86f70987227ed89cfe40b0 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -81,13 +81,15 @@ ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric } mBucketSizeNs = bucketSizeMills * 1000000; - mDimensions = metric.dimensions_in_what(); + mDimensionsInWhat = metric.dimensions_in_what(); + mDimensionsInCondition = metric.dimensions_in_condition(); if (metric.links().size() > 0) { mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(), metric.links().end()); - mConditionSliced = true; } + mConditionSliced = (metric.links().size() > 0)|| + (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0); if (!metric.has_condition() && mPullTagId != -1) { VLOG("Setting up periodic pulling for %d", mPullTagId); @@ -124,7 +126,10 @@ void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLog auto value_metrics = report->mutable_value_metrics(); for (const auto& pair : mPastBuckets) { ValueMetricData* metricData = value_metrics->add_data(); - *metricData->mutable_dimensions_in_what() = pair.first.getDimensionsValue(); + *metricData->mutable_dimensions_in_what() = + pair.first.getDimensionKeyInWhat().getDimensionsValue(); + *metricData->mutable_dimensions_in_condition() = + pair.first.getDimensionKeyInCondition().getDimensionsValue(); for (const auto& bucket : pair.second) { ValueBucketInfo* bucketInfo = metricData->add_bucket_info(); bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs); @@ -146,16 +151,24 @@ void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS); for (const auto& pair : mPastBuckets) { - const HashableDimensionKey& hashableKey = pair.first; - VLOG(" dimension key %s", hashableKey.c_str()); + const MetricDimensionKey& dimensionKey = pair.first; + VLOG(" dimension key %s", dimensionKey.c_str()); long long wrapperToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); // First fill dimension. long long dimensionToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT); - writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput); protoOutput->end(dimensionToken); + if (dimensionKey.hasDimensionKeyInCondition()) { + long long dimensionInConditionToken = protoOutput->start( + FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION); + writeDimensionsValueProtoToStream( + dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput); + protoOutput->end(dimensionInConditionToken); + } // Then fill bucket_info (ValueBucketInfo). for (const auto& bucket : pair.second) { @@ -239,7 +252,7 @@ void ValueMetricProducer::onDataPulled(const std::vector soft limit if (mCurrentSlicedBucket.find(newKey) != mCurrentSlicedBucket.end()) { @@ -260,7 +273,7 @@ bool ValueMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) } void ValueMetricProducer::onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) { uint64_t eventTimeNs = event.GetTimestampNs(); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 9f750cf419b5dff2314c4b978fe2a94289bbdb29..121ec7d185159e80bbf02ce6f832c15e3b711bdf 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -49,7 +49,7 @@ public: protected: void onMatchedLogEventInternalLocked( - const size_t matcherIndex, const HashableDimensionKey& eventKey, + const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) override; @@ -99,16 +99,16 @@ private: long sum; } Interval; - std::unordered_map mCurrentSlicedBucket; + std::unordered_map mCurrentSlicedBucket; // Save the past buckets and we can clear when the StatsLogReport is dumped. // TODO: Add a lock to mPastBuckets. - std::unordered_map> mPastBuckets; + std::unordered_map> mPastBuckets; std::shared_ptr getValueFields(const LogEvent& event); // Util function to check whether the specified dimension hits the guardrail. - bool hitGuardRailLocked(const HashableDimensionKey& newKey); + bool hitGuardRailLocked(const MetricDimensionKey& newKey); static const size_t kBucketSize = sizeof(ValueBucket{}); diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h index c2d2cea2a1ff187f3a91ea086f378ca57f394b7e..45735a866978506d0e3a4a6060b5635d37a42ed4 100644 --- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h @@ -60,8 +60,9 @@ struct DurationBucket { class DurationTracker { public: - DurationTracker(const ConfigKey& key, const int64_t& id, const HashableDimensionKey& eventKey, - sp wizard, int conditionIndex, bool nesting, + DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, + sp wizard, int conditionIndex, + const FieldMatcher& dimensionInCondition, bool nesting, uint64_t currentBucketStartNs, uint64_t bucketSizeNs, bool conditionSliced, const std::vector>& anomalyTrackers) : mConfigKey(key), @@ -70,6 +71,7 @@ public: mWizard(wizard), mConditionTrackerIndex(conditionIndex), mBucketSizeNs(bucketSizeNs), + mDimensionInCondition(dimensionInCondition), mNested(nesting), mCurrentBucketStartTimeNs(currentBucketStartNs), mDuration(0), @@ -79,6 +81,8 @@ public: virtual ~DurationTracker(){}; + virtual unique_ptr clone(const uint64_t eventTime) = 0; + virtual void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime, const ConditionKey& conditionKey) = 0; virtual void noteStop(const HashableDimensionKey& key, const uint64_t eventTime, @@ -92,7 +96,7 @@ public: // events, so that the owner can safely remove the tracker. virtual bool flushIfNeeded( uint64_t timestampNs, - std::unordered_map>* output) = 0; + std::unordered_map>* output) = 0; // Predict the anomaly timestamp given the current status. virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, @@ -100,6 +104,10 @@ public: // Dump internal states for debugging virtual void dumpStates(FILE* out, bool verbose) const = 0; + void setEventKey(const MetricDimensionKey& eventKey) { + mEventKey = eventKey; + } + protected: // Starts the anomaly alarm. void startAnomalyAlarm(const uint64_t eventTime) { @@ -150,7 +158,7 @@ protected: const int64_t mTrackerId; - HashableDimensionKey mEventKey; + MetricDimensionKey mEventKey; sp mWizard; @@ -158,6 +166,8 @@ protected: const int64_t mBucketSizeNs; + const FieldMatcher mDimensionInCondition; + const bool mNested; uint64_t mCurrentBucketStartTimeNs; diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp index 412a0c93576635fdf2f388cc9061ec2a8eb600fc..db7dea4afd04df99c5f4f2f09f7da6e12fec3287 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp @@ -25,13 +25,23 @@ namespace os { namespace statsd { MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id, - const HashableDimensionKey& eventKey, - sp wizard, int conditionIndex, bool nesting, + const MetricDimensionKey& eventKey, + sp wizard, int conditionIndex, + const FieldMatcher& dimensionInCondition, bool nesting, uint64_t currentBucketStartNs, uint64_t bucketSizeNs, bool conditionSliced, const vector>& anomalyTrackers) - : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs, - bucketSizeNs, conditionSliced, anomalyTrackers) { + : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting, + currentBucketStartNs, bucketSizeNs, conditionSliced, anomalyTrackers) { +} + +unique_ptr MaxDurationTracker::clone(const uint64_t eventTime) { + auto clonedTracker = make_unique(*this); + for (auto it = clonedTracker->mInfos.begin(); it != clonedTracker->mInfos.end(); ++it) { + it->second.lastStartTime = eventTime; + it->second.lastDuration = 0; + } + return clonedTracker; } bool MaxDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) { @@ -44,7 +54,7 @@ bool MaxDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) { if (mInfos.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { size_t newTupleCount = mInfos.size() + 1; StatsdStats::getInstance().noteMetricDimensionSize( - mConfigKey, hashDimensionsValue(mTrackerId, mEventKey.getDimensionsValue()), + mConfigKey, hashMetricDimensionKey(mTrackerId, mEventKey), newTupleCount); // 2. Don't add more tuples, we are above the allowed threshold. Drop the data. if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) { @@ -149,7 +159,7 @@ void MaxDurationTracker::noteStopAll(const uint64_t eventTime) { } bool MaxDurationTracker::flushIfNeeded( - uint64_t eventTime, unordered_map>* output) { + uint64_t eventTime, unordered_map>* output) { if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) { return false; } @@ -236,8 +246,14 @@ void MaxDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) { if (pair.second.state == kStopped) { continue; } - bool conditionMet = mWizard->query(mConditionTrackerIndex, pair.second.conditionKeys) == - ConditionState::kTrue; + std::unordered_set conditionDimensionKeySet; + ConditionState conditionState = mWizard->query( + mConditionTrackerIndex, pair.second.conditionKeys, mDimensionInCondition, + &conditionDimensionKeySet); + bool conditionMet = (conditionState == ConditionState::kTrue) && + (!mDimensionInCondition.has_field() || + conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) != + conditionDimensionKeySet.end()); VLOG("key: %s, condition: %d", pair.first.c_str(), conditionMet); noteConditionChanged(pair.first, conditionMet, timestamp); } diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h index e988ebc06307c0b0300feb542e91cfff78802bcc..4d32a0637d56d1a0ecf639d9afb6e73d5470a253 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h @@ -29,10 +29,15 @@ namespace statsd { class MaxDurationTracker : public DurationTracker { public: MaxDurationTracker(const ConfigKey& key, const int64_t& id, - const HashableDimensionKey& eventKey, sp wizard, - int conditionIndex, bool nesting, uint64_t currentBucketStartNs, - uint64_t bucketSizeNs, bool conditionSliced, + const MetricDimensionKey& eventKey, sp wizard, + int conditionIndex, const FieldMatcher& dimensionInCondition, bool nesting, + uint64_t currentBucketStartNs, uint64_t bucketSizeNs, bool conditionSliced, const std::vector>& anomalyTrackers); + + MaxDurationTracker(const MaxDurationTracker& tracker) = default; + + unique_ptr clone(const uint64_t eventTime) override; + void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime, const ConditionKey& conditionKey) override; void noteStop(const HashableDimensionKey& key, const uint64_t eventTime, @@ -41,7 +46,7 @@ public: bool flushIfNeeded( uint64_t timestampNs, - std::unordered_map>* output) override; + std::unordered_map>* output) override; void onSlicedConditionMayChange(const uint64_t timestamp) override; void onConditionChanged(bool condition, const uint64_t timestamp) override; @@ -51,7 +56,7 @@ public: void dumpStates(FILE* out, bool verbose) const override; private: - std::map mInfos; + std::unordered_map mInfos; void noteConditionChanged(const HashableDimensionKey& key, bool conditionMet, const uint64_t timestamp); diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp index 75d7c0898d78d817d0b5c4a7a65e00a0172fac7a..0feae369b0d585209d9f835ed089272cfde6c957 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp @@ -25,17 +25,25 @@ namespace statsd { using std::pair; OringDurationTracker::OringDurationTracker( - const ConfigKey& key, const int64_t& id, const HashableDimensionKey& eventKey, - sp wizard, int conditionIndex, bool nesting, uint64_t currentBucketStartNs, + const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, + sp wizard, int conditionIndex, + const FieldMatcher& dimensionInCondition, bool nesting, uint64_t currentBucketStartNs, uint64_t bucketSizeNs, bool conditionSliced, const vector>& anomalyTrackers) - : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs, - bucketSizeNs, conditionSliced, anomalyTrackers), + : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting, + currentBucketStartNs, bucketSizeNs, conditionSliced, anomalyTrackers), mStarted(), mPaused() { mLastStartTime = 0; } +unique_ptr OringDurationTracker::clone(const uint64_t eventTime) { + auto clonedTracker = make_unique(*this); + clonedTracker->mLastStartTime = eventTime; + clonedTracker->mDuration = 0; + return clonedTracker; +} + bool OringDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) { // ===========GuardRail============== // 1. Report the tuple count if the tuple count > soft limit @@ -45,7 +53,7 @@ bool OringDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) { if (mConditionKeyMap.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { size_t newTupleCount = mConditionKeyMap.size() + 1; StatsdStats::getInstance().noteMetricDimensionSize( - mConfigKey, hashDimensionsValue(mTrackerId, mEventKey.getDimensionsValue()), + mConfigKey, hashMetricDimensionKey(mTrackerId, mEventKey), newTupleCount); // 2. Don't add more tuples, we are above the allowed threshold. Drop the data. if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) { @@ -76,7 +84,6 @@ void OringDurationTracker::noteStart(const HashableDimensionKey& key, bool condi if (mConditionSliced && mConditionKeyMap.find(key) == mConditionKeyMap.end()) { mConditionKeyMap[key] = conditionKey; } - VLOG("Oring: %s start, condition %d", key.c_str(), condition); } @@ -128,7 +135,7 @@ void OringDurationTracker::noteStopAll(const uint64_t timestamp) { } bool OringDurationTracker::flushIfNeeded( - uint64_t eventTime, unordered_map>* output) { + uint64_t eventTime, unordered_map>* output) { if (eventTime < mCurrentBucketStartTimeNs + mBucketSizeNs) { return false; } @@ -184,8 +191,14 @@ void OringDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) ++it; continue; } - if (mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key]) != - ConditionState::kTrue) { + std::unordered_set conditionDimensionKeySet; + ConditionState conditionState = + mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key], + mDimensionInCondition, &conditionDimensionKeySet); + if (conditionState != ConditionState::kTrue || + (mDimensionInCondition.has_field() && + conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) == + conditionDimensionKeySet.end())) { startedToPaused.push_back(*it); it = mStarted.erase(it); VLOG("Key %s started -> paused", key.c_str()); @@ -210,8 +223,14 @@ void OringDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) ++it; continue; } - if (mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key]) == - ConditionState::kTrue) { + std::unordered_set conditionDimensionKeySet; + ConditionState conditionState = + mWizard->query(mConditionTrackerIndex, mConditionKeyMap[key], + mDimensionInCondition, &conditionDimensionKeySet); + if (conditionState == ConditionState::kTrue && + (!mDimensionInCondition.has_field() || + conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) + != conditionDimensionKeySet.end())) { pausedToStarted.push_back(*it); it = mPaused.erase(it); VLOG("Key %s paused -> started", key.c_str()); diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h index 1b74ed1addca6b4110d0bf3e0bc88e22ac55a2c9..75b5a815de9cb9706b990614a5a2b39fbc473345 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h @@ -28,11 +28,15 @@ namespace statsd { class OringDurationTracker : public DurationTracker { public: OringDurationTracker(const ConfigKey& key, const int64_t& id, - const HashableDimensionKey& eventKey, sp wizard, - int conditionIndex, bool nesting, uint64_t currentBucketStartNs, - uint64_t bucketSizeNs, bool conditionSliced, + const MetricDimensionKey& eventKey, sp wizard, + int conditionIndex, const FieldMatcher& dimensionInCondition, bool nesting, + uint64_t currentBucketStartNs, uint64_t bucketSizeNs, bool conditionSliced, const std::vector>& anomalyTrackers); + OringDurationTracker(const OringDurationTracker& tracker) = default; + + unique_ptr clone(const uint64_t eventTime) override; + void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime, const ConditionKey& conditionKey) override; void noteStop(const HashableDimensionKey& key, const uint64_t eventTime, @@ -44,7 +48,7 @@ public: bool flushIfNeeded( uint64_t timestampNs, - std::unordered_map>* output) override; + std::unordered_map>* output) override; int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, const uint64_t currentTimestamp) const override; @@ -56,10 +60,10 @@ private: // 2) which keys are paused (started but condition was false) // 3) whenever a key stops, we remove it from the started set. And if the set becomes empty, // it means everything has stopped, we then record the end time. - std::map mStarted; - std::map mPaused; + std::unordered_map mStarted; + std::unordered_map mPaused; int64_t mLastStartTime; - std::map mConditionKeyMap; + std::unordered_map mConditionKeyMap; // return true if we should not allow newKey to be tracked because we are above the threshold bool hitGuardRail(const HashableDimensionKey& newKey); diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index a4ccbd42883dab768628b4979e937d0c723c6748..af21ca4d82e87683352b742504ef02f9c3950ed0 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -100,7 +100,9 @@ message GaugeBucketInfo { optional int64 end_bucket_nanos = 2; - optional Atom atom = 3; + repeated Atom atom = 3; + + repeated int64 timestamp_nanos = 4; } message GaugeMetricData { diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp index a41f30c2bece0cadd72eeea100b14f1f18b749c6..6c6140081bd81166c25a989548d83a2c40251a95 100644 --- a/cmds/statsd/src/stats_log_util.cpp +++ b/cmds/statsd/src/stats_log_util.cpp @@ -54,6 +54,9 @@ const int FIELD_ID_MIN_PULL_INTERVAL_SEC = 4; void writeDimensionsValueProtoToStream(const DimensionsValue& dimensionsValue, ProtoOutputStream* protoOutput) { + if (!dimensionsValue.has_field()) { + return; + } protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, dimensionsValue.field()); switch (dimensionsValue.value_case()) { case DimensionsValue::ValueCase::kValueStr: @@ -103,6 +106,9 @@ const int FIELD_CHILD = 3; void writeFieldProtoToStream( const Field& field, util::ProtoOutputStream* protoOutput) { + if (!field.has_field()) { + return; + } protoOutput->write(FIELD_TYPE_INT32 | FIELD_FIELD, field.field()); if (field.has_position_index()) { protoOutput->write(FIELD_TYPE_INT32 | FIELD_POSITION_INDEX, field.position_index()); diff --git a/cmds/statsd/src/stats_util.h b/cmds/statsd/src/stats_util.h index 160b1f40243f3c2bc19d135404c19299df6c6973..31f51a7ac0a43650878d2f85be3638d89c232dbb 100644 --- a/cmds/statsd/src/stats_util.h +++ b/cmds/statsd/src/stats_util.h @@ -28,13 +28,14 @@ namespace os { namespace statsd { const HashableDimensionKey DEFAULT_DIMENSION_KEY = HashableDimensionKey(); +const MetricDimensionKey DEFAULT_METRIC_DIMENSION_KEY = MetricDimensionKey(); // Minimum bucket size in seconds const long kMinBucketSizeSec = 5 * 60; typedef std::map> ConditionKey; -typedef std::unordered_map DimToValMap; +typedef std::unordered_map DimToValMap; } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index 07bbcb2190e8d193af9f2517c7061e7ef7213a39..3eaf7a17a3e269d6becbc8f59d2d40a4f7473998 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -64,7 +64,7 @@ message FieldValueMatcher { oneof value_matcher { bool eq_bool = 3; string eq_string = 4; - int32 eq_int = 5; + int64 eq_int = 5; int64 lt_int = 6; int64 gt_int = 7; @@ -222,6 +222,12 @@ message GaugeMetric { optional TimeUnit bucket = 6; repeated MetricConditionLink links = 7; + + enum SamplingType { + RANDOM_ONE_SAMPLE = 1; + ALL_CONDITION_CHANGES = 2; + } + optional SamplingType sampling_type = 9 [default = RANDOM_ONE_SAMPLE] ; } message ValueMetric { diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp index f912e4b2cd2432fd8ae83a525b85cb9d6b416f38..3af684fa60697c53aae5769167a196c40a1b0fe5 100644 --- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp +++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp @@ -56,7 +56,7 @@ void SubscriberReporter::removeConfig(const ConfigKey& configKey) { void SubscriberReporter::alertBroadcastSubscriber(const ConfigKey& configKey, const Subscription& subscription, - const HashableDimensionKey& dimKey) const { + const MetricDimensionKey& dimKey) const { // Reminder about ids: // subscription id - name of the Subscription (that ties the Alert to the broadcast) // subscription rule_id - the name of the Alert (that triggers the broadcast) @@ -92,7 +92,7 @@ void SubscriberReporter::alertBroadcastSubscriber(const ConfigKey& configKey, void SubscriberReporter::sendBroadcastLocked(const sp& intentSender, const ConfigKey& configKey, const Subscription& subscription, - const HashableDimensionKey& dimKey) const { + const MetricDimensionKey& dimKey) const { VLOG("SubscriberReporter::sendBroadcastLocked called."); if (mStatsCompanionService == nullptr) { ALOGW("Failed to send subscriber broadcast: could not access StatsCompanionService."); @@ -107,8 +107,8 @@ void SubscriberReporter::sendBroadcastLocked(const sp& intentSender, } StatsDimensionsValue SubscriberReporter::protoToStatsDimensionsValue( - const HashableDimensionKey& dimKey) { - return protoToStatsDimensionsValue(dimKey.getDimensionsValue()); + const MetricDimensionKey& dimKey) { + return protoToStatsDimensionsValue(dimKey.getDimensionKeyInWhat().getDimensionsValue()); } StatsDimensionsValue SubscriberReporter::protoToStatsDimensionsValue( diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.h b/cmds/statsd/src/subscriber/SubscriberReporter.h index 5bb458a8b1d8e53ad5e7d8ea8e91630d12012a48..13fc7fd06279c15821d427d0c873d810e69721ab 100644 --- a/cmds/statsd/src/subscriber/SubscriberReporter.h +++ b/cmds/statsd/src/subscriber/SubscriberReporter.h @@ -80,7 +80,7 @@ public: */ void alertBroadcastSubscriber(const ConfigKey& configKey, const Subscription& subscription, - const HashableDimensionKey& dimKey) const; + const MetricDimensionKey& dimKey) const; private: SubscriberReporter() {}; @@ -101,7 +101,7 @@ private: void sendBroadcastLocked(const sp& intentSender, const ConfigKey& configKey, const Subscription& subscription, - const HashableDimensionKey& dimKey) const; + const MetricDimensionKey& dimKey) const; /** Converts a stats_log.proto DimensionsValue to a StatsDimensionsValue. */ static StatsDimensionsValue protoToStatsDimensionsValue( @@ -109,7 +109,7 @@ private: /** Converts a HashableDimensionKey to a StatsDimensionsValue. */ static StatsDimensionsValue protoToStatsDimensionsValue( - const HashableDimensionKey& dimKey); + const MetricDimensionKey& dimKey); }; } // namespace statsd diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp index 66bfa68ecc5595877ce1c93dbaae73347cbe7e67..a415ea1a3069a659973bb3b3b09559ab7e4f0a42 100644 --- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp +++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp @@ -33,14 +33,14 @@ namespace statsd { const ConfigKey kConfigKey(0, 12345); -HashableDimensionKey getMockDimensionKey(int key, string value) { +MetricDimensionKey getMockMetricDimensionKey(int key, string value) { DimensionsValue dimensionsValue; dimensionsValue.set_field(key); dimensionsValue.set_value_str(value); - return HashableDimensionKey(dimensionsValue); + return MetricDimensionKey(HashableDimensionKey(dimensionsValue), DEFAULT_DIMENSION_KEY); } -void AddValueToBucket(const std::vector>& key_value_pair_list, +void AddValueToBucket(const std::vector>& key_value_pair_list, std::shared_ptr bucket) { for (auto itr = key_value_pair_list.begin(); itr != key_value_pair_list.end(); itr++) { (*bucket)[itr->first] += itr->second; @@ -48,7 +48,7 @@ void AddValueToBucket(const std::vector>& } std::shared_ptr MockBucket( - const std::vector>& key_value_pair_list) { + const std::vector>& key_value_pair_list) { std::shared_ptr bucket = std::make_shared(); AddValueToBucket(key_value_pair_list, bucket); return bucket; @@ -56,7 +56,7 @@ std::shared_ptr MockBucket( // Returns the value, for the given key, in that bucket, or 0 if not present. int64_t getBucketValue(const std::shared_ptr& bucket, - const HashableDimensionKey& key) { + const MetricDimensionKey& key) { const auto& itr = bucket->find(key); if (itr != bucket->end()) { return itr->second; @@ -68,14 +68,14 @@ int64_t getBucketValue(const std::shared_ptr& bucket, bool detectAnomaliesPass(AnomalyTracker& tracker, const int64_t& bucketNum, const std::shared_ptr& currentBucket, - const std::set& trueList, - const std::set& falseList) { - for (HashableDimensionKey key : trueList) { + const std::set& trueList, + const std::set& falseList) { + for (MetricDimensionKey key : trueList) { if (!tracker.detectAnomaly(bucketNum, key, getBucketValue(currentBucket, key))) { return false; } } - for (HashableDimensionKey key : falseList) { + for (MetricDimensionKey key : falseList) { if (tracker.detectAnomaly(bucketNum, key, getBucketValue(currentBucket, key))) { return false; } @@ -100,7 +100,7 @@ void detectAndDeclareAnomalies(AnomalyTracker& tracker, void checkRefractoryTimes(AnomalyTracker& tracker, const int64_t& currTimestampNs, const int32_t& refractoryPeriodSec, - const std::unordered_map& timestamps) { + const std::unordered_map& timestamps) { for (const auto& kv : timestamps) { if (kv.second < 0) { // Make sure that, if there is a refractory period, it is already past. @@ -124,9 +124,9 @@ TEST(AnomalyTrackerTest, TestConsecutiveBuckets) { alert.set_trigger_if_sum_gt(2); AnomalyTracker anomalyTracker(alert, kConfigKey); - HashableDimensionKey keyA = getMockDimensionKey(1, "a"); - HashableDimensionKey keyB = getMockDimensionKey(1, "b"); - HashableDimensionKey keyC = getMockDimensionKey(1, "c"); + MetricDimensionKey keyA = getMockMetricDimensionKey(1, "a"); + MetricDimensionKey keyB = getMockMetricDimensionKey(1, "b"); + MetricDimensionKey keyC = getMockMetricDimensionKey(1, "c"); int64_t eventTimestamp0 = 10 * NS_PER_SEC; int64_t eventTimestamp1 = bucketSizeNs + 11 * NS_PER_SEC; @@ -269,11 +269,11 @@ TEST(AnomalyTrackerTest, TestSparseBuckets) { alert.set_trigger_if_sum_gt(2); AnomalyTracker anomalyTracker(alert, kConfigKey); - HashableDimensionKey keyA = getMockDimensionKey(1, "a"); - HashableDimensionKey keyB = getMockDimensionKey(1, "b"); - HashableDimensionKey keyC = getMockDimensionKey(1, "c"); - HashableDimensionKey keyD = getMockDimensionKey(1, "d"); - HashableDimensionKey keyE = getMockDimensionKey(1, "e"); + MetricDimensionKey keyA = getMockMetricDimensionKey(1, "a"); + MetricDimensionKey keyB = getMockMetricDimensionKey(1, "b"); + MetricDimensionKey keyC = getMockMetricDimensionKey(1, "c"); + MetricDimensionKey keyD = getMockMetricDimensionKey(1, "d"); + MetricDimensionKey keyE = getMockMetricDimensionKey(1, "e"); std::shared_ptr bucket9 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}}); std::shared_ptr bucket16 = MockBucket({{keyB, 4}}); diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp index 819f2bebf327e34c5f5fbf5ab5d0d57446ff8da7..d1b7b2842fd2a51d04aa8d9267ce2035cb3a423d 100644 --- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp +++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp @@ -78,7 +78,7 @@ void makeWakeLockEvent( std::map> getWakeLockQueryKey( const Position position, const std::vector &uids, const string& conditionName) { - std::map> outputKeyMap; + std::map> outputKeyMap; std::vector uid_indexes; switch(position) { case Position::FIRST: @@ -265,6 +265,9 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) { TEST(SimpleConditionTrackerTest, TestSlicedCondition) { for (Position position : { Position::ANY, Position::FIRST, Position::LAST}) { + FieldMatcher dimensionInCondition; + std::unordered_set dimensionKeys; + SimplePredicate simplePredicate = getWakeLockHeldCondition( true /*nesting*/, true /*default to false*/, true /*output slice by uid*/, position); @@ -307,7 +310,8 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { const auto queryKey = getWakeLockQueryKey(position, uids, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); // another wake lock acquired by this uid @@ -361,7 +365,8 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { // query again conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); } @@ -369,6 +374,9 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) { } TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { + FieldMatcher dimensionInCondition; + std::unordered_set dimensionKeys; + SimplePredicate simplePredicate = getWakeLockHeldCondition( true /*nesting*/, true /*default to false*/, false /*slice output by uid*/, Position::ANY /* position */); @@ -410,7 +418,8 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { ConditionKey queryKey; conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); // another wake lock acquired by this uid @@ -452,13 +461,17 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { // query again conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + dimensionKeys.clear(); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); } TEST(SimpleConditionTrackerTest, TestStopAll) { for (Position position : {Position::ANY, Position::FIRST, Position::LAST}) { + FieldMatcher dimensionInCondition; + std::unordered_set dimensionKeys; SimplePredicate simplePredicate = getWakeLockHeldCondition( true /*nesting*/, true /*default to false*/, true /*output slice by uid*/, position); @@ -502,7 +515,8 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); // another wake lock acquired by uid2 @@ -528,8 +542,9 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { // TEST QUERY const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); EXPECT_EQ(ConditionState::kTrue, conditionCache[0]); @@ -550,15 +565,15 @@ TEST(SimpleConditionTrackerTest, TestStopAll) { // TEST QUERY const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); // TEST QUERY const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName); conditionCache[0] = ConditionState::kNotEvaluated; - - conditionTracker.isConditionMet(queryKey, allPredicates, conditionCache); + conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition, + conditionCache, dimensionKeys); EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); } diff --git a/cmds/statsd/tests/dimension_test.cpp b/cmds/statsd/tests/dimension_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..678abaed5fd85a0a18c229bba99f599476b698ed --- /dev/null +++ b/cmds/statsd/tests/dimension_test.cpp @@ -0,0 +1,149 @@ +// 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. + +#include "dimension.h" + +#include + +using namespace android::os::statsd; + +#ifdef __ANDROID__ + +TEST(DimensionTest, subLeafNodes) { + DimensionsValue dimension; + int tagId = 100; + dimension.set_field(tagId); + auto child = dimension.mutable_value_tuple()->add_dimensions_value(); + child->set_field(1); + child->set_value_int(2000); + + child = dimension.mutable_value_tuple()->add_dimensions_value(); + child->set_field(3); + child->set_value_str("test"); + + child = dimension.mutable_value_tuple()->add_dimensions_value(); + child->set_field(4); + auto grandChild = child->mutable_value_tuple()->add_dimensions_value(); + grandChild->set_field(1); + grandChild->set_value_float(1.3f); + grandChild = child->mutable_value_tuple()->add_dimensions_value(); + grandChild->set_field(3); + grandChild->set_value_str("tag"); + + child = dimension.mutable_value_tuple()->add_dimensions_value(); + child->set_field(6); + child->set_value_bool(false); + + DimensionsValue sub_dimension; + FieldMatcher matcher; + + // Tag id not matched. + matcher.set_field(tagId + 1); + EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Field not exist. + matcher.Clear(); + matcher.set_field(tagId); + matcher.add_child()->set_field(5); + EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Field exists. + matcher.Clear(); + matcher.set_field(tagId); + matcher.add_child()->set_field(3); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Field exists. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + matcher.add_child()->set_field(6); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Field exists. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + matcher.add_child()->set_field(1); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Not leaf field. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + matcher.add_child()->set_field(4); + EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Grand-child leaf field not exist. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + auto childMatcher = matcher.add_child(); + childMatcher->set_field(4); + childMatcher->add_child()->set_field(2); + EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Grand-child leaf field. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + childMatcher = matcher.add_child(); + childMatcher->set_field(4); + childMatcher->add_child()->set_field(1); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + childMatcher = matcher.add_child(); + childMatcher->set_field(4); + childMatcher->add_child()->set_field(3); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Multiple grand-child fields. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + childMatcher = matcher.add_child(); + childMatcher->set_field(4); + childMatcher->add_child()->set_field(3); + childMatcher->add_child()->set_field(1); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Multiple fields. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + childMatcher = matcher.add_child(); + childMatcher->set_field(4); + childMatcher->add_child()->set_field(3); + childMatcher->add_child()->set_field(1); + matcher.add_child()->set_field(3); + EXPECT_TRUE(getSubDimension(dimension, matcher, &sub_dimension)); + + // Subset of the fields not exist. + matcher.Clear(); + sub_dimension.Clear(); + matcher.set_field(tagId); + childMatcher = matcher.add_child(); + childMatcher->set_field(4); + childMatcher->add_child()->set_field(3); + childMatcher->add_child()->set_field(1); + matcher.add_child()->set_field(2); + EXPECT_FALSE(getSubDimension(dimension, matcher, &sub_dimension)); +} + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5d48efb55f69d126696af55c4b4049540534a05 --- /dev/null +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp @@ -0,0 +1,725 @@ +// 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. + +#include + +#include "src/StatsLogProcessor.h" +#include "src/stats_log_util.h" +#include "tests/statsd_test_util.h" + +#include + +namespace android { +namespace os { +namespace statsd { + +#ifdef __ANDROID__ + +namespace { + +StatsdConfig CreateCountMetricWithNoLinkConfig() { + StatsdConfig config; + auto screenBrightnessChangeAtomMatcher = CreateScreenBrightnessChangedAtomMatcher(); + *config.add_atom_matcher() = screenBrightnessChangeAtomMatcher; + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher(); + *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher(); + + auto screenIsOffPredicate = CreateScreenIsOffPredicate(); + *config.add_predicate() = screenIsOffPredicate; + + auto holdingWakelockPredicate = CreateHoldingWakelockPredicate(); + // The predicate is dimensioning by any attribution node and both by uid and tag. + *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = + CreateAttributionUidAndTagDimensions( + android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + *config.add_predicate() = holdingWakelockPredicate; + + auto combinationPredicate = config.add_predicate(); + combinationPredicate->set_id(987654); + combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); + addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); + addPredicateToPredicateCombination(holdingWakelockPredicate, combinationPredicate); + + auto metric = config.add_count_metric(); + metric->set_id(StringToId("ScreenBrightnessChangeMetric")); + metric->set_what(screenBrightnessChangeAtomMatcher.id()); + metric->set_condition(combinationPredicate->id()); + *metric->mutable_dimensions_in_what() = CreateDimensions( + android::util::SCREEN_BRIGHTNESS_CHANGED, {1 /* level */}); + *metric->mutable_dimensions_in_condition() = CreateAttributionUidDimensions( + android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + metric->set_bucket(ONE_MINUTE); + return config; +} + +} // namespace + +TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { + ConfigKey cfgKey; + auto config = CreateCountMetricWithNoLinkConfig(); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; + + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + + std::vector attributions1 = + {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; + + std::vector attributions2 = + {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; + + std::vector> events; + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + bucketSizeNs + 1)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * bucketSizeNs - 10)); + + events.push_back(CreateAcquireWakelockEvent( + attributions1, "wl1", bucketStartTimeNs + 200)); + events.push_back(CreateReleaseWakelockEvent( + attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1)); + + events.push_back(CreateAcquireWakelockEvent( + attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 100)); + events.push_back(CreateReleaseWakelockEvent( + attributions2, "wl2", bucketStartTimeNs + 2 * bucketSizeNs - 50)); + + events.push_back(CreateScreenBrightnessChangedEvent( + 123, bucketStartTimeNs + 11)); + events.push_back(CreateScreenBrightnessChangedEvent( + 123, bucketStartTimeNs + 101)); + events.push_back(CreateScreenBrightnessChangedEvent( + 123, bucketStartTimeNs + 201)); + events.push_back(CreateScreenBrightnessChangedEvent( + 456, bucketStartTimeNs + 203)); + events.push_back(CreateScreenBrightnessChangedEvent( + 456, bucketStartTimeNs + bucketSizeNs - 99)); + events.push_back(CreateScreenBrightnessChangedEvent( + 456, bucketStartTimeNs + bucketSizeNs - 2)); + events.push_back(CreateScreenBrightnessChangedEvent( + 789, bucketStartTimeNs + bucketSizeNs - 1)); + events.push_back(CreateScreenBrightnessChangedEvent( + 456, bucketStartTimeNs + bucketSizeNs + 2)); + events.push_back(CreateScreenBrightnessChangedEvent( + 789, bucketStartTimeNs + 2 * bucketSizeNs - 11)); + events.push_back(CreateScreenBrightnessChangedEvent( + 789, bucketStartTimeNs + 2 * bucketSizeNs - 9)); + events.push_back(CreateScreenBrightnessChangedEvent( + 789, bucketStartTimeNs + 2 * bucketSizeNs - 1)); + + sortLogEventsByTimestamp(&events); + + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports); + + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + StatsLogReport::CountMetricDataWrapper countMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); + + EXPECT_EQ(countMetrics.data_size(), 7); + auto data = countMetrics.data(0); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs ); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + + data = countMetrics.data(1); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 123); + ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 111); + + data = countMetrics.data(2); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 3); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456); + ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 111); + + data = countMetrics.data(3); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).count(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).count(), 1); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 456); + ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 333); + + data = countMetrics.data(4); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + + data = countMetrics.data(5); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); + ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 111); + + data = countMetrics.data(6); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 789); + ValidateAttributionUidDimension(data.dimensions_in_condition(), android::util::WAKELOCK_STATE_CHANGED, 333); +} + +namespace { + +StatsdConfig CreateCountMetricWithLinkConfig() { + StatsdConfig config; + auto appCrashMatcher = CreateProcessCrashAtomMatcher(); + *config.add_atom_matcher() = appCrashMatcher; + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); + *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); + + auto screenIsOffPredicate = CreateScreenIsOffPredicate(); + auto isSyncingPredicate = CreateIsSyncingPredicate(); + auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); + *syncDimension = CreateAttributionUidAndTagDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + syncDimension->add_child()->set_field(2 /* name field*/); + + *config.add_predicate() = screenIsOffPredicate; + *config.add_predicate() = isSyncingPredicate; + auto combinationPredicate = config.add_predicate(); + combinationPredicate->set_id(987654); + combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); + addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); + addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); + + auto metric = config.add_count_metric(); + metric->set_bucket(ONE_MINUTE); + metric->set_id(StringToId("AppCrashMetric")); + metric->set_what(appCrashMatcher.id()); + metric->set_condition(combinationPredicate->id()); + *metric->mutable_dimensions_in_what() = CreateDimensions( + android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1 /* uid */}); + *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + + // Links between crash atom and condition of app is in syncing. + auto links = metric->add_links(); + links->set_condition(isSyncingPredicate.id()); + auto dimensionWhat = links->mutable_fields_in_what(); + dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); + dimensionWhat->add_child()->set_field(1); // uid field. + *links->mutable_fields_in_condition() = CreateAttributionUidDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + return config; +} + +} // namespace + +TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { + ConfigKey cfgKey; + auto config = CreateCountMetricWithLinkConfig(); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; + + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + std::vector attributions1 = + {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; + + std::vector attributions2 = + {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; + + std::vector> events; + + events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 11)); + events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 101)); + events.push_back(CreateAppCrashEvent(222, bucketStartTimeNs + 101)); + + events.push_back(CreateAppCrashEvent(222, bucketStartTimeNs + 201)); + events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 211)); + events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + 211)); + + events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + 401)); + events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + 401)); + events.push_back(CreateAppCrashEvent(555, bucketStartTimeNs + 401)); + + events.push_back(CreateAppCrashEvent(111, bucketStartTimeNs + bucketSizeNs + 301)); + events.push_back(CreateAppCrashEvent(333, bucketStartTimeNs + bucketSizeNs + 301)); + + events.push_back(CreateAppCrashEvent(777, bucketStartTimeNs + bucketSizeNs + 701)); + + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 202)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + bucketSizeNs + 700)); + + events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 300)); + + events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", + bucketStartTimeNs + bucketSizeNs - 1)); + + events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 400)); + events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 600)); + + sortLogEventsByTimestamp(&events); + + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports); + + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + StatsLogReport::CountMetricDataWrapper countMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); + + EXPECT_EQ(countMetrics.data_size(), 5); + auto data = countMetrics.data(0); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + + data = countMetrics.data(1); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + + data = countMetrics.data(2); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 222); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 2); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + + data = countMetrics.data(3); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).count(), 1); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + + data = countMetrics.data(4); + EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 777); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); +} + +namespace { + +StatsdConfig CreateDurationMetricConfigNoLink(DurationMetric::AggregationType aggregationType) { + StatsdConfig config; + *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher(); + *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); + *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); + + auto inBatterySaverModePredicate = CreateBatterySaverModePredicate(); + + auto screenIsOffPredicate = CreateScreenIsOffPredicate(); + auto isSyncingPredicate = CreateIsSyncingPredicate(); + auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); + *syncDimension = CreateAttributionUidAndTagDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + syncDimension->add_child()->set_field(2 /* name field */); + + *config.add_predicate() = inBatterySaverModePredicate; + *config.add_predicate() = screenIsOffPredicate; + *config.add_predicate() = isSyncingPredicate; + auto combinationPredicate = config.add_predicate(); + combinationPredicate->set_id(987654); + combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); + addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); + addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); + + auto metric = config.add_duration_metric(); + metric->set_bucket(ONE_MINUTE); + metric->set_id(StringToId("BatterySaverModeDurationMetric")); + metric->set_what(inBatterySaverModePredicate.id()); + metric->set_condition(combinationPredicate->id()); + *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + return config; +} + +} // namespace + + +TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) { + for (auto aggregationType : { DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { + ConfigKey cfgKey; + auto config = CreateDurationMetricConfigNoLink(aggregationType); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; + + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + + std::vector attributions1 = + {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; + + std::vector attributions2 = + {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; + + std::vector> events; + + events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 1)); + events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 101)); + events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 110)); + + events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 201)); + events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 500)); + + events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 600)); + events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 850)); + + events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + bucketSizeNs + 870)); + events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + bucketSizeNs + 900)); + + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 202)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + bucketSizeNs + 800)); + + events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 300)); + + events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", + bucketStartTimeNs + bucketSizeNs - 1)); + + events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401)); + events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 700)); + + sortLogEventsByTimestamp(&events); + + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports); + + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + StatsLogReport::DurationMetricDataWrapper metrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metrics); + + EXPECT_EQ(metrics.data_size(), 3); + auto data = metrics.data(0); + EXPECT_FALSE(data.dimensions_in_what().has_field()); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + + data = metrics.data(1); + EXPECT_FALSE(data.dimensions_in_what().has_field()); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + + data = metrics.data(2); + EXPECT_FALSE(data.dimensions_in_what().has_field()); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + } +} + +namespace { + +StatsdConfig CreateDurationMetricConfigWithLink(DurationMetric::AggregationType aggregationType) { + StatsdConfig config; + *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); + *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + *config.add_atom_matcher() = CreateSyncStartAtomMatcher(); + *config.add_atom_matcher() = CreateSyncEndAtomMatcher(); + + auto screenIsOffPredicate = CreateScreenIsOffPredicate(); + auto isSyncingPredicate = CreateIsSyncingPredicate(); + auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); + *syncDimension = CreateAttributionUidAndTagDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + syncDimension->add_child()->set_field(2 /* name field */); + + auto isInBackgroundPredicate = CreateIsInBackgroundPredicate(); + *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = + CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ }); + + *config.add_predicate() = screenIsOffPredicate; + *config.add_predicate() = isSyncingPredicate; + *config.add_predicate() = isInBackgroundPredicate; + auto combinationPredicate = config.add_predicate(); + combinationPredicate->set_id(987654); + combinationPredicate->mutable_combination()->set_operation(LogicalOperation::OR); + addPredicateToPredicateCombination(screenIsOffPredicate, combinationPredicate); + addPredicateToPredicateCombination(isSyncingPredicate, combinationPredicate); + + auto metric = config.add_duration_metric(); + metric->set_bucket(ONE_MINUTE); + metric->set_id(StringToId("AppInBackgroundMetric")); + metric->set_what(isInBackgroundPredicate.id()); + metric->set_condition(combinationPredicate->id()); + *metric->mutable_dimensions_in_what() = CreateDimensions( + android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ }); + *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + + // Links between crash atom and condition of app is in syncing. + auto links = metric->add_links(); + links->set_condition(isSyncingPredicate.id()); + auto dimensionWhat = links->mutable_fields_in_what(); + dimensionWhat->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); + dimensionWhat->add_child()->set_field(1); // uid field. + *links->mutable_fields_in_condition() = CreateAttributionUidDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + return config; +} + +} // namespace + +TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) { + for (auto aggregationType : { DurationMetric::SUM, DurationMetric::MAX_SPARSE}) { + ConfigKey cfgKey; + auto config = CreateDurationMetricConfigWithLink(aggregationType); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL; + + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + + std::vector attributions1 = + {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(222, "GMSCoreModule2")}; + + std::vector attributions2 = + {CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(555, "GMSCoreModule2")}; + + std::vector> events; + + events.push_back(CreateMoveToBackgroundEvent(111, bucketStartTimeNs + 101)); + events.push_back(CreateMoveToForegroundEvent(111, bucketStartTimeNs + 110)); + + events.push_back(CreateMoveToBackgroundEvent(111, bucketStartTimeNs + 201)); + events.push_back(CreateMoveToForegroundEvent(111, bucketStartTimeNs + bucketSizeNs + 100)); + + events.push_back(CreateMoveToBackgroundEvent(333, bucketStartTimeNs + 399)); + events.push_back(CreateMoveToForegroundEvent(333, bucketStartTimeNs + bucketSizeNs + 800)); + + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 100)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 202)); + events.push_back(CreateScreenStateChangedEvent( + android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + bucketSizeNs + 801)); + + events.push_back(CreateSyncStartEvent(attributions1, "ReadEmail", bucketStartTimeNs + 200)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 300)); + + events.push_back(CreateSyncStartEvent(attributions1, "ReadDoc", bucketStartTimeNs + 400)); + events.push_back(CreateSyncEndEvent(attributions1, "ReadDoc", + bucketStartTimeNs + bucketSizeNs - 1)); + + events.push_back(CreateSyncStartEvent(attributions2, "ReadEmail", bucketStartTimeNs + 401)); + events.push_back(CreateSyncEndEvent(attributions2, "ReadEmail", + bucketStartTimeNs + bucketSizeNs + 700)); + + sortLogEventsByTimestamp(&events); + + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &reports); + + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + StatsLogReport::DurationMetricDataWrapper metrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), &metrics); + + EXPECT_EQ(metrics.data_size(), 3); + auto data = metrics.data(0); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); + EXPECT_FALSE(data.dimensions_in_condition().has_field()); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + + data = metrics.data(1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 111); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 111, "App1"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + + data = metrics.data(2); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), 333); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_condition(), android::util::SYNC_STATE_CHANGED, 333, "App2"); + EXPECT_EQ(data.bucket_info_size(), 2); + EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401); + EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); + EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + } +} + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif + +} // namespace statsd +} // namespace os +} // namespace android \ No newline at end of file diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp index e56a6c57848f2aa0beed0be965b02b85dd264855..a80fdc5606b755c1a2a0e22015f14883d9c0e322 100644 --- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp @@ -153,23 +153,26 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) { EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid1); EXPECT_EQ(data.bucket_info_size(), 3); + EXPECT_EQ(data.bucket_info(0).atom_size(), 1); EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().type(), AppStartChanged::HOT); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_name(), "activity_name2"); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_start_msec(), 102L); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2"); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 102L); + EXPECT_EQ(data.bucket_info(1).atom_size(), 1); EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().type(), AppStartChanged::WARM); - EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().activity_name(), "activity_name4"); - EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().activity_start_msec(), 104L); + EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM); + EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4"); + EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_msec(), 104L); + EXPECT_EQ(data.bucket_info(2).atom_size(), 1); EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().type(), AppStartChanged::COLD); - EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_name(), "activity_name5"); - EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_start_msec(), 105L); + EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD); + EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5"); + EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_msec(), 105L); data = gaugeMetrics.data(1); @@ -178,11 +181,12 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) { EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid2); EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).atom_size(), 1); EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().type(), AppStartChanged::COLD); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_name(), "activity_name7"); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_start_msec(), 201L); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7"); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 201L); } #else diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp index 4504a95c8ef0137c8b55de6477202c7d9afd3b9c..233031c5c8da4f91d44a23e794d41cdac51f8536 100644 --- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp @@ -44,9 +44,10 @@ StatsdConfig CreateStatsdConfig() { auto screenIsOffPredicate = CreateScreenIsOffPredicate(); auto isSyncingPredicate = CreateIsSyncingPredicate(); - *isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions() = - CreateDimensions( - android::util::SYNC_STATE_CHANGED, {1 /* uid field */, 2 /* name field*/}); + auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); + *syncDimension = CreateAttributionUidDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + syncDimension->add_child()->set_field(2 /* name field*/); auto isInBackgroundPredicate = CreateIsInBackgroundPredicate(); *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = @@ -78,9 +79,8 @@ StatsdConfig CreateStatsdConfig() { auto dimensionWhat = links->mutable_fields_in_what(); dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); dimensionWhat->add_child()->set_field(1); // uid field. - auto dimensionCondition = links->mutable_fields_in_condition(); - dimensionCondition->set_field(android::util::SYNC_STATE_CHANGED); - dimensionCondition->add_child()->set_field(1); // uid field. + *links->mutable_fields_in_condition() = CreateAttributionUidDimensions( + android::util::SYNC_STATE_CHANGED, {Position::FIRST}); // Links between crash atom and condition of app is in background. links = countMetric->add_links(); @@ -88,7 +88,7 @@ StatsdConfig CreateStatsdConfig() { dimensionWhat = links->mutable_fields_in_what(); dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); dimensionWhat->add_child()->set_field(1); // uid field. - dimensionCondition = links->mutable_fields_in_condition(); + auto dimensionCondition = links->mutable_fields_in_condition(); dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); dimensionCondition->add_child()->set_field(1); // uid field. return config; @@ -132,12 +132,14 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks) { CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2 * bucketSizeNs - 100); + std::vector attributions = + {CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")}; auto syncOnEvent1 = - CreateSyncStartEvent(appUid, "ReadEmail", bucketStartTimeNs + 50); + CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50); auto syncOffEvent1 = - CreateSyncEndEvent(appUid, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300); + CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300); auto syncOnEvent2 = - CreateSyncStartEvent(appUid, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000); + CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000); auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15); diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp index 897328d4635ef0908514034c68f11611bcaa26bf..50b3532e827a62f9acea2e216877435190669a73 100644 --- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp @@ -67,9 +67,9 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) { // Flushes. countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1); EXPECT_EQ(1UL, countProducer.mPastBuckets.size()); - EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != countProducer.mPastBuckets.end()); - const auto& buckets = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY]; + const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(1UL, buckets.size()); EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs); EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs); @@ -80,10 +80,10 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) { countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3); countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1); EXPECT_EQ(1UL, countProducer.mPastBuckets.size()); - EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != countProducer.mPastBuckets.end()); - EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY].size()); - const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY][1]; + EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1]; EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs); EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs); EXPECT_EQ(1LL, bucketInfo2.mCount); @@ -91,9 +91,9 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) { // nothing happens in bucket 3. we should not record anything for bucket 3. countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1); EXPECT_EQ(1UL, countProducer.mPastBuckets.size()); - EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != countProducer.mPastBuckets.end()); - const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY]; + const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(2UL, buckets3.size()); } @@ -124,10 +124,10 @@ TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) { countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1); EXPECT_EQ(1UL, countProducer.mPastBuckets.size()); - EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != countProducer.mPastBuckets.end()); { - const auto& buckets = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY]; + const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(1UL, buckets.size()); const auto& bucketInfo = buckets[0]; EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs); @@ -149,8 +149,8 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) { metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON")); MetricConditionLink* link = metric.add_links(); link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID")); - *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1); - *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2); + buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what()); + buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition()); LogEvent event1(tagId, bucketStartTimeNs + 1); event1.write("111"); // uid @@ -167,9 +167,9 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) { {getMockedDimensionKey(conditionTagId, 2, "222")}; sp wizard = new NaggyMock(); - EXPECT_CALL(*wizard, query(_, key1)).WillOnce(Return(ConditionState::kFalse)); + EXPECT_CALL(*wizard, query(_, key1, _, _)).WillOnce(Return(ConditionState::kFalse)); - EXPECT_CALL(*wizard, query(_, key2)).WillOnce(Return(ConditionState::kTrue)); + EXPECT_CALL(*wizard, query(_, key2, _, _)).WillOnce(Return(ConditionState::kTrue)); CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard, bucketStartTimeNs); @@ -181,9 +181,9 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) { countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2); countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1); EXPECT_EQ(1UL, countProducer.mPastBuckets.size()); - EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != countProducer.mPastBuckets.end()); - const auto& buckets = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY]; + const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(1UL, buckets.size()); const auto& bucketInfo = buckets[0]; EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs); @@ -229,13 +229,13 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) { EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size()); EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second); - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); // One event in bucket #2. No alarm as bucket #0 is trashed out. countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3); EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size()); EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second); - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); // Two events in bucket #3. countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4); @@ -244,13 +244,13 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) { EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size()); EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second); // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6 - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event5.GetTimestampNs() / NS_PER_SEC + refPeriodSec); countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7); EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size()); EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second); - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event7.GetTimestampNs() / NS_PER_SEC + refPeriodSec); } diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp index a59f1fe663545c42096eff8793432b1efdc367bf..c9fe2523c577d520b10e5d95a8cd876b571d2557 100644 --- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp @@ -62,9 +62,9 @@ TEST(DurationMetricTrackerTest, TestNoCondition) { durationProducer.onMatchedLogEvent(2 /* stop index*/, event2); durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1); EXPECT_EQ(1UL, durationProducer.mPastBuckets.size()); - EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != durationProducer.mPastBuckets.end()); - const auto& buckets = durationProducer.mPastBuckets[DEFAULT_DIMENSION_KEY]; + const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(2UL, buckets.size()); EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs); EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs); @@ -107,9 +107,9 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) { durationProducer.onMatchedLogEvent(2 /* stop index*/, event4); durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1); EXPECT_EQ(1UL, durationProducer.mPastBuckets.size()); - EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) != + EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) != durationProducer.mPastBuckets.end()); - const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_DIMENSION_KEY]; + const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(1UL, buckets2.size()); EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs); EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs); diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp index 34cde607988e473e721cf2c9fe96435459ce006e..3deab3710dd105a42c685abc4504e38528cb3a8b 100644 --- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp @@ -98,8 +98,8 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) { metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON")); MetricConditionLink* link = metric.add_links(); link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID")); - *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1); - *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2); + buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what()); + buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition()); LogEvent event1(tagId, bucketStartTimeNs + 1); EXPECT_TRUE(event1.write("111")); @@ -114,9 +114,9 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) { key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")}; sp wizard = new NaggyMock(); - EXPECT_CALL(*wizard, query(_, key1)).WillOnce(Return(ConditionState::kFalse)); + EXPECT_CALL(*wizard, query(_, key1, _, _)).WillOnce(Return(ConditionState::kFalse)); - EXPECT_CALL(*wizard, query(_, key2)).WillOnce(Return(ConditionState::kTrue)); + EXPECT_CALL(*wizard, query(_, key2, _, _)).WillOnce(Return(ConditionState::kTrue)); EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 82772d854db27a2ade3e1728628e4b849d2201a0..58be5b071b53190fe1e6bc2bb78f1b2747155e58 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -78,7 +78,7 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { gaugeProducer.onDataPulled(allData); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin(); + auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin(); EXPECT_EQ(10, it->second.value_int()); it++; EXPECT_EQ(11, it->second.value_int()); @@ -94,14 +94,14 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { allData.push_back(event2); gaugeProducer.onDataPulled(allData); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin(); + it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin(); EXPECT_EQ(24, it->second.value_int()); it++; EXPECT_EQ(25, it->second.value_int()); // One dimension. EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size()); - it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin(); + it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin(); EXPECT_EQ(10L, it->second.value_int()); it++; EXPECT_EQ(11L, it->second.value_int()); @@ -112,7 +112,7 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { // One dimension. EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); - it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin(); + it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin(); EXPECT_EQ(24L, it->second.value_int()); it++; EXPECT_EQ(25L, it->second.value_int()); @@ -151,7 +151,8 @@ TEST(GaugeMetricProducerTest, TestWithCondition) { gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(100, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size()); vector> allData; @@ -165,17 +166,18 @@ TEST(GaugeMetricProducerTest, TestWithCondition) { EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(110, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()->second.back() - .mGaugeFields->begin()->second.value_int()); + .mGaugeAtoms.front().mFields->begin()->second.value_int()); gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10); gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()->second.back() - .mGaugeFields->begin()->second.value_int()); + .mGaugeAtoms.front().mFields->begin()->second.value_int()); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum); } @@ -214,8 +216,9 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { gaugeProducer.onDataPulled({event1}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(13L, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); std::shared_ptr event2 = std::make_shared(tagId, bucketStartTimeNs + bucketSizeNs + 20); @@ -226,8 +229,9 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { gaugeProducer.onDataPulled({event2}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(15L, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec); std::shared_ptr event3 = @@ -239,8 +243,9 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { gaugeProducer.onDataPulled({event3}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(26L, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec); // The event4 does not have the gauge field. Thus the current bucket value is 0. @@ -250,7 +255,7 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { event4->init(); gaugeProducer.onDataPulled({event4}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second->empty()); + EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty()); } } // namespace statsd diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp index 0772b0d4001df408d3526d82aebcb547b618228e..203f028080d2b8033fd93dd0a7ad8e49aef9742e 100644 --- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp +++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp @@ -41,22 +41,24 @@ const ConfigKey kConfigKey(0, 12345); const int TagId = 1; -const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "1"); -const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; -const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); -const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; + const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); + const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); + + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs, - bucketSizeNs, false, {}); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, false, {}); tracker.noteStart(key1, true, bucketStartTimeNs, ConditionKey()); // Event starts again. This would not change anything as it already starts. @@ -75,16 +77,22 @@ TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) { } TEST(MaxDurationTrackerTest, TestStopAll) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; + const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); + const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); + + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs, - bucketSizeNs, false, {}); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, false, {}); tracker.noteStart(key1, true, bucketStartTimeNs + 1, ConditionKey()); @@ -105,21 +113,26 @@ TEST(MaxDurationTrackerTest, TestStopAll) { } TEST(MaxDurationTrackerTest, TestCrossBucketBoundary) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; + const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); + const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs, - bucketSizeNs, false, {}); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, false, {}); // The event starts. tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey()); - // Starts again. Does not change anything. + // Starts again. Does not DEFAULT_DIMENSION_KEY anything. tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + bucketSizeNs + 1, ConditionKey()); @@ -135,16 +148,21 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary) { } TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; + const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); + const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, true, bucketStartTimeNs, - bucketSizeNs, false, {}); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, false, {}); // 2 starts tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey()); @@ -160,7 +178,8 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration); // real stop now. - tracker.noteStop(DEFAULT_DIMENSION_KEY, bucketStartTimeNs + (2 * bucketSizeNs) + 5, false); + tracker.noteStop(DEFAULT_DIMENSION_KEY, + bucketStartTimeNs + (2 * bucketSizeNs) + 5, false); tracker.flushIfNeeded(bucketStartTimeNs + (3 * bucketSizeNs) + 1, &buckets); EXPECT_EQ(3u, buckets[eventKey].size()); @@ -170,16 +189,20 @@ TEST(MaxDurationTrackerTest, TestCrossBucketBoundary_nested) { } TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { + const std::vector conditionKey = {getMockedDimensionKey(TagId, 4, "1")}; + const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); + + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); ConditionKey conditionKey1; - HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 2, "maps"); + MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 2, "maps"); conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey; - EXPECT_CALL(*wizard, query(_, conditionKey1)) // #4 + EXPECT_CALL(*wizard, query(_, conditionKey1, _, _)) // #4 .WillOnce(Return(ConditionState::kFalse)); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; @@ -187,8 +210,8 @@ TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { int64_t durationTimeNs = 2 * 1000; int64_t metricId = 1; - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs, - bucketSizeNs, true, {}); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, true, {}); EXPECT_TRUE(tracker.mAnomalyTrackers.empty()); tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1); @@ -204,6 +227,10 @@ TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) { } TEST(MaxDurationTrackerTest, TestAnomalyDetection) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1"); + const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1"); + const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2"); + FieldMatcher dimensionInCondition; int64_t metricId = 1; Alert alert; alert.set_id(101); @@ -213,7 +240,7 @@ TEST(MaxDurationTrackerTest, TestAnomalyDetection) { const int32_t refPeriodSec = 1; alert.set_refractory_period_secs(refPeriodSec); - unordered_map> buckets; + unordered_map> buckets; sp wizard = new NaggyMock(); uint64_t bucketStartTimeNs = 10 * NS_PER_SEC; @@ -221,8 +248,8 @@ TEST(MaxDurationTrackerTest, TestAnomalyDetection) { uint64_t bucketSizeNs = 30 * NS_PER_SEC; sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); - MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, true, bucketStartTimeNs, - bucketSizeNs, false, {anomalyTracker}); + MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker}); tracker.noteStart(key1, true, eventStartTimeNs, ConditionKey()); tracker.noteStop(key1, eventStartTimeNs + 10, false); diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp index 6b8893e5973f9c3b7df34c88b0dbb4b05efeaf09..80e16a1f3b55557e53f0daa1146c7c69aa59deb7 100644 --- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp +++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp @@ -38,24 +38,26 @@ namespace statsd { const ConfigKey kConfigKey(0, 12345); const int TagId = 1; const int64_t metricId = 123; -const HashableDimensionKey eventKey = getMockedDimensionKey(TagId, 0, "event"); - -const std::vector kConditionKey1 = {getMockedDimensionKey(TagId, 1, "maps")}; -const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); -const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); TEST(OringDurationTrackerTest, TestDurationOverlap) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, - bucketStartTimeNs, bucketSizeNs, false, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, false, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey()); EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime); @@ -71,16 +73,23 @@ TEST(OringDurationTrackerTest, TestDurationOverlap) { } TEST(OringDurationTrackerTest, TestDurationNested) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, - bucketSizeNs, false, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, false, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey()); tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl @@ -95,16 +104,23 @@ TEST(OringDurationTrackerTest, TestDurationNested) { } TEST(OringDurationTrackerTest, TestStopAll) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, - bucketSizeNs, false, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, false, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey()); tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl @@ -118,17 +134,24 @@ TEST(OringDurationTrackerTest, TestStopAll) { } TEST(OringDurationTrackerTest, TestCrossBucketBoundary) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, - bucketSizeNs, false, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, false, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey()); EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime); @@ -150,23 +173,30 @@ TEST(OringDurationTrackerTest, TestCrossBucketBoundary) { } TEST(OringDurationTrackerTest, TestDurationConditionChange) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); ConditionKey key1; key1[StringToId("APP_BACKGROUND")] = kConditionKey1; - EXPECT_CALL(*wizard, query(_, key1)) // #4 + EXPECT_CALL(*wizard, query(_, key1, _, _)) // #4 .WillOnce(Return(ConditionState::kFalse)); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, - bucketStartTimeNs, bucketSizeNs, true, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, true, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1); @@ -181,25 +211,32 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange) { } TEST(OringDurationTrackerTest, TestDurationConditionChange2) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); ConditionKey key1; key1[StringToId("APP_BACKGROUND")] = kConditionKey1; - EXPECT_CALL(*wizard, query(_, key1)) + EXPECT_CALL(*wizard, query(_, key1, _, _)) .Times(2) .WillOnce(Return(ConditionState::kFalse)) .WillOnce(Return(ConditionState::kTrue)); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t durationTimeNs = 2 * 1000; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, - bucketStartTimeNs, bucketSizeNs, true, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + false, bucketStartTimeNs, bucketSizeNs, true, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1); // condition to false; record duration 5n @@ -216,22 +253,29 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange2) { } TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; sp wizard = new NaggyMock(); ConditionKey key1; key1[StringToId("APP_BACKGROUND")] = kConditionKey1; - EXPECT_CALL(*wizard, query(_, key1)) // #4 + EXPECT_CALL(*wizard, query(_, key1, _, _)) // #4 .WillOnce(Return(ConditionState::kFalse)); - unordered_map> buckets; + unordered_map> buckets; uint64_t bucketStartTimeNs = 10000000000; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, - bucketSizeNs, true, {}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, true, {}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1); tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2, key1); @@ -249,6 +293,13 @@ TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) { } TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -256,7 +307,7 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { alert.set_num_buckets(2); alert.set_refractory_period_secs(1); - unordered_map> buckets; + unordered_map> buckets; sp wizard = new NaggyMock(); uint64_t bucketStartTimeNs = 10 * NS_PER_SEC; @@ -264,8 +315,8 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { uint64_t bucketSizeNs = 30 * NS_PER_SEC; sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs, - bucketSizeNs, true, {anomalyTracker}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true, bucketStartTimeNs, bucketSizeNs, true, {anomalyTracker}); // Nothing in the past bucket. tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey()); @@ -310,6 +361,12 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { } TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -318,7 +375,7 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { const int32_t refPeriodSec = 45; alert.set_refractory_period_secs(refPeriodSec); - unordered_map> buckets; + unordered_map> buckets; sp wizard = new NaggyMock(); uint64_t bucketStartTimeNs = 10 * NS_PER_SEC; @@ -326,8 +383,8 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { uint64_t bucketSizeNs = 30 * NS_PER_SEC; sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/, - bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true /*nesting*/, bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker}); tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey()); tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false); @@ -352,6 +409,13 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { } TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { + const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event"); + + const std::vector kConditionKey1 = + {getMockedDimensionKey(TagId, 1, "maps")}; + const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps"); + const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps"); + FieldMatcher dimensionInCondition; Alert alert; alert.set_id(101); alert.set_metric_id(1); @@ -360,7 +424,7 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { const int32_t refPeriodSec = 45; alert.set_refractory_period_secs(refPeriodSec); - unordered_map> buckets; + unordered_map> buckets; sp wizard = new NaggyMock(); ConditionKey conkey; conkey[StringToId("APP_BACKGROUND")] = kConditionKey1; @@ -369,8 +433,9 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { uint64_t bucketSizeNs = 30 * NS_PER_SEC; sp anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); - OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/, - bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker}); + OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition, + true /*nesting*/, bucketStartTimeNs, bucketSizeNs, false, + {anomalyTracker}); tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey); // start key1 EXPECT_EQ(1u, anomalyTracker->mAlarms.size()); diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index fff3dbf5428d99775e48649b39fad09f5bfcfabc..55c078dcbab808d99507f97d3714a3cd2fd3cb57 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -299,26 +299,26 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); // Value sum == 30 <= 130. - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); // One event in bucket #2. No alarm as bucket #0 is trashed out. valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); // Value sum == 130 <= 130. - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U); + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); // Three events in bucket #3. valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); // Anomaly at event 4 since Value sum == 131 > 130! - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec); valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5); // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4. - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec); valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6); // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period. - EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), + EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), event6->GetTimestampNs() / NS_PER_SEC + refPeriodSec); } diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.cpp b/cmds/statsd/tests/metrics/metrics_test_helper.cpp index fc7245ca54e327fd592338d2c8af5b67b6fd4812..ab9345af172e9737f3bf3c1e75b07b444daa070b 100644 --- a/cmds/statsd/tests/metrics/metrics_test_helper.cpp +++ b/cmds/statsd/tests/metrics/metrics_test_helper.cpp @@ -26,6 +26,13 @@ HashableDimensionKey getMockedDimensionKey(int tagId, int key, string value) { return HashableDimensionKey(dimensionsValue); } +MetricDimensionKey getMockedMetricDimensionKey(int tagId, int key, string value) { + DimensionsValue dimensionsValue; + dimensionsValue.set_field(tagId); + dimensionsValue.mutable_value_tuple()->add_dimensions_value()->set_field(key); + dimensionsValue.mutable_value_tuple()->mutable_dimensions_value(0)->set_value_str(value); + return MetricDimensionKey(HashableDimensionKey(dimensionsValue), DEFAULT_DIMENSION_KEY); +} } // namespace statsd } // namespace os } // namespace android \ No newline at end of file diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h index 23e86f92f844b85cf4cc5a0f8b789d5e3ca77de3..0a97456c56847f99ff422a51ee54a6bbc47d1acd 100644 --- a/cmds/statsd/tests/metrics/metrics_test_helper.h +++ b/cmds/statsd/tests/metrics/metrics_test_helper.h @@ -25,10 +25,12 @@ namespace statsd { class MockConditionWizard : public ConditionWizard { public: - MOCK_METHOD2( + MOCK_METHOD4( query, ConditionState(const int conditionIndex, - const ConditionKey& conditionParameters)); + const ConditionKey& conditionParameters, + const FieldMatcher& dimensionFields, + std::unordered_set *dimensionKeySet)); }; class MockStatsPullerManager : public StatsPullerManager { @@ -39,6 +41,7 @@ public: }; HashableDimensionKey getMockedDimensionKey(int tagId, int key, std::string value); +MetricDimensionKey getMockedMetricDimensionKey(int tagId, int key, std::string value); } // namespace statsd } // namespace os diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index 9f4582dc6994ea42580449d2dbe7b7491e12b6bd..13055cb9e7a30226e34a38dc13b973414593319a 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include "statsd_test_util.h" namespace android { @@ -27,6 +26,22 @@ AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) { return atom_matcher; } +AtomMatcher CreateScreenBrightnessChangedAtomMatcher() { + AtomMatcher atom_matcher; + atom_matcher.set_id(StringToId("ScreenBrightnessChanged")); + auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); + simple_atom_matcher->set_atom_id(android::util::SCREEN_BRIGHTNESS_CHANGED); + return atom_matcher; +} + +AtomMatcher CreateUidProcessStateChangedAtomMatcher() { + AtomMatcher atom_matcher; + atom_matcher.set_id(StringToId("UidProcessStateChanged")); + auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); + simple_atom_matcher->set_atom_id(android::util::UID_PROCESS_STATE_CHANGED); + return atom_matcher; +} + AtomMatcher CreateWakelockStateChangedAtomMatcher(const string& name, WakelockStateChanged::State state) { AtomMatcher atom_matcher; @@ -47,6 +62,30 @@ AtomMatcher CreateReleaseWakelockAtomMatcher() { return CreateWakelockStateChangedAtomMatcher("ReleaseWakelock", WakelockStateChanged::RELEASE); } +AtomMatcher CreateBatterySaverModeStateChangedAtomMatcher( + const string& name, BatterySaverModeStateChanged::State state) { + AtomMatcher atom_matcher; + atom_matcher.set_id(StringToId(name)); + auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); + simple_atom_matcher->set_atom_id(android::util::BATTERY_SAVER_MODE_STATE_CHANGED); + auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); + field_value_matcher->set_field(1); // State field. + field_value_matcher->set_eq_int(state); + return atom_matcher; +} + +AtomMatcher CreateBatterySaverModeStartAtomMatcher() { + return CreateBatterySaverModeStateChangedAtomMatcher( + "BatterySaverModeStart", BatterySaverModeStateChanged::ON); +} + + +AtomMatcher CreateBatterySaverModeStopAtomMatcher() { + return CreateBatterySaverModeStateChangedAtomMatcher( + "BatterySaverModeStop", BatterySaverModeStateChanged::OFF); +} + + AtomMatcher CreateScreenStateChangedAtomMatcher( const string& name, android::view::DisplayStateEnum state) { AtomMatcher atom_matcher; @@ -59,6 +98,7 @@ AtomMatcher CreateScreenStateChangedAtomMatcher( return atom_matcher; } + AtomMatcher CreateScreenTurnedOnAtomMatcher() { return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", android::view::DisplayStateEnum::DISPLAY_STATE_ON); @@ -128,6 +168,13 @@ AtomMatcher CreateProcessCrashAtomMatcher() { "ProcessCrashed", ProcessLifeCycleStateChanged::PROCESS_CRASHED); } +Predicate CreateBatterySaverModePredicate() { + Predicate predicate; + predicate.set_id(StringToId("BatterySaverIsOn")); + predicate.mutable_simple_predicate()->set_start(StringToId("BatterySaverModeStart")); + predicate.mutable_simple_predicate()->set_stop(StringToId("BatterySaverModeStop")); + return predicate; +} Predicate CreateScreenIsOnPredicate() { Predicate predicate; @@ -218,6 +265,31 @@ std::unique_ptr CreateScreenStateChangedEvent( return event; } +std::unique_ptr CreateBatterySaverOnEvent(uint64_t timestampNs) { + auto event = std::make_unique( + android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs); + EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON)); + event->init(); + return event; +} + +std::unique_ptr CreateBatterySaverOffEvent(uint64_t timestampNs) { + auto event = std::make_unique( + android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs); + EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF)); + event->init(); + return event; +} + +std::unique_ptr CreateScreenBrightnessChangedEvent( + int level, uint64_t timestampNs) { + auto event = std::make_unique(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs); + EXPECT_TRUE(event->write(level)); + event->init(); + return event; + +} + std::unique_ptr CreateWakelockStateChangedEvent( const std::vector& attributions, const string& wakelockName, const WakelockStateChanged::State state, uint64_t timestampNs) { @@ -267,9 +339,10 @@ std::unique_ptr CreateMoveToForegroundEvent(const int uid, uint64_t ti } std::unique_ptr CreateSyncStateChangedEvent( - const int uid, const string& name, const SyncStateChanged::State state, uint64_t timestampNs) { + const std::vector& attributions, + const string& name, const SyncStateChanged::State state, uint64_t timestampNs) { auto event = std::make_unique(android::util::SYNC_STATE_CHANGED, timestampNs); - event->write(uid); + event->write(attributions); event->write(name); event->write(state); event->init(); @@ -277,13 +350,13 @@ std::unique_ptr CreateSyncStateChangedEvent( } std::unique_ptr CreateSyncStartEvent( - const int uid, const string& name, uint64_t timestampNs){ - return CreateSyncStateChangedEvent(uid, name, SyncStateChanged::ON, timestampNs); + const std::vector& attributions, const string& name, uint64_t timestampNs){ + return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs); } std::unique_ptr CreateSyncEndEvent( - const int uid, const string& name, uint64_t timestampNs) { - return CreateSyncStateChangedEvent(uid, name, SyncStateChanged::OFF, timestampNs); + const std::vector& attributions, const string& name, uint64_t timestampNs) { + return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs); } std::unique_ptr CreateProcessLifeCycleStateChangedEvent( diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index ff8fef0c46b6115a9579b49e29cc5ba999ca6105..6638893f6aebcc1babdc8a470c32b8b1dd8804a1 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -14,6 +14,7 @@ #pragma once +#include #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "statslog.h" #include "src/logd/LogEvent.h" @@ -26,6 +27,18 @@ namespace statsd { // Create AtomMatcher proto to simply match a specific atom type. AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId); +// Create AtomMatcher proto for screen brightness state changed. +AtomMatcher CreateScreenBrightnessChangedAtomMatcher(); + +// Create AtomMatcher proto for starting battery save mode. +AtomMatcher CreateBatterySaverModeStartAtomMatcher(); + +// Create AtomMatcher proto for stopping battery save mode. +AtomMatcher CreateBatterySaverModeStopAtomMatcher(); + +// Create AtomMatcher proto for process state changed. +AtomMatcher CreateUidProcessStateChangedAtomMatcher(); + // Create AtomMatcher proto for acquiring wakelock. AtomMatcher CreateAcquireWakelockAtomMatcher(); @@ -59,6 +72,9 @@ Predicate CreateScreenIsOnPredicate(); // Create Predicate proto for screen is off. Predicate CreateScreenIsOffPredicate(); +// Create Predicate proto for battery saver mode. +Predicate CreateBatterySaverModePredicate(); + // Create Predicate proto for holding wakelock. Predicate CreateHoldingWakelockPredicate(); @@ -86,6 +102,15 @@ FieldMatcher CreateAttributionUidDimensions(const int atomId, std::unique_ptr CreateScreenStateChangedEvent( const android::view::DisplayStateEnum state, uint64_t timestampNs); +// Create log event for screen brightness state changed. +std::unique_ptr CreateScreenBrightnessChangedEvent( + int level, uint64_t timestampNs); + +// Create log event when battery saver starts. +std::unique_ptr CreateBatterySaverOnEvent(uint64_t timestampNs); +// Create log event when battery saver stops. +std::unique_ptr CreateBatterySaverOffEvent(uint64_t timestampNs); + // Create log event for app moving to background. std::unique_ptr CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs); @@ -94,11 +119,11 @@ std::unique_ptr CreateMoveToForegroundEvent(const int uid, uint64_t ti // Create log event when the app sync starts. std::unique_ptr CreateSyncStartEvent( - const int uid, const string& name, uint64_t timestampNs); + const std::vector& attributions, const string& name, uint64_t timestampNs); // Create log event when the app sync ends. std::unique_ptr CreateSyncEndEvent( - const int uid, const string& name, uint64_t timestampNs); + const std::vector& attributions, const string& name, uint64_t timestampNs); // Create log event when the app sync ends. std::unique_ptr CreateAppCrashEvent( @@ -136,9 +161,12 @@ void ValidateAttributionUidAndTagDimension( template void sortMetricDataByDimensionsValue(const T& metricData, T* sortedMetricData) { - std::map dimensionIndexMap; + std::map dimensionIndexMap; for (int i = 0; i < metricData.data_size(); ++i) { - dimensionIndexMap.insert(std::make_pair(metricData.data(i).dimensions_in_what(), i)); + dimensionIndexMap.insert(std::make_pair( + MetricDimensionKey(HashableDimensionKey(metricData.data(i).dimensions_in_what()), + HashableDimensionKey(metricData.data(i).dimensions_in_condition())), + i)); } for (const auto& itr : dimensionIndexMap) { *sortedMetricData->add_data() = metricData.data(itr.second); diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk index 32a85b1360235d79fc37178f3bfd8a673a2507ac..a65095f4188d56ea00f2628d935dc2f8786c14ed 100644 --- a/cmds/statsd/tools/dogfood/Android.mk +++ b/cmds/statsd/tools/dogfood/Android.mk @@ -27,6 +27,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \ LOCAL_PROTOC_OPTIMIZE_TYPE := lite LOCAL_PRIVILEGED_MODULE := true LOCAL_DEX_PREOPT := false +LOCAL_CERTIFICATE := platform LOCAL_PROGUARD_ENABLED := disabled include $(BUILD_PACKAGE) diff --git a/cmds/statsd/tools/dogfood/AndroidManifest.xml b/cmds/statsd/tools/dogfood/AndroidManifest.xml index 7bfde4050197f4ae99fa936bcb6da240405aa59a..cd76c9d379b5766c314a245ac5f32b47041a4c06 100644 --- a/cmds/statsd/tools/dogfood/AndroidManifest.xml +++ b/cmds/statsd/tools/dogfood/AndroidManifest.xml @@ -18,6 +18,7 @@ --> diff --git a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config index c1c3914838558079f14c3c35018c56a13575889d..d05006124994831625369971ac34b4c18e304730 100644 Binary files a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config and b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config differ diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java index d39aa1d314e6b833efc395d1659a88e6f3a84680..57575ae145f61f33c1acfe221c9036f1fde572a0 100644 --- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java +++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java @@ -116,28 +116,32 @@ public class MainActivity extends Activity { findViewById(R.id.plug).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, 1); + StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, + StatsLog.PLUGGED_STATE_CHANGED__STATE__BATTERY_PLUGGED_AC); } }); findViewById(R.id.unplug).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, 0); + StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, + StatsLog.PLUGGED_STATE_CHANGED__STATE__BATTERY_PLUGGED_NONE); } }); findViewById(R.id.screen_on).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, 2); + StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, + StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_ON); } }); findViewById(R.id.screen_off).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, 1); + StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, + StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF); } }); @@ -255,7 +259,9 @@ public class MainActivity extends Activity { } int[] uids = new int[] {mUids[id]}; String[] tags = new String[] {"acquire"}; - StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, 0, name, 1); + StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, + StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name, + StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); StringBuilder sb = new StringBuilder(); sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0) .append(", ").append(name).append(", 1);"); @@ -269,7 +275,9 @@ public class MainActivity extends Activity { } int[] uids = new int[] {mUids[id]}; String[] tags = new String[] {"release"}; - StatsLog.write(10, uids, tags, 0, name, 0); + StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, + StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name, + StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); StringBuilder sb = new StringBuilder(); sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0) .append(", ").append(name).append(", 0);"); diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java index 34f6d7de0cc9924a3791808b13788f4e14136146..3893be49e739ce5b30b81224c1214126266e6658 100644 --- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java +++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java @@ -21,7 +21,6 @@ import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; public class UsbCommand extends Svc.Command { public UsbCommand() { @@ -37,41 +36,41 @@ public class UsbCommand extends Svc.Command { public String longHelp() { return shortHelp() + "\n" + "\n" - + "usage: svc usb setFunction [function] [usbDataUnlocked=false]\n" - + " Set the current usb function and optionally the data lock state.\n\n" + + "usage: svc usb setFunctions [function]\n" + + " Set the current usb function. If function is blank, sets to charging.\n" + " svc usb setScreenUnlockedFunctions [function]\n" - + " Sets the functions which, if the device was charging," - + " become current on screen unlock.\n" - + " svc usb getFunction\n" - + " Gets the list of currently enabled functions\n"; + + " Sets the functions which, if the device was charging, become current on" + + "screen unlock. If function is blank, turn off this feature.\n" + + " svc usb getFunctions\n" + + " Gets the list of currently enabled functions\n\n" + + "possible values of [function] are any of 'mtp', 'ptp', 'rndis', 'midi'\n"; } @Override public void run(String[] args) { - boolean validCommand = false; if (args.length >= 2) { - if ("setFunction".equals(args[1])) { - IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService( - Context.USB_SERVICE)); - boolean unlockData = false; - if (args.length >= 4) { - unlockData = Boolean.valueOf(args[3]); - } + IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService( + Context.USB_SERVICE)); + if ("setFunctions".equals(args[1])) { try { - usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), unlockData); + usbMgr.setCurrentFunctions(UsbManager.usbFunctionsFromString( + args.length >= 3 ? args[2] : "")); } catch (RemoteException e) { System.err.println("Error communicating with UsbManager: " + e); } return; - } else if ("getFunction".equals(args[1])) { - System.err.println(SystemProperties.get("sys.usb.config")); + } else if ("getFunctions".equals(args[1])) { + try { + System.err.println( + UsbManager.usbFunctionsToString(usbMgr.getCurrentFunctions())); + } catch (RemoteException e) { + System.err.println("Error communicating with UsbManager: " + e); + } return; } else if ("setScreenUnlockedFunctions".equals(args[1])) { - IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService( - Context.USB_SERVICE)); try { - usbMgr.setScreenUnlockedFunctions((args.length >= 3 ? args[2] : - UsbManager.USB_FUNCTION_NONE)); + usbMgr.setScreenUnlockedFunctions(UsbManager.usbFunctionsFromString( + args.length >= 3 ? args[2] : "")); } catch (RemoteException e) { System.err.println("Error communicating with UsbManager: " + e); } diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt new file mode 100644 index 0000000000000000000000000000000000000000..58936fcc4452d4633c3bdfa1f83591951248f6ae --- /dev/null +++ b/config/hiddenapi-light-greylist.txt @@ -0,0 +1,1164 @@ +Landroid/accounts/AccountManager;->mContext:Landroid/content/Context; +Landroid/animation/ValueAnimator;->animateValue(F)V +Landroid/animation/ValueAnimator;->getDurationScale()F +Landroid/animation/ValueAnimator;->sDurationScale:F +Landroid/app/Activity;->convertFromTranslucent()V +Landroid/app/Activity;->convertToTranslucent(Landroid/app/Activity$TranslucentConversionListener;Landroid/app/ActivityOptions;)Z +Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions; +Landroid/app/Activity;->getActivityToken()Landroid/os/IBinder; +Landroid/app/Activity;->mActivityInfo:Landroid/content/pm/ActivityInfo; +Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)Z +Landroid/app/ActivityManager;->forceStopPackage(Ljava/lang/String;)V +Landroid/app/ActivityManager;->getCurrentUser()I +Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z +Landroid/app/ActivityManager;->isUserRunning(I)Z +Landroid/app/ActivityManager;->mContext:Landroid/content/Context; +Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager; +Landroid/app/ActivityManager;->PROCESS_STATE_TOP:I +Landroid/app/ActivityManager$RecentTaskInfo;->firstActiveTime:J +Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I +Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I +Landroid/app/Activity;->mApplication:Landroid/app/Application; +Landroid/app/Activity;->mHandler:Landroid/os/Handler; +Landroid/app/Activity;->mResultCode:I +Landroid/app/Activity;->mResultData:Landroid/content/Intent; +Landroid/app/Activity;->mToken:Landroid/os/IBinder; +Landroid/app/Activity;->mWindow:Landroid/view/Window; +Landroid/app/Activity;->mWindowManager:Landroid/view/WindowManager; +Landroid/app/Activity;->setDisablePreviewScreenshots(Z)V +Landroid/app/ActivityThread$ActivityClientRecord;->activityInfo:Landroid/content/pm/ActivityInfo; +Landroid/app/ActivityThread$ActivityClientRecord;->token:Landroid/os/IBinder; +Landroid/app/ActivityThread$AppBindData;->info:Landroid/app/LoadedApk; +Landroid/app/ActivityThread$AppBindData;->instrumentationArgs:Landroid/os/Bundle; +Landroid/app/ActivityThread;->currentActivityThread()Landroid/app/ActivityThread; +Landroid/app/ActivityThread;->currentApplication()Landroid/app/Application; +Landroid/app/ActivityThread;->currentPackageName()Ljava/lang/String; +Landroid/app/ActivityThread;->currentProcessName()Ljava/lang/String; +Landroid/app/ActivityThread;->getApplication()Landroid/app/Application; +Landroid/app/ActivityThread;->getApplicationThread()Landroid/app/ActivityThread$ApplicationThread; +Landroid/app/ActivityThread;->getHandler()Landroid/os/Handler; +Landroid/app/ActivityThread;->getPackageManager()Landroid/content/pm/IPackageManager; +Landroid/app/ActivityThread;->getProcessName()Ljava/lang/String; +Landroid/app/ActivityThread$H;->BIND_SERVICE:I +Landroid/app/ActivityThread$H;->CREATE_SERVICE:I +Landroid/app/ActivityThread$H;->EXIT_APPLICATION:I +Landroid/app/ActivityThread$H;->RECEIVER:I +Landroid/app/ActivityThread$H;->RELAUNCH_ACTIVITY:I +Landroid/app/ActivityThread$H;->REMOVE_PROVIDER:I +Landroid/app/ActivityThread$H;->SERVICE_ARGS:I +Landroid/app/ActivityThread$H;->STOP_SERVICE:I +Landroid/app/ActivityThread$H;->UNBIND_SERVICE:I +Landroid/app/ActivityThread;->installContentProviders(Landroid/content/Context;Ljava/util/List;)V +Landroid/app/ActivityThread;->mActivities:Landroid/util/ArrayMap; +Landroid/app/ActivityThread;->mAllApplications:Ljava/util/ArrayList; +Landroid/app/ActivityThread;->mBoundApplication:Landroid/app/ActivityThread$AppBindData; +Landroid/app/ActivityThread;->mInitialApplication:Landroid/app/Application; +Landroid/app/ActivityThread;->mInstrumentation:Landroid/app/Instrumentation; +Landroid/app/ActivityThread;->mNumVisibleActivities:I +Landroid/app/ActivityThread;->mPackages:Landroid/util/ArrayMap; +Landroid/app/ActivityThread;->performStopActivity(Landroid/os/IBinder;ZLjava/lang/String;)V +Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager; +Landroid/app/admin/DevicePolicyManager;->getTrustAgentConfiguration(Landroid/content/ComponentName;Landroid/content/ComponentName;I)Ljava/util/List; +Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(J)V +Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(JZ)V +Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z +Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;)Z +Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V +Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;Z)V +Landroid/app/AlertDialog$Builder;->P:Lcom/android/internal/app/AlertController$AlertParams; +Landroid/app/AlertDialog;->mAlert:Lcom/android/internal/app/AlertController; +Landroid/app/AppGlobals;->getInitialApplication()Landroid/app/Application; +Landroid/app/AppGlobals;->getPackageManager()Landroid/content/pm/IPackageManager; +Landroid/app/Application;->attach(Landroid/content/Context;)V +Landroid/app/ApplicationLoaders;->getDefault()Landroid/app/ApplicationLoaders; +Landroid/app/ApplicationLoaders;->mLoaders:Landroid/util/ArrayMap; +Landroid/app/Application;->mComponentCallbacks:Ljava/util/ArrayList; +Landroid/app/Application;->mLoadedApk:Landroid/app/LoadedApk; +Landroid/app/ApplicationPackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V +Landroid/app/ApplicationPackageManager;->installExistingPackage(Ljava/lang/String;)I +Landroid/app/ApplicationPackageManager;->installExistingPackage(Ljava/lang/String;I)I +Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I +Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I +Landroid/app/AppOpsManager;->noteOp(I)I +Landroid/app/AppOpsManager;->noteOp(IILjava/lang/String;)I +Landroid/app/AppOpsManager;->OP_POST_NOTIFICATION:I +Landroid/app/AppOpsManager;->OP_WIFI_SCAN:I +Landroid/app/AppOpsManager;->OP_WRITE_SMS:I +Landroid/app/AppOpsManager;->setMode(IILjava/lang/String;I)V +Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I +Landroid/app/backup/BackupDataInputStream;->dataSize:I +Landroid/app/backup/BackupDataInputStream;->key:Ljava/lang/String; +Landroid/app/backup/FullBackup;->backupToTar(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I +Landroid/app/ContextImpl;->createActivityContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;ILandroid/content/res/Configuration;)Landroid/app/ContextImpl; +Landroid/app/ContextImpl;->getActivityToken()Landroid/os/IBinder; +Landroid/app/ContextImpl;->mMainThread:Landroid/app/ActivityThread; +Landroid/app/ContextImpl;->mPackageInfo:Landroid/app/LoadedApk; +Landroid/app/ContextImpl;->setOuterContext(Landroid/content/Context;)V +Landroid/app/DatePickerDialog;->mDatePicker:Landroid/widget/DatePicker; +Landroid/app/Dialog;->CANCEL:I +Landroid/app/Dialog;->mCancelMessage:Landroid/os/Message; +Landroid/app/Dialog;->mDismissMessage:Landroid/os/Message; +Landroid/app/Dialog;->mListenersHandler:Landroid/os/Handler; +Landroid/app/Dialog;->mOwnerActivity:Landroid/app/Activity; +Landroid/app/Dialog;->mShowMessage:Landroid/os/Message; +Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri; +Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl; +Landroid/app/IActivityManager;->forceStopPackage(Ljava/lang/String;I)V +Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String; +Landroid/app/IActivityManager;->resumeAppSwitches()V +Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V +Landroid/app/IntentService;->mServiceHandler:Landroid/app/IntentService$ServiceHandler; +Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor; +Landroid/app/LoadedApk;->mApplication:Landroid/app/Application; +Landroid/app/LoadedApk;->mReceivers:Landroid/util/ArrayMap; +Landroid/app/LoadedApk;->mResDir:Ljava/lang/String; +Landroid/app/LoadedApk;->mResources:Landroid/content/res/Resources; +Landroid/app/LocalActivityManager;->mActivities:Ljava/util/Map; +Landroid/app/LocalActivityManager;->mActivityArray:Ljava/util/ArrayList; +Landroid/app/Notification$Builder;->mActions:Ljava/util/ArrayList; +Landroid/app/Notification;->EXTRA_SUBSTITUTE_APP_NAME:Ljava/lang/String; +Landroid/app/Notification;->isGroupSummary()Z +Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager; +Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V +Landroid/app/Notification;->setLatestEventInfo(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/app/PendingIntent;)V +Landroid/app/PendingIntent;->getActivityAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/PendingIntent; +Landroid/app/PendingIntent;->getIntent()Landroid/content/Intent; +Landroid/app/PendingIntent;->isActivity()Z +Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context; +Landroid/app/ProgressDialog;->mProgressNumber:Landroid/widget/TextView; +Landroid/app/Service;->setForeground(Z)V +Landroid/app/StatusBarManager;->collapsePanels()V +Landroid/app/StatusBarManager;->disable(I)V +Landroid/app/StatusBarManager;->expandNotificationsPanel()V +Landroid/app/StatusBarManager;->expandSettingsPanel(Ljava/lang/String;)V +Landroid/app/StatusBarManager;->expandSettingsPanel()V +Landroid/app/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker; +Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap; +Landroid/app/WallpaperManager;->getBitmap(Z)Landroid/graphics/Bitmap; +Landroid/app/WallpaperManager;->getIWallpaperManager()Landroid/app/IWallpaperManager; +Landroid/app/WallpaperManager;->openDefaultWallpaper(Landroid/content/Context;I)Ljava/io/InputStream; +Landroid/app/WallpaperManager;->setBitmap(Landroid/graphics/Bitmap;Landroid/graphics/Rect;ZII)I +Landroid/app/WallpaperManager;->sGlobals:Landroid/app/WallpaperManager$Globals; +Landroid/appwidget/AppWidgetManager;->bindAppWidgetIdIfAllowed(IILandroid/content/ComponentName;Landroid/os/Bundle;)Z +Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V +Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V +Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z +Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z +Landroid/bluetooth/BluetoothAdapter;->enableNoAutoConnect()Z +Landroid/bluetooth/BluetoothAdapter;->getDiscoverableTimeout()I +Landroid/bluetooth/BluetoothAdapter;->setScanMode(II)Z +Landroid/bluetooth/BluetoothAdapter;->setScanMode(I)Z +Landroid/bluetooth/BluetoothDevice;->cancelBondProcess()Z +Landroid/bluetooth/BluetoothDevice;->createBond(I)Z +Landroid/bluetooth/BluetoothDevice;->getAliasName()Ljava/lang/String; +Landroid/bluetooth/BluetoothDevice;->isConnected()Z +Landroid/bluetooth/BluetoothDevice;->isEncrypted()Z +Landroid/bluetooth/BluetoothDevice;->removeBond()Z +Landroid/bluetooth/BluetoothDevice;->setPhonebookAccessPermission(I)Z +Landroid/bluetooth/BluetoothGattCharacteristic;->mInstance:I +Landroid/bluetooth/BluetoothGattCharacteristic;->mService:Landroid/bluetooth/BluetoothGattService; +Landroid/bluetooth/BluetoothGattDescriptor;->mCharacteristic:Landroid/bluetooth/BluetoothGattCharacteristic; +Landroid/bluetooth/BluetoothGattDescriptor;->mInstance:I +Landroid/bluetooth/BluetoothGatt;->refresh()Z +Landroid/bluetooth/BluetoothHeadset;->close()V +Landroid/bluetooth/BluetoothHeadset;->setPriority(Landroid/bluetooth/BluetoothDevice;I)Z +Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid; +Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth; +Landroid/content/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor; +Landroid/content/ContentProviderOperation;->mSelection:Ljava/lang/String; +Landroid/content/ContentProviderOperation;->mType:I +Landroid/content/ContentResolver;->getContentService()Landroid/content/IContentService; +Landroid/content/ContentResolver;->getSyncStatus(Landroid/accounts/Account;Ljava/lang/String;)Landroid/content/SyncStatusInfo; +Landroid/content/ContentResolver;->mContext:Landroid/content/Context; +Landroid/content/ContentValues;->mValues:Ljava/util/HashMap; +Landroid/content/Context;->createPackageContextAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/Context; +Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File; +Landroid/content/Context;->getThemeResId()I +Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;I)V +Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;Landroid/os/Bundle;)V +Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V +Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V +Landroid/content/ContextWrapper;->mBase:Landroid/content/Context; +Landroid/content/CursorLoader;->mCancellationSignal:Landroid/os/CancellationSignal; +Landroid/content/CursorLoader;->mObserver:Landroid/content/Loader$ForceLoadContentObserver; +Landroid/content/IContentService;->cancelSync(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)V +Landroid/content/IContentService;->getMasterSyncAutomatically()Z +Landroid/content/IContentService;->setMasterSyncAutomatically(Z)V +Landroid/content/Intent;->ACTION_ALARM_CHANGED:Ljava/lang/String; +Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent; +Landroid/content/pm/ApplicationInfo;->installLocation:I +Landroid/content/pm/ApplicationInfo;->isForwardLocked()Z +Landroid/content/pm/ApplicationInfo;->isInstantApp()Z +Landroid/content/pm/ApplicationInfo;->isPrivilegedApp()Z +Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String; +Landroid/content/pm/ApplicationInfo;->privateFlags:I +Landroid/content/pm/ApplicationInfo;->targetSandboxVersion:I +Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo; +Landroid/content/pm/IPackageManager;->setLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/IntentFilter;ILandroid/content/ComponentName;)V +Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager; +Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V +Landroid/content/pm/PackageInstaller$SessionParams;->setGrantedRuntimePermissions([Ljava/lang/String;)V +Landroid/content/pm/PackageInstaller$SessionParams;->setInstallAsInstantApp(Z)V +Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V +Landroid/content/pm/PackageManager;->freeStorageAndNotify(Ljava/lang/String;JLandroid/content/pm/IPackageDataObserver;)V +Landroid/content/pm/PackageManager;->freeStorage(JLandroid/content/IntentSender;)V +Landroid/content/pm/PackageManager;->freeStorage(Ljava/lang/String;JLandroid/content/IntentSender;)V +Landroid/content/pm/PackageManager;->getApplicationInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo; +Landroid/content/pm/PackageManager;->getPackageCandidateVolumes(Landroid/content/pm/ApplicationInfo;)Ljava/util/List; +Landroid/content/pm/PackageManager;->getPackageInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/PackageInfo; +Landroid/content/pm/PackageManager;->getPackageSizeInfo(Ljava/lang/String;Landroid/content/pm/IPackageStatsObserver;)V +Landroid/content/pm/PackageManager;->getResourcesForApplicationAsUser(Ljava/lang/String;I)Landroid/content/res/Resources; +Landroid/content/pm/PackageManager;->movePackage(Ljava/lang/String;Landroid/os/storage/VolumeInfo;)I +Landroid/content/pm/PackageManager;->queryBroadcastReceivers(Landroid/content/Intent;II)Ljava/util/List; +Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V +Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Z)V +Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;I)Landroid/content/pm/PackageInfo; +Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;)Landroid/content/pm/PackageInfo; +Landroid/content/pm/PackageParser;->parseMonolithicPackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package; +Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package; +Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package; +Landroid/content/pm/UserInfo;->id:I +Landroid/content/pm/UserInfo;->isPrimary()Z +Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I +Landroid/content/res/AssetManager;->addAssetPaths([Ljava/lang/String;)[I +Landroid/content/res/AssetManager;->applyStyle(JIIJ[IIJJ)V +Landroid/content/res/AssetManager;->getArraySize(I)I +Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray; +Landroid/content/res/AssetManager;->getCookieName(I)Ljava/lang/String; +Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence; +Landroid/content/res/AssetManager;->loadResourceBagValue(IILandroid/util/TypedValue;Z)I +Landroid/content/res/AssetManager;->loadResourceValue(ISLandroid/util/TypedValue;Z)I +Landroid/content/res/AssetManager;->loadThemeAttributeValue(JILandroid/util/TypedValue;Z)I +Landroid/content/res/AssetManager;->mObject:J +Landroid/content/res/AssetManager;->openNonAssetFdNative(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor; +Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;I)Ljava/io/InputStream; +Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;)Ljava/io/InputStream; +Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream; +Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream; +Landroid/content/res/AssetManager;->openNonAssetNative(ILjava/lang/String;I)J +Landroid/content/res/AssetManager;->openXmlAssetNative(ILjava/lang/String;)J +Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z +Landroid/content/res/AssetManager;->retrieveArray(I[I)I +Landroid/content/res/AssetManager;->retrieveAttributes(J[I[I[I)Z +Landroid/content/res/AssetManager;->STYLE_NUM_ENTRIES:I +Landroid/content/res/AssetManager;->STYLE_RESOURCE_ID:I +Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable; +Landroid/content/res/Resources;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo; +Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object; +Landroid/content/res/ResourcesImpl;->mAssets:Landroid/content/res/AssetManager; +Landroid/content/res/ResourcesImpl;->mColorDrawableCache:Landroid/content/res/DrawableCache; +Landroid/content/res/ResourcesImpl;->mConfiguration:Landroid/content/res/Configuration; +Landroid/content/res/ResourcesImpl;->mDrawableCache:Landroid/content/res/DrawableCache; +Landroid/content/res/ResourcesImpl;->mPreloading:Z +Landroid/content/res/ResourcesImpl;->sPreloadedColorDrawables:Landroid/util/LongSparseArray; +Landroid/content/res/ResourcesImpl;->sPreloadedDrawables:[Landroid/util/LongSparseArray; +Landroid/content/res/ResourcesImpl;->TRACE_FOR_MISS_PRELOAD:Z +Landroid/content/res/ResourcesImpl;->TRACE_FOR_PRELOAD:Z +Landroid/content/res/Resources;->loadXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser; +Landroid/content/res/Resources;->loadXmlResourceParser(Ljava/lang/String;IILjava/lang/String;)Landroid/content/res/XmlResourceParser; +Landroid/content/res/Resources;->mResourcesImpl:Landroid/content/res/ResourcesImpl; +Landroid/content/res/Resources;->mTmpValue:Landroid/util/TypedValue; +Landroid/content/res/Resources;->mTypedArrayPool:Landroid/util/Pools$SynchronizedPool; +Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V +Landroid/content/res/TypedArray;->getValueAt(ILandroid/util/TypedValue;)Z +Landroid/content/res/TypedArray;->mAssets:Landroid/content/res/AssetManager; +Landroid/content/res/TypedArray;->mData:[I +Landroid/content/res/TypedArray;->mIndices:[I +Landroid/content/res/TypedArray;->mLength:I +Landroid/content/res/TypedArray;->mMetrics:Landroid/util/DisplayMetrics; +Landroid/content/res/TypedArray;->mRecycled:Z +Landroid/content/res/TypedArray;->mResources:Landroid/content/res/Resources; +Landroid/content/res/TypedArray;->mTheme:Landroid/content/res/Resources$Theme; +Landroid/content/res/TypedArray;->mValue:Landroid/util/TypedValue; +Landroid/content/res/TypedArray;->mXml:Landroid/content/res/XmlBlock$Parser; +Landroid/content/res/XmlBlock;->close()V +Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser; +Landroid/content/res/XmlBlock$Parser;->mParseState:J +Landroid/content/SyncStatusInfo;->lastSuccessTime:J +Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri; +Landroid/database/CursorWindow;->mWindowPtr:J +Landroid/database/CursorWindow;->sCursorWindowSize:I +Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray; +Landroid/database/CursorWrapper;->mCursor:Landroid/database/Cursor; +Landroid/graphics/Bitmap$Config;->nativeInt:I +Landroid/graphics/Bitmap;->createAshmemBitmap()Landroid/graphics/Bitmap; +Landroid/graphics/Bitmap;->createAshmemBitmap(Landroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap; +Landroid/graphics/Bitmap;->getDefaultDensity()I +Landroid/graphics/drawable/AnimationDrawable;->mCurFrame:I +Landroid/graphics/drawable/BitmapDrawable;->getTint()Landroid/content/res/ColorStateList; +Landroid/graphics/drawable/BitmapDrawable;->getTintMode()Landroid/graphics/PorterDuff$Mode; +Landroid/graphics/drawable/BitmapDrawable;->setBitmap(Landroid/graphics/Bitmap;)V +Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mConstantPadding:Landroid/graphics/Rect; +Landroid/graphics/drawable/DrawableContainer;->getOpticalInsets()Landroid/graphics/Insets; +Landroid/graphics/drawable/DrawableContainer;->mDrawableContainerState:Landroid/graphics/drawable/DrawableContainer$DrawableContainerState; +Landroid/graphics/drawable/Drawable;->inflateWithAttributes(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/content/res/TypedArray;I)V +Landroid/graphics/drawable/Drawable;->mCallback:Ljava/lang/ref/WeakReference; +Landroid/graphics/drawable/NinePatchDrawable;->mNinePatchState:Landroid/graphics/drawable/NinePatchDrawable$NinePatchState; +Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;->mNinePatch:Landroid/graphics/NinePatch; +Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I +Landroid/graphics/drawable/StateListDrawable;->getStateCount()I +Landroid/graphics/drawable/StateListDrawable;->getStateDrawable(I)Landroid/graphics/drawable/Drawable; +Landroid/graphics/drawable/StateListDrawable;->getStateSet(I)[I +Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState; +Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V +Landroid/graphics/LinearGradient;->mColors:[I +Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap; +Landroid/graphics/SurfaceTexture;->nativeDetachFromGLContext()I +Landroid/graphics/Typeface;->mStyle:I +Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface; +Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V +Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map; +Landroid/hardware/Camera;->addCallbackBuffer([BI)V +Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera; +Landroid/hardware/display/WifiDisplayStatus;->mActiveDisplay:Landroid/hardware/display/WifiDisplay; +Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay; +Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager; +Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager; +Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager; +Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V +Landroid/location/LocationRequest;->createFromDeprecatedProvider(Ljava/lang/String;JFZ)Landroid/location/LocationRequest; +Landroid/location/LocationRequest;->setWorkSource(Landroid/os/WorkSource;)V +Landroid/location/Location;->setIsFromMockProvider(Z)V +Landroid/media/AudioAttributes$Builder;->setInternalCapturePreset(I)Landroid/media/AudioAttributes$Builder; +Landroid/media/AudioManager;->abandonAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;)I +Landroid/media/AudioManager;->mAudioFocusIdListenerMap:Ljava/util/concurrent/ConcurrentHashMap; +Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioFocusRequest;Landroid/media/audiopolicy/AudioPolicy;)I +Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;II)I +Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;IILandroid/media/audiopolicy/AudioPolicy;)I +Landroid/media/AudioManager;->setMasterMute(ZI)V +Landroid/media/AudioManager;->STREAM_BLUETOOTH_SCO:I +Landroid/media/AudioManager;->STREAM_SYSTEM_ENFORCED:I +Landroid/media/AudioManager;->STREAM_TTS:I +Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I +Landroid/media/AudioTrack;->getLatency()I +Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService; +Landroid/media/MediaCodec;->releaseOutputBuffer(IZZJ)V +Landroid/media/MediaFile;->getFileType(Ljava/lang/String;)Landroid/media/MediaFile$MediaFileType; +Landroid/media/MediaFile;->getMimeTypeForFile(Ljava/lang/String;)Ljava/lang/String; +Landroid/media/MediaFile;->isVideoFileType(I)Z +Landroid/media/MediaFile$MediaFileType;->fileType:I +Landroid/media/MediaFile;->sFileTypeMap:Ljava/util/HashMap; +Landroid/media/MediaMetadataRetriever;->getEmbeddedPicture(I)[B +Landroid/media/MediaPlayer;->getMetadata(ZZ)Landroid/media/Metadata; +Landroid/media/MediaPlayer;->invoke(Landroid/os/Parcel;Landroid/os/Parcel;)V +Landroid/media/MediaPlayer;->newRequest()Landroid/os/Parcel; +Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/util/List;)V +Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)V +Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;)V +Landroid/media/MediaPlayer;->setRetransmitEndpoint(Ljava/net/InetSocketAddress;)V +Landroid/media/MediaRecorder$AudioSource;->RADIO_TUNER:I +Landroid/media/MediaRouter$RouteInfo;->getStatusCode()I +Landroid/media/MediaRouter$RouteInfo;->STATUS_CONNECTING:I +Landroid/media/MediaRouter;->selectRouteInt(ILandroid/media/MediaRouter$RouteInfo;Z)V +Landroid/media/MediaScanner;->mClient:Landroid/media/MediaScanner$MyMediaScannerClient; +Landroid/media/MediaScanner;->scanSingleFile(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri; +Landroid/media/MiniThumbFile;->reset()V +Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone; +Landroid/media/Ringtone;->setLooping(Z)V +Landroid/media/Ringtone;->setVolume(F)V +Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler; +Landroid/media/ThumbnailUtils;->createImageThumbnail(Ljava/lang/String;I)Landroid/graphics/Bitmap; +Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String; +Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String; +Landroid/net/ConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties; +Landroid/net/ConnectivityManager;->getLinkProperties(I)Landroid/net/LinkProperties; +Landroid/net/ConnectivityManager;->getMobileDataEnabled()Z +Landroid/net/ConnectivityManager;->getTetherableUsbRegexs()[Ljava/lang/String; +Landroid/net/ConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String; +Landroid/net/ConnectivityManager;->getTetheredIfaces()[Ljava/lang/String; +Landroid/net/ConnectivityManager;->isNetworkSupported(I)Z +Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z +Landroid/net/ConnectivityManager;->isTetheringSupported()Z +Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager; +Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z +Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z +Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String; +Landroid/net/LinkProperties;->setHttpProxy(Landroid/net/ProxyInfo;)V +Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager; +Landroid/net/NetworkStats;->capacity:I +Landroid/net/NetworkStats;->defaultNetwork:[I +Landroid/net/NetworkStats;->iface:[Ljava/lang/String; +Landroid/net/NetworkStats;->metered:[I +Landroid/net/NetworkStats;->operations:[J +Landroid/net/NetworkStats;->roaming:[I +Landroid/net/NetworkStats;->rxBytes:[J +Landroid/net/NetworkStats;->rxPackets:[J +Landroid/net/NetworkStats;->set:[I +Landroid/net/NetworkStats;->size:I +Landroid/net/NetworkStats;->tag:[I +Landroid/net/NetworkStats;->txBytes:[J +Landroid/net/NetworkStats;->txPackets:[J +Landroid/net/NetworkStats;->uid:[I +Landroid/net/SSLCertificateSocketFactory;->getHttpSocketFactory(ILandroid/net/SSLSessionCache;)Lorg/apache/http/conn/ssl/SSLSocketFactory; +Landroid/net/TrafficStats;->getStatsService()Landroid/net/INetworkStatsService; +Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I +Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection; +Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V +Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V +Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V +Landroid/net/wifi/WifiConfiguration;->apBand:I +Landroid/net/wifi/WifiConfiguration;->apChannel:I +Landroid/net/wifi/WifiConfiguration;->hasNoInternetAccess()Z +Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration; +Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z +Landroid/net/wifi/WifiManager;->connect(ILandroid/net/wifi/WifiManager$ActionListener;)V +Landroid/net/wifi/WifiManager;->connect(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V +Landroid/net/wifi/WifiManager;->EXTRA_WIFI_AP_STATE:Ljava/lang/String; +Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionListener;)V +Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration; +Landroid/net/wifi/WifiManager;->getWifiApState()I +Landroid/net/wifi/WifiManager;->isDualBandSupported()Z +Landroid/net/wifi/WifiManager;->isWifiApEnabled()Z +Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager; +Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V +Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z +Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_CHANGED_ACTION:Ljava/lang/String; +Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLED:I +Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLING:I +Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLED:I +Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLING:I +Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_FAILED:I +Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter; +Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V +Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext; +Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper; +Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread; +Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask; +Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status; +Landroid/os/AsyncTask;->mTaskInvoked:Ljava/util/concurrent/atomic/AtomicBoolean; +Landroid/os/AsyncTask;->mWorker:Landroid/os/AsyncTask$WorkerRunnable; +Landroid/os/AsyncTask;->sDefaultExecutor:Ljava/util/concurrent/Executor; +Landroid/os/AsyncTask;->setDefaultExecutor(Ljava/util/concurrent/Executor;)V +Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I +Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J +Landroid/os/BatteryStats$Uid;->getFullWifiLockTime(JI)J +Landroid/os/BatteryStats$Uid;->getProcessStats()Landroid/util/ArrayMap; +Landroid/os/BatteryStats$Uid;->getSensorStats()Landroid/util/SparseArray; +Landroid/os/BatteryStats$Uid;->getUid()I +Landroid/os/BatteryStats$Uid;->getWifiMulticastTime(JI)J +Landroid/os/BatteryStats$Uid;->getWifiScanTime(JI)J +Landroid/os/BatteryStats$Uid$Proc;->getForegroundTime(I)J +Landroid/os/BatteryStats$Uid$Proc;->getSystemTime(I)J +Landroid/os/BatteryStats$Uid$Proc;->getUserTime(I)J +Landroid/os/BatteryStats$Uid$Sensor;->getHandle()I +Landroid/os/BatteryStats$Uid$Sensor;->getSensorTime()Landroid/os/BatteryStats$Timer; +Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String; +Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder; +Landroid/os/Bundle;->putIBinder(Ljava/lang/String;Landroid/os/IBinder;)V +Landroid/os/Debug;->countInstancesOfClass(Ljava/lang/Class;)J +Landroid/os/Debug;->dumpReferenceTables()V +Landroid/os/Debug$MemoryInfo;->getOtherLabel(I)Ljava/lang/String; +Landroid/os/Debug$MemoryInfo;->getOtherPrivateDirty(I)I +Landroid/os/Debug$MemoryInfo;->getOtherPss(I)I +Landroid/os/Debug$MemoryInfo;->getOtherSharedDirty(I)I +Landroid/os/Debug$MemoryInfo;->NUM_DVK_STATS:I +Landroid/os/Debug$MemoryInfo;->NUM_OTHER_STATS:I +Landroid/os/Environment;->buildExternalStorageAppDataDirs(Ljava/lang/String;)[Ljava/io/File; +Landroid/os/FileUtils;->checksumCrc32(Ljava/io/File;)J +Landroid/os/FileUtils;->copyFile(Ljava/io/File;Ljava/io/File;)Z +Landroid/os/FileUtils;->copyToFile(Ljava/io/InputStream;Ljava/io/File;)Z +Landroid/os/FileUtils;->deleteOlderFiles(Ljava/io/File;IJ)Z +Landroid/os/FileUtils;->readTextFile(Ljava/io/File;ILjava/lang/String;)Ljava/lang/String; +Landroid/os/FileUtils;->setPermissions(Ljava/io/FileDescriptor;III)I +Landroid/os/FileUtils;->setPermissions(Ljava/io/File;III)I +Landroid/os/FileUtils;->setPermissions(Ljava/lang/String;III)I +Landroid/os/FileUtils;->stringToFile(Ljava/io/File;Ljava/lang/String;)V +Landroid/os/FileUtils;->stringToFile(Ljava/lang/String;Ljava/lang/String;)V +Landroid/os/Handler;->getIMessenger()Landroid/os/IMessenger; +Landroid/os/Handler;->hasCallbacks(Ljava/lang/Runnable;)Z +Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback; +Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger; +Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager; +Landroid/os/IPowerManager;->userActivity(JII)V +Landroid/os/Looper;->mQueue:Landroid/os/MessageQueue; +Landroid/os/MemoryFile;->getFileDescriptor()Ljava/io/FileDescriptor; +Landroid/os/Message;->callback:Ljava/lang/Runnable; +Landroid/os/Message;->flags:I +Landroid/os/Message;->next:Landroid/os/Message; +Landroid/os/MessageQueue;->mIdleHandlers:Ljava/util/ArrayList; +Landroid/os/MessageQueue;->mMessages:Landroid/os/Message; +Landroid/os/MessageQueue;->mQuitAllowed:Z +Landroid/os/MessageQueue;->next()Landroid/os/Message; +Landroid/os/Message;->target:Landroid/os/Handler; +Landroid/os/PowerManager;->getMaximumScreenBrightnessSetting()I +Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I +Landroid/os/PowerManager;->isLightDeviceIdleMode()Z +Landroid/os/PowerManager;->userActivity(JII)V +Landroid/os/PowerManager;->userActivity(JZ)V +Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V +Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V +Landroid/os/PowerManager;->wakeUp(J)V +Landroid/os/Process;->getParentPid(I)I +Landroid/os/Process;->getPids(Ljava/lang/String;[I)[I +Landroid/os/Process;->getUidForPid(I)I +Landroid/os/Process;->isIsolated(I)Z +Landroid/os/Process;->isIsolated()Z +Landroid/os/Process;->readProcFile(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z +Landroid/os/Process;->readProcLines(Ljava/lang/String;[Ljava/lang/String;[J)V +Landroid/os/RecoverySystem;->cancelScheduledUpdate(Landroid/content/Context;)V +Landroid/os/RecoverySystem;->installPackage(Landroid/content/Context;Ljava/io/File;Z)V +Landroid/os/RecoverySystem;->processPackage(Landroid/content/Context;Ljava/io/File;Landroid/os/RecoverySystem$ProgressListener;Landroid/os/Handler;)V +Landroid/os/RecoverySystem;->processPackage(Landroid/content/Context;Ljava/io/File;Landroid/os/RecoverySystem$ProgressListener;)V +Landroid/os/RecoverySystem;->rebootWipeAb(Landroid/content/Context;Ljava/io/File;Ljava/lang/String;)V +Landroid/os/RecoverySystem;->scheduleUpdateOnBoot(Landroid/content/Context;Ljava/io/File;)V +Landroid/os/SELinux;->isSELinuxEnabled()Z +Landroid/os/SELinux;->isSELinuxEnforced()Z +Landroid/os/ServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder; +Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder; +Landroid/os/storage/DiskInfo;->getDescription()Ljava/lang/String; +Landroid/os/storage/StorageManager;->findVolumeByUuid(Ljava/lang/String;)Landroid/os/storage/VolumeInfo; +Landroid/os/storage/StorageManager;->getBestVolumeDescription(Landroid/os/storage/VolumeInfo;)Ljava/lang/String; +Landroid/os/storage/StorageManager;->getDisks()Ljava/util/List; +Landroid/os/storage/StorageManager;->getStorageBytesUntilLow(Ljava/io/File;)J +Landroid/os/storage/StorageManager;->getVolumeList(II)[Landroid/os/storage/StorageVolume; +Landroid/os/storage/StorageManager;->getVolumeList()[Landroid/os/storage/StorageVolume; +Landroid/os/storage/StorageManager;->getVolumePaths()[Ljava/lang/String; +Landroid/os/storage/StorageManager;->getVolumes()Ljava/util/List; +Landroid/os/storage/StorageManager;->getVolumeState(Ljava/lang/String;)Ljava/lang/String; +Landroid/os/storage/StorageVolume;->getPathFile()Ljava/io/File; +Landroid/os/storage/StorageVolume;->getPath()Ljava/lang/String; +Landroid/os/storage/StorageVolume;->getUserLabel()Ljava/lang/String; +Landroid/os/storage/VolumeInfo;->getDisk()Landroid/os/storage/DiskInfo; +Landroid/os/storage/VolumeInfo;->getFsUuid()Ljava/lang/String; +Landroid/os/storage/VolumeInfo;->getPath()Ljava/io/File; +Landroid/os/storage/VolumeInfo;->getState()I +Landroid/os/storage/VolumeInfo;->getType()I +Landroid/os/storage/VolumeInfo;->isPrimary()Z +Landroid/os/storage/VolumeInfo;->isVisible()Z +Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal; +Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V +Landroid/os/SystemProperties;->getBoolean(Ljava/lang/String;Z)Z +Landroid/os/SystemProperties;->getInt(Ljava/lang/String;I)I +Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String; +Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; +Landroid/os/SystemProperties;->getLong(Ljava/lang/String;J)J +Landroid/os/SystemProperties;->PROP_NAME_MAX:I +Landroid/os/SystemProperties;->set(Ljava/lang/String;Ljava/lang/String;)V +Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V +Landroid/os/Trace;->asyncTraceEnd(JLjava/lang/String;I)V +Landroid/os/Trace;->isTagEnabled(J)Z +Landroid/os/Trace;->setAppTracingAllowed(Z)V +Landroid/os/Trace;->traceBegin(JLjava/lang/String;)V +Landroid/os/Trace;->traceCounter(JLjava/lang/String;I)V +Landroid/os/Trace;->traceEnd(J)V +Landroid/os/Trace;->TRACE_TAG_APP:J +Landroid/os/Trace;->TRACE_TAG_VIEW:J +Landroid/os/UpdateEngine;->applyPayload(Ljava/lang/String;JJ[Ljava/lang/String;)V +Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;Landroid/os/Handler;)Z +Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;)Z +Landroid/os/UpdateEngine;->cancel()V +Landroid/os/UpdateEngine;->resetStatus()V +Landroid/os/UpdateLock;->acquire()V +Landroid/os/UpdateLock;->isHeld()Z +Landroid/os/UpdateLock;->release()V +Landroid/os/UserHandle;->ALL:Landroid/os/UserHandle; +Landroid/os/UserHandle;->getIdentifier()I +Landroid/os/UserHandle;->getUserId(I)I +Landroid/os/UserHandle;->isOwner()Z +Landroid/os/UserHandle;->myUserId()I +Landroid/os/UserHandle;->of(I)Landroid/os/UserHandle; +Landroid/os/UserManager;->get(Landroid/content/Context;)Landroid/os/UserManager; +Landroid/os/UserManager;->getMaxSupportedUsers()I +Landroid/os/UserManager;->getProfiles(I)Ljava/util/List; +Landroid/os/UserManager;->getUserHandle()I +Landroid/os/UserManager;->getUserHandle(I)I +Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo; +Landroid/os/UserManager;->getUserSerialNumber(I)I +Landroid/os/UserManager;->getUsers()Ljava/util/List; +Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z +Landroid/os/UserManager;->isLinkedUser()Z +Landroid/os/UserManager;->isUserUnlocked(I)Z +Landroid/os/WorkSource;->add(ILjava/lang/String;)Z +Landroid/os/WorkSource;->add(I)Z +Landroid/os/WorkSource;->get(I)I +Landroid/os/WorkSource;->getName(I)Ljava/lang/String; +Landroid/os/WorkSource;->size()I +Landroid/preference/DialogPreference;->mBuilder:Landroid/app/AlertDialog$Builder; +Landroid/preference/DialogPreference;->mDialogIcon:Landroid/graphics/drawable/Drawable; +Landroid/preference/DialogPreference;->mDialog:Landroid/app/Dialog; +Landroid/preference/DialogPreference;->mDialogMessage:Ljava/lang/CharSequence; +Landroid/preference/DialogPreference;->mDialogTitle:Ljava/lang/CharSequence; +Landroid/preference/DialogPreference;->mNegativeButtonText:Ljava/lang/CharSequence; +Landroid/preference/DialogPreference;->mPositiveButtonText:Ljava/lang/CharSequence; +Landroid/preference/DialogPreference;->mWhichButtonClicked:I +Landroid/preference/ListPreference;->mClickedDialogEntryIndex:I +Landroid/preference/PreferenceActivity;->mPreferenceManager:Landroid/preference/PreferenceManager; +Landroid/preference/PreferenceActivity;->mPrefsContainer:Landroid/view/ViewGroup; +Landroid/preference/PreferenceManager;->dispatchActivityDestroy()V +Landroid/preference/PreferenceManager;->dispatchActivityResult(IILandroid/content/Intent;)V +Landroid/preference/PreferenceManager;->dispatchActivityStop()V +Landroid/preference/PreferenceManager;->getEditor()Landroid/content/SharedPreferences$Editor; +Landroid/preference/PreferenceManager;->getPreferenceScreen()Landroid/preference/PreferenceScreen; +Landroid/preference/PreferenceManager;->inflateFromIntent(Landroid/content/Intent;Landroid/preference/PreferenceScreen;)Landroid/preference/PreferenceScreen; +Landroid/preference/PreferenceManager;->inflateFromResource(Landroid/content/Context;ILandroid/preference/PreferenceScreen;)Landroid/preference/PreferenceScreen; +Landroid/preference/PreferenceManager;->mActivityDestroyListeners:Ljava/util/List; +Landroid/preference/PreferenceManager;->mOnPreferenceTreeClickListener:Landroid/preference/PreferenceManager$OnPreferenceTreeClickListener; +Landroid/preference/PreferenceManager;->mSharedPreferences:Landroid/content/SharedPreferences; +Landroid/preference/PreferenceManager;->registerOnActivityDestroyListener(Landroid/preference/PreferenceManager$OnActivityDestroyListener;)V +Landroid/preference/PreferenceManager;->registerOnActivityStopListener(Landroid/preference/PreferenceManager$OnActivityStopListener;)V +Landroid/preference/PreferenceManager;->setFragment(Landroid/preference/PreferenceFragment;)V +Landroid/preference/PreferenceManager;->setPreferences(Landroid/preference/PreferenceScreen;)Z +Landroid/preference/PreferenceManager;->shouldCommit()Z +Landroid/preference/PreferenceManager;->unregisterOnActivityDestroyListener(Landroid/preference/PreferenceManager$OnActivityDestroyListener;)V +Landroid/preference/PreferenceManager;->unregisterOnActivityStopListener(Landroid/preference/PreferenceManager$OnActivityStopListener;)V +Landroid/preference/Preference;->onKey(Landroid/view/View;ILandroid/view/KeyEvent;)Z +Landroid/preference/Preference;->performClick(Landroid/preference/PreferenceScreen;)V +Landroid/preference/PreferenceScreen;->mRootAdapter:Landroid/widget/ListAdapter; +Landroid/print/PrinterId;->getServiceName()Landroid/content/ComponentName; +Landroid/print/PrintJobInfo;->getAdvancedOptions()Landroid/os/Bundle; +Landroid/print/PrintJobInfo;->getDocumentInfo()Landroid/print/PrintDocumentInfo; +Landroid/provider/Browser;->canClearHistory(Landroid/content/ContentResolver;)Z +Landroid/provider/Browser;->clearHistory(Landroid/content/ContentResolver;)V +Landroid/provider/Browser;->clearSearches(Landroid/content/ContentResolver;)V +Landroid/provider/Browser;->deleteFromHistory(Landroid/content/ContentResolver;Ljava/lang/String;)V +Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String; +Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V +Landroid/provider/Settings$Global;->OTA_DISABLE_AUTOMATIC_UPDATE:Ljava/lang/String; +Landroid/provider/Settings$Global;->PACKAGE_VERIFIER_ENABLE:Ljava/lang/String; +Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED:Ljava/lang/String; +Landroid/provider/Settings$Secure;->PACKAGE_VERIFIER_USER_CONSENT:Ljava/lang/String; +Landroid/provider/Settings$Secure;->USER_SETUP_COMPLETE:Ljava/lang/String; +Landroid/provider/Settings$System;->AIRPLANE_MODE_TOGGLEABLE_RADIOS:Ljava/lang/String; +Landroid/provider/Settings$System;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String; +Landroid/provider/Settings$System;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z +Landroid/provider/Telephony$Sms;->addMessageToUri(ILandroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZJ)Landroid/net/Uri; +Landroid/provider/Telephony$Sms;->addMessageToUri(ILandroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZ)Landroid/net/Uri; +Landroid/provider/Telephony$Sms;->addMessageToUri(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZJ)Landroid/net/Uri; +Landroid/provider/Telephony$Sms;->addMessageToUri(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZ)Landroid/net/Uri; +Landroid/provider/Telephony$Sms$Inbox;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Z)Landroid/net/Uri; +Landroid/provider/Telephony$Sms$Inbox;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Z)Landroid/net/Uri; +Landroid/provider/Telephony$Sms$Sent;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri; +Landroid/provider/Telephony$Sms$Sent;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri; +Landroid/renderscript/RenderScript;->create(Landroid/content/Context;I)Landroid/renderscript/RenderScript; +Landroid/renderscript/RenderScript;->create(Landroid/content/Context;ILandroid/renderscript/RenderScript$ContextType;I)Landroid/renderscript/RenderScript; +Landroid/renderscript/RenderScript;->getMinorID()J +Landroid/R$styleable;->TextAppearance:[I +Landroid/R$styleable;->TextAppearance_textColor:I +Landroid/R$styleable;->TextAppearance_textSize:I +Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore; +Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnectFailed()V +Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnect(Ljava/lang/String;Landroid/media/session/MediaSession$Token;Landroid/os/Bundle;)V +Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildren(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;)V +Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildrenWithOptions(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;Landroid/os/Bundle;)V +Landroid/service/media/MediaBrowserService;->KEY_MEDIA_ITEM:Ljava/lang/String; +Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V +Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V +Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V +Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String; +Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer; +Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState; +Landroid/telephony/SignalStrength;->getCdmaLevel()I +Landroid/telephony/SignalStrength;->getLteDbm()I +Landroid/telephony/SignalStrength;->getLteRsrp()I +Landroid/telephony/SignalStrength;->getLteRssnr()I +Landroid/telephony/SignalStrength;->getLteSignalStrength()I +Landroid/telephony/SmsManager;->RESULT_ERROR_FDN_CHECK_FAILURE:I +Landroid/telephony/SmsMessage;->getSubId()I +Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase; +Landroid/telephony/SubscriptionManager;->getDefaultSmsPhoneId()I +Landroid/telephony/SubscriptionManager;->getPhoneId(I)I +Landroid/telephony/SubscriptionManager;->getSubId(I)[I +Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V +Landroid/telephony/TelephonyManager;->checkCarrierPrivilegesForPackage(Ljava/lang/String;)I +Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager; +Landroid/telephony/TelephonyManager;->getCurrentPhoneType()I +Landroid/telephony/TelephonyManager;->getCurrentPhoneType(I)I +Landroid/telephony/TelephonyManager;->getDataEnabled(I)Z +Landroid/telephony/TelephonyManager;->getDataEnabled()Z +Landroid/telephony/TelephonyManager;->getDefault()Landroid/telephony/TelephonyManager; +Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony; +Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getNetworkClass(I)I +Landroid/telephony/TelephonyManager;->getNetworkCountryIso(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getNetworkOperator(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getNetworkOperatorName(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getNetworkType(I)I +Landroid/telephony/TelephonyManager;->getSimOperator(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getSimOperatorName(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getSimSerialNumber(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->getSubscriberId(I)Ljava/lang/String; +Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z +Landroid/telephony/TelephonyManager;->setDataEnabled(IZ)V +Landroid/text/AndroidBidi;->bidi(I[C[B)I +Landroid/text/DynamicLayout;->sStaticLayout:Landroid/text/StaticLayout; +Landroid/text/Html;->withinStyle(Ljava/lang/StringBuilder;Ljava/lang/CharSequence;II)V +Landroid/text/Layout;->DIRS_ALL_LEFT_TO_RIGHT:Landroid/text/Layout$Directions; +Landroid/text/method/LinkMovementMethod;->sInstance:Landroid/text/method/LinkMovementMethod; +Landroid/text/SpannableStringBuilder;->mGapLength:I +Landroid/text/SpannableStringBuilder;->mGapStart:I +Landroid/text/SpannableStringBuilder;->mSpanCount:I +Landroid/text/SpannableStringBuilder;->mSpanEnds:[I +Landroid/text/SpannableStringBuilder;->mSpanFlags:[I +Landroid/text/SpannableStringBuilder;->mSpans:[Ljava/lang/Object; +Landroid/text/SpannableStringBuilder;->mSpanStarts:[I +Landroid/text/StaticLayout;->mColumns:I +Landroid/text/StaticLayout;->mLineCount:I +Landroid/text/StaticLayout;->mLines:[I +Landroid/text/TextLine;->obtain()Landroid/text/TextLine; +Landroid/text/TextLine;->sCached:[Landroid/text/TextLine; +Landroid/text/TextPaint;->setUnderlineText(IF)V +Landroid/util/Log;->wtf(ILjava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;ZZ)I +Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object; +Landroid/view/accessibility/AccessibilityManager;->getInstance(Landroid/content/Context;)Landroid/view/accessibility/AccessibilityManager; +Landroid/view/accessibility/AccessibilityManager;->isHighTextContrastEnabled()Z +Landroid/view/accessibility/AccessibilityManager;->sInstance:Landroid/view/accessibility/AccessibilityManager; +Landroid/view/accessibility/AccessibilityManager;->sInstanceSync:Ljava/lang/Object; +Landroid/view/accessibility/AccessibilityNodeInfo;->refresh(Landroid/os/Bundle;Z)Z +Landroid/view/ActionMode;->isUiFocusable()Z +Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener; +Landroid/view/Choreographer;->doFrame(JI)V +Landroid/view/Choreographer;->getFrameTime()J +Landroid/view/Choreographer;->mCallbackQueues:[Landroid/view/Choreographer$CallbackQueue; +Landroid/view/Choreographer;->postCallback(ILjava/lang/Runnable;Ljava/lang/Object;)V +Landroid/view/Choreographer;->removeCallbacks(ILjava/lang/Runnable;Ljava/lang/Object;)V +Landroid/view/Choreographer;->scheduleVsyncLocked()V +Landroid/view/ContextThemeWrapper;->mResources:Landroid/content/res/Resources; +Landroid/view/ContextThemeWrapper;->mTheme:Landroid/content/res/Resources$Theme; +Landroid/view/ContextThemeWrapper;->mThemeResource:I +Landroid/view/InputDevice;->isExternal()Z +Landroid/view/inputmethod/InputMethodManager;->finishInputLocked()V +Landroid/view/inputmethod/InputMethodManager;->focusIn(Landroid/view/View;)V +Landroid/view/inputmethod/InputMethodManager;->getInputMethodWindowVisibleHeight()I +Landroid/view/inputmethod/InputMethodManager;->mCurId:Ljava/lang/String; +Landroid/view/inputmethod/InputMethodManager;->mCurRootView:Landroid/view/View; +Landroid/view/inputmethod/InputMethodManager;->mNextServedView:Landroid/view/View; +Landroid/view/inputmethod/InputMethodManager;->mServedView:Landroid/view/View; +Landroid/view/inputmethod/InputMethodManager;->notifyUserAction()V +Landroid/view/inputmethod/InputMethodManager;->showSoftInputUnchecked(ILandroid/os/ResultReceiver;)V +Landroid/view/inputmethod/InputMethodManager;->windowDismissed(Landroid/os/IBinder;)V +Landroid/view/IWindowManager;->getAnimationScale(I)F +Landroid/view/IWindowManager;->hasNavigationBar()Z +Landroid/view/IWindowManager;->setAnimationScale(IF)V +Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V +Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager; +Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I +Landroid/view/LayoutInflater;->mConstructorArgs:[Ljava/lang/Object; +Landroid/view/LayoutInflater;->mFactory2:Landroid/view/LayoutInflater$Factory2; +Landroid/view/LayoutInflater;->mFactory:Landroid/view/LayoutInflater$Factory; +Landroid/view/LayoutInflater;->mFactorySet:Z +Landroid/view/LayoutInflater;->sConstructorMap:Ljava/util/HashMap; +Landroid/view/MotionEvent;->HISTORY_CURRENT:I +Landroid/view/MotionEvent;->mNativePtr:J +Landroid/view/MotionEvent;->nativeGetRawAxisValue(JIII)F +Landroid/view/MotionEvent;->scale(F)V +Landroid/view/ScaleGestureDetector;->mListener:Landroid/view/ScaleGestureDetector$OnScaleGestureListener; +Landroid/view/SurfaceView;->mCallbacks:Ljava/util/ArrayList; +Landroid/view/SurfaceView;->mFormat:I +Landroid/view/SurfaceView;->mRequestedFormat:I +Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder; +Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->(Landroid/content/Context;I)V +Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V +Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; +Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(IIILandroid/view/textclassifier/TextClassification;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; +Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(II)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; +Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextClassification;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; +Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextSelection;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; +Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionStarted(I)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; +Landroid/view/textservice/TextServicesManager;->isSpellCheckerEnabled()Z +Landroid/view/TextureView;->mLayer:Landroid/view/HardwareLayer; +Landroid/view/TextureView;->mSurface:Landroid/graphics/SurfaceTexture; +Landroid/view/TextureView;->mUpdateListener:Landroid/graphics/SurfaceTexture$OnFrameAvailableListener; +Landroid/view/TouchDelegate;->mDelegateTargeted:Z +Landroid/view/VelocityTracker;->obtain(Ljava/lang/String;)Landroid/view/VelocityTracker; +Landroid/view/View;->clearAccessibilityFocus()V +Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z +Landroid/view/View;->computeOpaqueFlags()V +Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z +Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z +Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z +Landroid/view/View;->createSnapshot(Landroid/view/ViewDebug$CanvasProvider;Z)Landroid/graphics/Bitmap; +Landroid/view/ViewDebug;->dispatchCommand(Landroid/view/View;Ljava/lang/String;Ljava/lang/String;Ljava/io/OutputStream;)V +Landroid/view/ViewDebug;->dump(Landroid/view/View;ZZLjava/io/OutputStream;)V +Landroid/view/View;->dispatchAttachedToWindow(Landroid/view/View$AttachInfo;I)V +Landroid/view/View;->dispatchDetachedFromWindow()V +Landroid/view/View;->fitsSystemWindows()Z +Landroid/view/View;->getListenerInfo()Landroid/view/View$ListenerInfo; +Landroid/view/View;->getViewRootImpl()Landroid/view/ViewRootImpl; +Landroid/view/ViewGroup;->FLAG_SUPPORT_STATIC_TRANSFORMATIONS:I +Landroid/view/ViewGroup;->FLAG_USE_CHILD_DRAWING_ORDER:I +Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V +Landroid/view/ViewGroup$MarginLayoutParams;->endMargin:I +Landroid/view/ViewGroup$MarginLayoutParams;->startMargin:I +Landroid/view/ViewGroup;->mChildren:[Landroid/view/View; +Landroid/view/ViewGroup;->mFirstTouchTarget:Landroid/view/ViewGroup$TouchTarget; +Landroid/view/ViewGroup;->mGroupFlags:I +Landroid/view/ViewGroup;->mOnHierarchyChangeListener:Landroid/view/ViewGroup$OnHierarchyChangeListener; +Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V +Landroid/view/View;->isPaddingResolved()Z +Landroid/view/View;->isVisibleToUser(Landroid/graphics/Rect;)Z +Landroid/view/View;->isVisibleToUser()Z +Landroid/view/View$ListenerInfo;->mOnClickListener:Landroid/view/View$OnClickListener; +Landroid/view/View$ListenerInfo;->mOnTouchListener:Landroid/view/View$OnTouchListener; +Landroid/view/View;->mAccessibilityDelegate:Landroid/view/View$AccessibilityDelegate; +Landroid/view/View;->mAttachInfo:Landroid/view/View$AttachInfo; +Landroid/view/View;->mBottom:I +Landroid/view/View;->mContext:Landroid/content/Context; +Landroid/view/View;->mDrawingCache:Landroid/graphics/Bitmap; +Landroid/view/View;->mLeft:I +Landroid/view/View;->mListenerInfo:Landroid/view/View$ListenerInfo; +Landroid/view/View;->mMinHeight:I +Landroid/view/View;->mMinWidth:I +Landroid/view/View;->mPaddingLeft:I +Landroid/view/View;->mPaddingRight:I +Landroid/view/View;->mParent:Landroid/view/ViewParent; +Landroid/view/View;->mPrivateFlags3:I +Landroid/view/View;->mRecreateDisplayList:Z +Landroid/view/View;->mResources:Landroid/content/res/Resources; +Landroid/view/View;->mRight:I +Landroid/view/View;->mScrollCache:Landroid/view/View$ScrollabilityCache; +Landroid/view/View;->mScrollX:I +Landroid/view/View;->mScrollY:I +Landroid/view/View;->mStartActivityRequestWho:Ljava/lang/String; +Landroid/view/View;->mTop:I +Landroid/view/View;->mUnscaledDrawingCache:Landroid/graphics/Bitmap; +Landroid/view/View;->notifySubtreeAccessibilityStateChangedIfNeeded()V +Landroid/view/View;->recomputePadding()V +Landroid/view/View;->requestAccessibilityFocus()Z +Landroid/view/View;->resetPaddingToInitialValues()V +Landroid/view/ViewRootImpl;->detachFunctor(J)V +Landroid/view/ViewRootImpl;->invokeFunctor(JZ)V +Landroid/view/ViewRootImpl;->mStopped:Z +Landroid/view/View;->setAssistBlocked(Z)V +Landroid/view/View;->setFrame(IIII)Z +Landroid/view/View;->setIsRootNamespace(Z)V +Landroid/view/View;->startActivityForResult(Landroid/content/Intent;I)V +Landroid/view/View;->STATUS_BAR_DISABLE_BACK:I +Landroid/view/View;->STATUS_BAR_DISABLE_EXPAND:I +Landroid/view/View;->STATUS_BAR_DISABLE_HOME:I +Landroid/view/View;->STATUS_BAR_DISABLE_RECENT:I +Landroid/view/View;->toGlobalMotionEvent(Landroid/view/MotionEvent;)Z +Landroid/view/View;->toLocalMotionEvent(Landroid/view/MotionEvent;)Z +Landroid/view/ViewTreeObserver;->addOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V +Landroid/view/ViewTreeObserver$InternalInsetsInfo;->setTouchableInsets(I)V +Landroid/view/ViewTreeObserver$InternalInsetsInfo;->TOUCHABLE_INSETS_REGION:I +Landroid/view/ViewTreeObserver$InternalInsetsInfo;->touchableRegion:Landroid/graphics/Region; +Landroid/view/ViewTreeObserver;->removeOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V +Landroid/view/WindowManagerGlobal;->getInstance()Landroid/view/WindowManagerGlobal; +Landroid/view/WindowManagerGlobal;->getRootView(Ljava/lang/String;)Landroid/view/View; +Landroid/view/WindowManagerGlobal;->getViewRootNames()[Ljava/lang/String; +Landroid/view/WindowManagerGlobal;->getWindowManagerService()Landroid/view/IWindowManager; +Landroid/view/WindowManagerGlobal;->mLock:Ljava/lang/Object; +Landroid/view/WindowManagerGlobal;->mViews:Ljava/util/ArrayList; +Landroid/view/WindowManagerGlobal;->trimMemory(I)V +Landroid/view/WindowManager$LayoutParams;->needsMenuKey:I +Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_TRUE:I +Landroid/view/WindowManager$LayoutParams;->privateFlags:I +Landroid/view/WindowManager$LayoutParams;->userActivityTimeout:J +Landroid/view/Window;->mAppName:Ljava/lang/String; +Landroid/view/Window;->mAppToken:Landroid/os/IBinder; +Landroid/view/Window;->mHardwareAccelerated:Z +Landroid/webkit/WebSettings;->setNavDump(Z)V +Landroid/webkit/WebSettings;->setPluginsEnabled(Z)V +Landroid/webkit/WebView;->debugDump()V +Landroid/webkit/WebView;->disablePlatformNotifications()V +Landroid/webkit/WebView;->emulateShiftHeld()V +Landroid/webkit/WebView;->enablePlatformNotifications()V +Landroid/webkit/WebViewFactory;->getLoadedPackageInfo()Landroid/content/pm/PackageInfo; +Landroid/webkit/WebViewFactory;->getProvider()Landroid/webkit/WebViewFactoryProvider; +Landroid/webkit/WebViewFactory;->sPackageInfo:Landroid/content/pm/PackageInfo; +Landroid/webkit/WebView;->getVisibleTitleHeight()I +Landroid/webkit/WebView;->getWebViewProvider()Landroid/webkit/WebViewProvider; +Landroid/webkit/WebView;->isPaused()Z +Landroid/webkit/WebView;->mProvider:Landroid/webkit/WebViewProvider; +Landroid/webkit/WebView;->notifyFindDialogDismissed()V +Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z +Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z +Landroid/webkit/WebView;->sEnforceThreadChecking:Z +Landroid/widget/AbsListView$FlingRunnable;->endFling()V +Landroid/widget/AbsListView;->invokeOnItemScrollListener()V +Landroid/widget/AbsListView;->isVerticalScrollBarHidden()Z +Landroid/widget/AbsListView;->mAdapter:Landroid/widget/ListAdapter; +Landroid/widget/AbsListView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect; +Landroid/widget/AbsListView;->mEdgeGlowTop:Landroid/widget/EdgeEffect; +Landroid/widget/AbsListView;->mFastScroll:Landroid/widget/FastScroller; +Landroid/widget/AbsListView;->mFlingRunnable:Landroid/widget/AbsListView$FlingRunnable; +Landroid/widget/AbsListView;->mIsChildViewEnabled:Z +Landroid/widget/AbsListView;->mMaximumVelocity:I +Landroid/widget/AbsListView;->mMotionPosition:I +Landroid/widget/AbsListView;->mOnScrollListener:Landroid/widget/AbsListView$OnScrollListener; +Landroid/widget/AbsListView;->mRecycler:Landroid/widget/AbsListView$RecycleBin; +Landroid/widget/AbsListView;->mSelectionTopPadding:I +Landroid/widget/AbsListView;->mSelectorPosition:I +Landroid/widget/AbsListView;->mSelectorRect:Landroid/graphics/Rect; +Landroid/widget/AbsListView;->mTouchMode:I +Landroid/widget/AbsListView;->mTouchSlop:I +Landroid/widget/AbsListView;->mVelocityTracker:Landroid/view/VelocityTracker; +Landroid/widget/AbsListView;->performLongPress(Landroid/view/View;IJFF)Z +Landroid/widget/AbsListView;->performLongPress(Landroid/view/View;IJ)Z +Landroid/widget/AbsListView;->smoothScrollBy(IIZZ)V +Landroid/widget/AbsListView;->trackMotionScroll(II)Z +Landroid/widget/AbsSeekBar;->mIsDragging:Z +Landroid/widget/AbsSeekBar;->mSplitTrack:Z +Landroid/widget/AbsSeekBar;->mThumb:Landroid/graphics/drawable/Drawable; +Landroid/widget/AbsSeekBar;->mTouchProgressOffset:F +Landroid/widget/ActivityChooserView;->setExpandActivityOverflowButtonDrawable(Landroid/graphics/drawable/Drawable;)V +Landroid/widget/AdapterView;->mDataChanged:Z +Landroid/widget/AdapterView;->setNextSelectedPositionInt(I)V +Landroid/widget/AdapterView;->setSelectedPositionInt(I)V +Landroid/widget/AutoCompleteTextView;->doAfterTextChanged()V +Landroid/widget/AutoCompleteTextView;->doBeforeTextChanged()V +Landroid/widget/AutoCompleteTextView;->ensureImeVisible(Z)V +Landroid/widget/AutoCompleteTextView;->mPopup:Landroid/widget/ListPopupWindow; +Landroid/widget/AutoCompleteTextView;->setDropDownAlwaysVisible(Z)V +Landroid/widget/CompoundButton;->mButtonDrawable:Landroid/graphics/drawable/Drawable; +Landroid/widget/DatePicker;->mDelegate:Landroid/widget/DatePicker$DatePickerDelegate; +Landroid/widget/EdgeEffect;->mPaint:Landroid/graphics/Paint; +Landroid/widget/Editor;->mShowCursor:J +Landroid/widget/ExpandableListView;->mChildDivider:Landroid/graphics/drawable/Drawable; +Landroid/widget/FastScroller;->mThumbDrawable:Landroid/graphics/drawable/Drawable; +Landroid/widget/FastScroller;->mTrackDrawable:Landroid/graphics/drawable/Drawable; +Landroid/widget/Gallery;->mDownTouchView:Landroid/view/View; +Landroid/widget/GridView;->mColumnWidth:I +Landroid/widget/GridView;->mHorizontalSpacing:I +Landroid/widget/GridView;->mNumColumns:I +Landroid/widget/GridView;->mRequestedNumColumns:I +Landroid/widget/GridView;->mVerticalSpacing:I +Landroid/widget/HorizontalScrollView;->mEdgeGlowLeft:Landroid/widget/EdgeEffect; +Landroid/widget/HorizontalScrollView;->mEdgeGlowRight:Landroid/widget/EdgeEffect; +Landroid/widget/HorizontalScrollView;->mScroller:Landroid/widget/OverScroller; +Landroid/widget/ImageView;->mAdjustViewBounds:Z +Landroid/widget/ImageView;->mAlpha:I +Landroid/widget/ImageView;->mMaxHeight:I +Landroid/widget/ImageView;->mMaxWidth:I +Landroid/widget/LinearLayout;->mGravity:I +Landroid/widget/LinearLayout;->mUseLargestChild:Z +Landroid/widget/ListPopupWindow;->mPopup:Landroid/widget/PopupWindow; +Landroid/widget/ListPopupWindow;->setForceIgnoreOutsideTouch(Z)V +Landroid/widget/ListView;->mAreAllItemsSelectable:Z +Landroid/widget/ListView;->setSelectionInt(I)V +Landroid/widget/MediaController;->mAnchor:Landroid/view/View; +Landroid/widget/MediaController;->mDecor:Landroid/view/View; +Landroid/widget/MediaController;->mDecorLayoutParams:Landroid/view/WindowManager$LayoutParams; +Landroid/widget/MediaController;->mWindowManager:Landroid/view/WindowManager; +Landroid/widget/NumberPicker;->mInputText:Landroid/widget/EditText; +Landroid/widget/NumberPicker;->mSelectionDivider:Landroid/graphics/drawable/Drawable; +Landroid/widget/NumberPicker;->mSelectorWheelPaint:Landroid/graphics/Paint; +Landroid/widget/PopupMenu;->mPopup:Lcom/android/internal/view/menu/MenuPopupHelper; +Landroid/widget/PopupWindow;->computeAnimationResource()I +Landroid/widget/PopupWindow;->createPopupLayoutParams(Landroid/os/IBinder;)Landroid/view/WindowManager$LayoutParams; +Landroid/widget/PopupWindow;->invokePopup(Landroid/view/WindowManager$LayoutParams;)V +Landroid/widget/PopupWindow;->mAboveAnchor:Z +Landroid/widget/PopupWindow;->mAnchor:Ljava/lang/ref/WeakReference; +Landroid/widget/PopupWindow;->mAnimationStyle:I +Landroid/widget/PopupWindow;->mBackgroundView:Landroid/view/View; +Landroid/widget/PopupWindow;->mContentView:Landroid/view/View; +Landroid/widget/PopupWindow;->mHeightMode:I +Landroid/widget/PopupWindow;->mIsDropdown:Z +Landroid/widget/PopupWindow;->mIsShowing:Z +Landroid/widget/PopupWindow;->mLastHeight:I +Landroid/widget/PopupWindow;->mLastWidth:I +Landroid/widget/PopupWindow;->mOnScrollChangedListener:Landroid/view/ViewTreeObserver$OnScrollChangedListener; +Landroid/widget/PopupWindow;->mWidthMode:I +Landroid/widget/PopupWindow;->preparePopup(Landroid/view/WindowManager$LayoutParams;)V +Landroid/widget/PopupWindow;->setLayoutInScreenEnabled(Z)V +Landroid/widget/PopupWindow;->setLayoutInsetDecor(Z)V +Landroid/widget/PopupWindow;->setTouchModal(Z)V +Landroid/widget/ProgressBar;->mCurrentDrawable:Landroid/graphics/drawable/Drawable; +Landroid/widget/ProgressBar;->mDuration:I +Landroid/widget/ProgressBar;->mIndeterminate:Z +Landroid/widget/ProgressBar;->mMaxHeight:I +Landroid/widget/ProgressBar;->mMinHeight:I +Landroid/widget/ProgressBar;->mOnlyIndeterminate:Z +Landroid/widget/RelativeLayout$LayoutParams;->mBottom:I +Landroid/widget/RelativeLayout$LayoutParams;->mLeft:I +Landroid/widget/RelativeLayout$LayoutParams;->mRight:I +Landroid/widget/RelativeLayout$LayoutParams;->mTop:I +Landroid/widget/RelativeLayout;->mGravity:I +Landroid/widget/RemoteViews$Action;->mergeBehavior()I +Landroid/widget/RemoteViews$Action;->viewId:I +Landroid/widget/RemoteViews;->mActions:Ljava/util/ArrayList; +Landroid/widget/RemoteViews;->mApplication:Landroid/content/pm/ApplicationInfo; +Landroid/widget/RemoteViews$ReflectionAction;->methodName:Ljava/lang/String; +Landroid/widget/ScrollView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect; +Landroid/widget/ScrollView;->mEdgeGlowTop:Landroid/widget/EdgeEffect; +Landroid/widget/ScrollView;->mIsBeingDragged:Z +Landroid/widget/ScrollView;->mOverflingDistance:I +Landroid/widget/ScrollView;->mOverscrollDistance:I +Landroid/widget/ScrollView;->mScroller:Landroid/widget/OverScroller; +Landroid/widget/SearchView;->mCloseButton:Landroid/widget/ImageView; +Landroid/widget/SearchView;->mSearchButton:Landroid/widget/ImageView; +Landroid/widget/SearchView;->mSearchPlate:Landroid/view/View; +Landroid/widget/SearchView;->onCloseClicked()V +Landroid/widget/SearchView;->setQuery(Ljava/lang/CharSequence;)V +Landroid/widget/SlidingDrawer;->mTopOffset:I +Landroid/widget/Spinner;->mPopup:Landroid/widget/Spinner$SpinnerPopup; +Landroid/widget/Switch;->mThumbDrawable:Landroid/graphics/drawable/Drawable; +Landroid/widget/Switch;->mTrackDrawable:Landroid/graphics/drawable/Drawable; +Landroid/widget/TabWidget;->setTabSelectionListener(Landroid/widget/TabWidget$OnTabSelectionChanged;)V +Landroid/widget/TextView;->assumeLayout()V +Landroid/widget/TextView;->createEditorIfNeeded()V +Landroid/widget/TextView;->mCursorDrawableRes:I +Landroid/widget/TextView;->mCurTextColor:I +Landroid/widget/TextView;->mEditor:Landroid/widget/Editor; +Landroid/widget/TextView;->mListeners:Ljava/util/ArrayList; +Landroid/widget/TextView;->mMarquee:Landroid/widget/TextView$Marquee; +Landroid/widget/TextView;->mMaximum:I +Landroid/widget/TextView;->mMaxMode:I +Landroid/widget/TextView;->mSingleLine:Z +Landroid/widget/VideoView;->mCurrentBufferPercentage:I +Landroid/widget/VideoView;->mMediaController:Landroid/widget/MediaController; +Landroid/widget/VideoView;->mSHCallback:Landroid/view/SurfaceHolder$Callback; +Landroid/widget/VideoView;->mUri:Landroid/net/Uri; +Landroid/widget/VideoView;->mVideoHeight:I +Landroid/widget/VideoView;->mVideoWidth:I +Lcom/android/internal/app/IBatteryStats;->getStatistics()[B +Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats; +Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryRealtime(JI)J +Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryUptime(JI)J +Lcom/android/internal/os/BatteryStatsImpl;->CREATOR:Landroid/os/Parcelable$Creator; +Lcom/android/internal/os/BatteryStatsImpl;->getGlobalWifiRunningTime(JI)J +Lcom/android/internal/os/BatteryStatsImpl;->getScreenOnTime(JI)J +Lcom/android/internal/os/BatteryStatsImpl;->getUidStats()Landroid/util/SparseArray; +Lcom/android/internal/os/BatteryStatsImpl$Timer;->getCountLocked(I)I +Lcom/android/internal/os/BatteryStatsImpl$Timer;->getTotalTimeLocked(JI)J +Lcom/android/internal/os/BatteryStatsImpl$Uid;->getProcessStats()Landroid/util/ArrayMap; +Lcom/android/internal/os/BatteryStatsImpl$Uid;->getSensorStats()Landroid/util/SparseArray; +Lcom/android/internal/os/BatteryStatsImpl$Uid;->getUid()I +Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWakelockStats()Landroid/util/ArrayMap; +Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWifiRunningTime(JI)J +Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWifiScanTime(JI)J +Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getForegroundTime(I)J +Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getStarts(I)I +Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getSystemTime(I)J +Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getUserTime(I)J +Lcom/android/internal/os/BatteryStatsImpl$Uid$Sensor;->getHandle()I +Lcom/android/internal/os/BatteryStatsImpl$Uid$Sensor;->getSensorTime()Lcom/android/internal/os/BatteryStatsImpl$Timer; +Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;->getWakeTime(I)Lcom/android/internal/os/BatteryStatsImpl$Timer; +Lcom/android/internal/os/FuseAppLoop;->onCommand(IJJJI[B)V +Lcom/android/internal/os/FuseAppLoop;->onOpen(JJ)[B +Lcom/android/internal/os/PowerProfile;->getAveragePower(Ljava/lang/String;)D +Lcom/android/internal/os/PowerProfile;->getAveragePower(Ljava/lang/String;I)D +Lcom/android/internal/os/PowerProfile;->getBatteryCapacity()D +Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I +Lcom/android/internal/R$array;->config_tether_wifi_regexs:I +Lcom/android/internal/R$attr;->switchStyle:I +Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I +Lcom/android/internal/R$bool;->config_showNavigationBar:I +Lcom/android/internal/R$dimen;->navigation_bar_height:I +Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I +Lcom/android/internal/R$dimen;->status_bar_height:I +Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I +Lcom/android/internal/R$id;->amPm:I +Lcom/android/internal/R$id;->edittext_container:I +Lcom/android/internal/R$id;->icon:I +Lcom/android/internal/R$id;->message:I +Lcom/android/internal/R$id;->minute:I +Lcom/android/internal/R$id;->shortcut:I +Lcom/android/internal/R$id;->text:I +Lcom/android/internal/R$id;->time:I +Lcom/android/internal/R$id;->timePicker:I +Lcom/android/internal/R$id;->title_container:I +Lcom/android/internal/R$id;->title:I +Lcom/android/internal/R$integer;->config_screenBrightnessDim:I +Lcom/android/internal/R$layout;->screen_title:I +Lcom/android/internal/R$styleable;->CompoundButton_button:I +Lcom/android/internal/R$styleable;->CompoundButton:[I +Lcom/android/internal/R$styleable;->IconMenuView:[I +Lcom/android/internal/R$styleable;->ImageView:[I +Lcom/android/internal/R$styleable;->ImageView_src:I +Lcom/android/internal/R$styleable;->ScrollView:[I +Lcom/android/internal/R$styleable;->TabWidget:[I +Lcom/android/internal/R$styleable;->TextView_drawableBottom:I +Lcom/android/internal/R$styleable;->TextView_drawableLeft:I +Lcom/android/internal/R$styleable;->TextView_drawableRight:I +Lcom/android/internal/R$styleable;->TextView_drawableTop:I +Lcom/android/internal/R$styleable;->TextView:[I +Lcom/android/internal/R$styleable;->View_background:I +Lcom/android/internal/R$styleable;->View:[I +Lcom/android/internal/R$styleable;->View_id:I +Lcom/android/internal/R$styleable;->ViewStub:[I +Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I +Lcom/android/internal/R$styleable;->ViewStub_layout:I +Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I +Lcom/android/internal/R$xml;->power_profile:I +Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneSubInfo; +Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms; +Lcom/android/internal/telephony/ITelephony;->call(Ljava/lang/String;Ljava/lang/String;)V +Lcom/android/internal/telephony/ITelephony;->endCall()Z +Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z +Lcom/android/internal/telephony/ITelephony;->silenceRinger()V +Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony; +Lcom/android/internal/util/XmlUtils;->readMapXml(Ljava/io/InputStream;)Ljava/util/HashMap; +Lcom/android/internal/view/InputBindResult;->CREATOR:Landroid/os/Parcelable$Creator; +Lcom/android/internal/view/menu/MenuBuilder;->mContext:Landroid/content/Context; +Lcom/android/internal/view/menu/MenuBuilder;->setCurrentMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V +Lcom/android/internal/view/menu/MenuBuilder;->setOptionalIconsVisible(Z)V +Lcom/android/internal/view/menu/MenuItemImpl;->mIconResId:I +Lcom/android/internal/view/menu/MenuItemImpl;->setMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V +Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I +Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool; +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B +Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V +Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String; +Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList; +Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; +Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V +Ldalvik/system/CloseGuard;->warnIfOpen()V +Ldalvik/system/DexFile;->mCookie:Ljava/lang/Object; +Ldalvik/system/DexFile;->mFileName:Ljava/lang/String; +Ldalvik/system/DexFile;->openDexFile(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object; +Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element; +Ldalvik/system/DexPathList$Element;->dexFile:Ldalvik/system/DexFile; +Ldalvik/system/DexPathList;->makeDexElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;Ljava/lang/ClassLoader;)[Ldalvik/system/DexPathList$Element; +Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;)[Ldalvik/system/DexPathList$NativeLibraryElement; +Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;)[Ldalvik/system/DexPathList$Element; +Ldalvik/system/DexPathList;->nativeLibraryDirectories:Ljava/util/List; +Ldalvik/system/DexPathList;->nativeLibraryPathElements:[Ldalvik/system/DexPathList$NativeLibraryElement; +Ldalvik/system/DexPathList;->systemNativeLibraryDirectories:Ljava/util/List; +Ldalvik/system/VMDebug;->dumpReferenceTables()V +Ldalvik/system/VMRuntime;->clearGrowthLimit()V +Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String; +Ldalvik/system/VMRuntime;->getRuntime()Ldalvik/system/VMRuntime; +Ldalvik/system/VMRuntime;->is64Bit()Z +Ldalvik/system/VMRuntime;->newNonMovableArray(Ljava/lang/Class;I)Ljava/lang/Object; +Ldalvik/system/VMRuntime;->registerNativeAllocation(I)V +Ldalvik/system/VMRuntime;->registerNativeFree(I)V +Ldalvik/system/VMRuntime;->setMinimumHeapSize(J)J +Ldalvik/system/VMRuntime;->setTargetHeapUtilization(F)F +Ldalvik/system/VMRuntime;->trackExternalAllocation(J)Z +Ldalvik/system/VMRuntime;->trackExternalFree(J)V +Ldalvik/system/VMStack;->getCallingClassLoader()Ljava/lang/ClassLoader; +Ldalvik/system/VMStack;->getStackClass2()Ljava/lang/Class; +Ljava/io/FileDescriptor;->descriptor:I +Ljava/io/FileDescriptor;->getInt$()I +Ljava/io/FileDescriptor;->setInt$(I)V +Ljava/io/ObjectStreamClass;->getConstructorId(Ljava/lang/Class;)J +Ljava/io/ObjectStreamClass;->newInstance(Ljava/lang/Class;J)Ljava/lang/Object; +Ljava/io/ObjectStreamClass;->newInstance()Ljava/lang/Object; +Ljava/lang/Class;->dexCache:Ljava/lang/Object; +Ljava/lang/Class;->dexClassDefIndex:I +Ljava/lang/ClassLoader;->parent:Ljava/lang/ClassLoader; +Ljava/lang/Daemons$Daemon;->stop()V +Ljava/lang/Daemons$Daemon;->thread:Ljava/lang/Thread; +Ljava/lang/Daemons$FinalizerDaemon;->finalizingObject:Ljava/lang/Object; +Ljava/lang/Daemons$FinalizerDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerDaemon; +Ljava/lang/Daemons$FinalizerWatchdogDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon; +Ljava/lang/Runtime;->loadLibrary(Ljava/lang/String;Ljava/lang/ClassLoader;)V +Ljava/lang/Runtime;->load(Ljava/lang/String;Ljava/lang/ClassLoader;)V +Ljava/lang/Runtime;->nativeLoad(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String; +Ljava/lang/ThreadGroup;->parent:Ljava/lang/ThreadGroup; +Ljava/lang/ThreadGroup;->systemThreadGroup:Ljava/lang/ThreadGroup; +Ljava/lang/Thread;->inheritableThreadLocals:Ljava/lang/ThreadLocal$ThreadLocalMap; +Ljava/lang/Throwable;->detailMessage:Ljava/lang/String; +Ljava/net/Authenticator;->theAuthenticator:Ljava/net/Authenticator; +Ljava/net/DatagramSocket;->impl:Ljava/net/DatagramSocketImpl; +Ljava/net/InetAddress;->clearDnsCache()V +Ljava/net/InetAddress;->isNumeric(Ljava/lang/String;)Z +Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress; +Ljava/net/Socket;->impl:Ljava/net/SocketImpl; +Ljava/net/URI;->host:Ljava/lang/String; +Ljava/nio/charset/CharsetEncoder;->canEncode(Ljava/nio/CharBuffer;)Z +Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String; +Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V +Ljava/util/ArrayList$SubList;->parent:Ljava/util/AbstractList; +Ljava/util/ArrayList$SubList;->parentOffset:I +Ljava/util/ArrayList$SubList;->size:I +Ljava/util/Arrays$ArrayList;->a:[Ljava/lang/Object; +Ljava/util/Calendar;->zone:Ljava/util/TimeZone; +Ljava/util/concurrent/FutureTask;->callable:Ljava/util/concurrent/Callable; +Ljava/util/Locale;->createConstant(Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale; +Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ssl/SSLServerSocketFactory; +Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory; +Lorg/apache/http/conn/ssl/SSLSocketFactory;->(Ljavax/net/ssl/SSLSocketFactory;)V +Lorg/json/JSONArray;->values:Ljava/util/List; +Lsun/misc/Unsafe;->theUnsafe:Lsun/misc/Unsafe; diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 06a9b0676d0828ae26430d44015914dbe69cf5d5..0b10a35b5d5ead0709c4ac0c5ec8d71084bab9d8 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -16,6 +16,7 @@ package android.accessibilityservice; +import android.annotation.IntDef; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; @@ -43,6 +44,8 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -346,6 +349,19 @@ public class AccessibilityServiceInfo implements Parcelable { */ public String[] packageNames; + + /** @hide */ + @IntDef(flag = true, prefix = { "FEEDBACK_" }, value = { + FEEDBACK_AUDIBLE, + FEEDBACK_GENERIC, + FEEDBACK_HAPTIC, + FEEDBACK_SPOKEN, + FEEDBACK_VISUAL, + FEEDBACK_BRAILLE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FeedbackType {} + /** * The feedback type an {@link AccessibilityService} provides. *

@@ -358,6 +374,7 @@ public class AccessibilityServiceInfo implements Parcelable { * @see #FEEDBACK_VISUAL * @see #FEEDBACK_BRAILLE */ + @FeedbackType public int feedbackType; /** @@ -818,7 +835,8 @@ public class AccessibilityServiceInfo implements Parcelable { return stringBuilder.toString(); } - private static void appendFeedbackTypes(StringBuilder stringBuilder, int feedbackTypes) { + private static void appendFeedbackTypes(StringBuilder stringBuilder, + @FeedbackType int feedbackTypes) { stringBuilder.append("feedbackTypes:"); stringBuilder.append("["); while (feedbackTypes != 0) { diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 782733f552a6f480bd90c8688fade513e558d6e0..5176d71ea67b7d78f5fadeadfa5ce7993f935040 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -680,7 +680,7 @@ public class AccountManager { */ @NonNull public Account[] getAccountsByType(String type) { - return getAccountsByTypeAsUser(type, Process.myUserHandle()); + return getAccountsByTypeAsUser(type, mContext.getUser()); } /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */ @@ -2006,7 +2006,7 @@ public class AccountManager { final AccountManagerCallback callback, final Handler handler) { return confirmCredentialsAsUser(account, options, activity, callback, handler, - Process.myUserHandle()); + mContext.getUser()); } /** @@ -3208,7 +3208,7 @@ public class AccountManager { return finishSessionAsUser( sessionBundle, activity, - Process.myUserHandle(), + mContext.getUser(), callback, handler); } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e7d0c8be47619d4fc2bc33e97b06aeb9f2990366..0bc510a13ba6dca05bd7eb8ebac3a9b2928d3f81 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -113,6 +113,7 @@ import android.view.Window.WindowControllerCallback; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; +import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillManager.AutofillClient; import android.view.autofill.AutofillPopupWindow; @@ -125,7 +126,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.ToolbarActionBar; import com.android.internal.app.WindowDecorActionBar; -import com.android.internal.policy.DecorView; import com.android.internal.policy.PhoneWindow; import dalvik.system.VMRuntime; @@ -425,6 +425,12 @@ import java.util.List; * safely called after {@link #onPause()} and allows and application to safely * wait until {@link #onStop()} to save persistent state.

* + *

For applications targeting platforms starting with + * {@link android.os.Build.VERSION_CODES#P} {@link #onSaveInstanceState(Bundle)} + * will always be called after {@link #onStop}, so an application may safely + * perform fragment transactions in {@link #onStop} and will be able to save + * persistent state later.

+ * *

For those methods that are not marked as being killable, the activity's * process will not be killed by the system starting from the time the method * is called and continuing after it returns. Thus an activity is in the killable @@ -1577,8 +1583,11 @@ public class Activity extends ContextThemeWrapper * call through to the default implementation, otherwise be prepared to save * all of the state of each view yourself. * - *

If called, this method will occur before {@link #onStop}. There are - * no guarantees about whether it will occur before or after {@link #onPause}. + *

If called, this method will occur after {@link #onStop} for applications + * targeting platforms starting with {@link android.os.Build.VERSION_CODES#P}. + * For applications targeting earlier platform versions this method will occur + * before {@link #onStop} and there are no guarantees about whether it will + * occur before or after {@link #onPause}. * * @param outState Bundle in which to place your saved state. * @@ -5823,7 +5832,7 @@ public class Activity extends ContextThemeWrapper ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, mParent == null ? mToken : mParent.mToken, mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null, - UserHandle.myUserId()); + getUserId()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { // Empty @@ -5952,12 +5961,16 @@ public class Activity extends ContextThemeWrapper * * @return Returns the complete component name for this activity */ - @Override - public ComponentName getComponentName() - { + public ComponentName getComponentName() { return mComponent; } + /** @hide */ + @Override + public final ComponentName autofillClientGetComponentName() { + return getComponentName(); + } + /** * Retrieve a {@link SharedPreferences} object for accessing preferences * that are private to this activity. This simply calls the underlying @@ -6253,7 +6266,6 @@ public class Activity extends ContextThemeWrapper * * @param action the action to run on the UI thread */ - @Override public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); @@ -6262,6 +6274,12 @@ public class Activity extends ContextThemeWrapper } } + /** @hide */ + @Override + public final void autofillClientRunOnUiThread(Runnable action) { + runOnUiThread(action); + } + /** * Standard implementation of * {@link android.view.LayoutInflater.Factory#onCreateView} used when @@ -6338,7 +6356,7 @@ public class Activity extends ContextThemeWrapper mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix); - final AutofillManager afm = mAutofillManager; + final AutofillManager afm = getAutofillManager(); if (afm != null) { afm.dump(prefix, writer); } else { @@ -7067,6 +7085,18 @@ public class Activity extends ContextThemeWrapper mCurrentConfig = config; mWindow.setColorMode(info.colorMode); + + setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled()); + enableAutofillCompatibilityIfNeeded(); + } + + private void enableAutofillCompatibilityIfNeeded() { + if (isAutofillCompatibilityEnabled()) { + final AutofillManager afm = getSystemService(AutofillManager.class); + if (afm != null) { + afm.enableCompatibilityMode(); + } + } } /** @hide */ @@ -7143,7 +7173,10 @@ public class Activity extends ContextThemeWrapper boolean isApiWarningEnabled = SystemProperties.getInt("ro.art.hiddenapi.warning", 0) == 1; if (isAppDebuggable || isApiWarningEnabled) { - if (VMRuntime.getRuntime().hasUsedHiddenApi()) { + if (!mMainThread.mHiddenApiWarningShown && VMRuntime.getRuntime().hasUsedHiddenApi()) { + // Only show the warning once per process. + mMainThread.mHiddenApiWarningShown = true; + String appName = getApplicationInfo().loadLabel(getPackageManager()) .toString(); String warning = "Detected problems with API compatiblity\n" @@ -7560,7 +7593,7 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - final public void autofillCallbackAuthenticate(int authenticationId, IntentSender intent, + public final void autofillClientAuthenticate(int authenticationId, IntentSender intent, Intent fillInIntent) { try { startIntentSenderForResultInner(intent, AUTO_FILL_AUTH_WHO_PREFIX, @@ -7572,13 +7605,13 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - final public void autofillCallbackResetableStateAvailable() { + public final void autofillClientResetableStateAvailable() { mAutoFillResetNeeded = true; } /** @hide */ @Override - final public boolean autofillCallbackRequestShowFillUi(@NonNull View anchor, int width, + public final boolean autofillClientRequestShowFillUi(@NonNull View anchor, int width, int height, @Nullable Rect anchorBounds, IAutofillWindowPresenter presenter) { final boolean wasShowing; @@ -7595,7 +7628,7 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - final public boolean autofillCallbackRequestHideFillUi() { + public final boolean autofillClientRequestHideFillUi() { if (mAutofillPopupWindow == null) { return false; } @@ -7606,8 +7639,16 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - @NonNull public View[] findViewsByAutofillIdTraversal(@NonNull int[] viewIds) { - final View[] views = new View[viewIds.length]; + public final boolean autofillClientIsFillUiShowing() { + return mAutofillPopupWindow != null && mAutofillPopupWindow.isShowing(); + } + + /** @hide */ + @Override + @NonNull + public final View[] autofillClientFindViewsByAutofillIdTraversal( + @NonNull AutofillId[] autofillId) { + final View[] views = new View[autofillId.length]; final ArrayList roots = WindowManagerGlobal.getInstance().getRootViews(getActivityToken()); @@ -7615,10 +7656,11 @@ public class Activity extends ContextThemeWrapper final View rootView = roots.get(rootNum).getView(); if (rootView != null) { - for (int viewNum = 0; viewNum < viewIds.length; viewNum++) { + final int viewCount = autofillId.length; + for (int viewNum = 0; viewNum < viewCount; viewNum++) { if (views[viewNum] == null) { views[viewNum] = rootView.findViewByAutofillIdTraversal( - viewIds[viewNum]); + autofillId[viewNum].getViewId()); } } } @@ -7629,14 +7671,15 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - @Nullable public View findViewByAutofillIdTraversal(int viewId) { + @Nullable + public final View autofillClientFindViewByAutofillIdTraversal(AutofillId autofillId) { final ArrayList roots = WindowManagerGlobal.getInstance().getRootViews(getActivityToken()); for (int rootNum = 0; rootNum < roots.size(); rootNum++) { final View rootView = roots.get(rootNum).getView(); if (rootView != null) { - final View view = rootView.findViewByAutofillIdTraversal(viewId); + final View view = rootView.findViewByAutofillIdTraversal(autofillId.getViewId()); if (view != null) { return view; } @@ -7648,50 +7691,62 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override - @NonNull public boolean[] getViewVisibility(@NonNull int[] viewIds) { - final boolean[] isVisible = new boolean[viewIds.length]; - final View views[] = findViewsByAutofillIdTraversal(viewIds); - - for (int i = 0; i < viewIds.length; i++) { - View view = views[i]; - if (view == null) { - isVisible[i] = false; - continue; - } - - isVisible[i] = true; - - // Check if the view is visible by checking all parents - while (true) { - if (view instanceof DecorView && view.getViewRootImpl() == view.getParent()) { - break; - } - - if (view.getVisibility() != View.VISIBLE) { - isVisible[i] = false; - break; + public final @NonNull boolean[] autofillClientGetViewVisibility( + @NonNull AutofillId[] autofillIds) { + final int autofillIdCount = autofillIds.length; + final boolean[] visible = new boolean[autofillIdCount]; + for (int i = 0; i < autofillIdCount; i++) { + final AutofillId autofillId = autofillIds[i]; + final View view = autofillClientFindViewByAutofillIdTraversal(autofillId); + if (view != null) { + if (!autofillId.isVirtual()) { + visible[i] = view.isVisibleToUser(); + } else { + visible[i] = view.isVisibleToUserForAutofill(autofillId.getVirtualChildId()); } + } + } + return visible; + } - if (view.getParent() instanceof View) { - view = (View) view.getParent(); - } else { - break; + /** @hide */ + public final @Nullable View autofillClientFindViewByAccessibilityIdTraversal(int viewId, + int windowId) { + final ArrayList roots = WindowManagerGlobal.getInstance() + .getRootViews(getActivityToken()); + for (int rootNum = 0; rootNum < roots.size(); rootNum++) { + final View rootView = roots.get(rootNum).getView(); + if (rootView != null && rootView.getAccessibilityWindowId() == windowId) { + final View view = rootView.findViewByAccessibilityIdTraversal(viewId); + if (view != null) { + return view; } } } + return null; + } - return isVisible; + /** @hide */ + @Override + public final @Nullable IBinder autofillClientGetActivityToken() { + return getActivityToken(); } /** @hide */ @Override - public boolean isVisibleForAutofill() { + public final boolean autofillClientIsVisibleForAutofill() { return !mStopped; } /** @hide */ @Override - public boolean isDisablingEnterExitEventForAutofill() { + public final boolean autofillIsCompatibilityModeEnabled() { + return isAutofillCompatibilityEnabled(); + } + + /** @hide */ + @Override + public final boolean isDisablingEnterExitEventForAutofill() { return mAutoFillIgnoreFirstResumePause || !mResumed; } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index e2ce8b177d2ee08e8e2d89f12dda1d5eac0486f7..ae47a684f6ab86c1018b58f54f64bf645bb4daf1 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1691,7 +1691,7 @@ public class ActivityManager { if (maxNum < 0) { throw new IllegalArgumentException("The requested number of tasks should be >= 0"); } - return getService().getRecentTasks(maxNum, flags, UserHandle.myUserId()).getList(); + return getService().getRecentTasks(maxNum, flags, mContext.getUserId()).getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2685,7 +2685,7 @@ public class ActivityManager { public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) { try { return getService().clearApplicationUserData(packageName, false, - observer, UserHandle.myUserId()); + observer, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2724,7 +2724,7 @@ public class ActivityManager { try { @SuppressWarnings("unchecked") final ParceledListSlice castedList = getService() - .getGrantedUriPermissions(packageName, UserHandle.myUserId()); + .getGrantedUriPermissions(packageName, mContext.getUserId()); return castedList; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2743,7 +2743,7 @@ public class ActivityManager { public void clearGrantedUriPermissions(String packageName) { try { getService().clearGrantedUriPermissions(packageName, - UserHandle.myUserId()); + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3528,7 +3528,7 @@ public class ActivityManager { public void killBackgroundProcesses(String packageName) { try { getService().killBackgroundProcesses(packageName, - UserHandle.myUserId()); + mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3586,7 +3586,7 @@ public class ActivityManager { @SystemApi @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES) public void forceStopPackage(String packageName) { - forceStopPackageAsUser(packageName, UserHandle.myUserId()); + forceStopPackageAsUser(packageName, mContext.getUserId()); } /** diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 6c3dbf4979c45998e0b6c831ebb62259d570a732..3d088ff9e5c39ddc95edbea49aadb1e7e4005e53 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -291,6 +291,7 @@ public final class ActivityThread extends ClientTransactionHandler { boolean mJitEnabled = false; boolean mSomeActivitiesChanged = false; boolean mUpdatingSystemConfig = false; + /* package */ boolean mHiddenApiWarningShown = false; // These can be accessed by multiple threads; mResourcesManager is the lock. // XXX For now we keep around information about all packages we have @@ -487,12 +488,14 @@ public final class ActivityThread extends ClientTransactionHandler { } } - public boolean isPreHoneycomb() { - if (activity != null) { - return activity.getApplicationInfo().targetSdkVersion - < android.os.Build.VERSION_CODES.HONEYCOMB; - } - return false; + private boolean isPreHoneycomb() { + return activity != null && activity.getApplicationInfo().targetSdkVersion + < android.os.Build.VERSION_CODES.HONEYCOMB; + } + + private boolean isPreP() { + return activity != null && activity.getApplicationInfo().targetSdkVersion + < android.os.Build.VERSION_CODES.P; } public boolean isPersistable() { @@ -634,6 +637,8 @@ public final class ActivityThread extends ClientTransactionHandler { /** Initial values for {@link Profiler}. */ ProfilerInfo initProfilerInfo; + boolean autofillCompatibilityEnabled; + public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; } @@ -860,7 +865,7 @@ public final class ActivityThread extends ClientTransactionHandler { boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings, - String buildSerial) { + String buildSerial, boolean autofillCompatibilityEnabled) { if (services != null) { // Setup the service cache in the ServiceManager @@ -886,6 +891,7 @@ public final class ActivityThread extends ClientTransactionHandler { data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; data.buildSerial = buildSerial; + data.autofillCompatibilityEnabled = autofillCompatibilityEnabled; sendMessage(H.BIND_APPLICATION, data); } @@ -3969,8 +3975,7 @@ public final class ActivityThread extends ClientTransactionHandler { } r.activity.mConfigChangeFlags |= configChanges; - performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity", - pendingActions); + performPauseActivity(r, finished, "handlePauseActivity", pendingActions); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { @@ -3993,16 +3998,18 @@ public final class ActivityThread extends ClientTransactionHandler { mInstrumentation.callActivityOnUserLeaving(r.activity); } - final Bundle performPauseActivity(IBinder token, boolean finished, - boolean saveState, String reason, PendingTransactionActions pendingActions) { + final Bundle performPauseActivity(IBinder token, boolean finished, String reason, + PendingTransactionActions pendingActions) { ActivityClientRecord r = mActivities.get(token); - return r != null - ? performPauseActivity(r, finished, saveState, reason, pendingActions) - : null; + return r != null ? performPauseActivity(r, finished, reason, pendingActions) : null; } - private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState, - String reason, PendingTransactionActions pendingActions) { + /** + * Pause the activity. + * @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise. + */ + private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason, + PendingTransactionActions pendingActions) { if (r.paused) { if (r.activity.mFinished) { // If we are finishing, we won't call onResume() in certain cases. @@ -4019,9 +4026,10 @@ public final class ActivityThread extends ClientTransactionHandler { r.activity.mFinished = true; } - // Next have the activity save its current state and managed dialogs... - if (!r.activity.mFinished && saveState) { - callCallActivityOnSaveInstanceState(r); + // Pre-Honeycomb apps always save their state before pausing + final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb(); + if (shouldSaveState) { + callActivityOnSaveInstanceState(r); } performPauseActivityIfNeeded(r, reason); @@ -4048,7 +4056,7 @@ public final class ActivityThread extends ClientTransactionHandler { } } - return !r.activity.mFinished && saveState ? r.state : null; + return shouldSaveState ? r.state : null; } private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) { @@ -4149,30 +4157,47 @@ public final class ActivityThread extends ClientTransactionHandler { } } - // Next have the activity save its current state and managed dialogs... - if (!r.activity.mFinished && saveState) { - if (r.state == null) { - callCallActivityOnSaveInstanceState(r); - } + if (!keepShown) { + callActivityOnStop(r, saveState, reason); } + } + } - if (!keepShown) { - try { - // Now we are idle. - r.activity.performStop(false /*preserveWindow*/); - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to stop activity " + /** + * Calls {@link Activity#onStop()} and {@link Activity#onSaveInstanceState(Bundle)}, and updates + * the client record's state. + * All calls to stop an activity must be done through this method to make sure that + * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call. + */ + private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) { + // Before P onSaveInstanceState was called before onStop, starting with P it's + // called after. Before Honeycomb state was always saved before onPause. + final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null + && !r.isPreHoneycomb(); + final boolean isPreP = r.isPreP(); + if (shouldSaveState && isPreP) { + callActivityOnSaveInstanceState(r); + } + + try { + r.activity.performStop(false /*preserveWindow*/); + } catch (SuperNotCalledException e) { + throw e; + } catch (Exception e) { + if (!mInstrumentation.onException(r.activity, e)) { + throw new RuntimeException( + "Unable to stop activity " + r.intent.getComponent().toShortString() + ": " + e.toString(), e); - } - } - r.setState(ON_STOP); - EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName(), reason); } } + r.setState(ON_STOP); + EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), + r.activity.getComponentName().getClassName(), reason); + + if (shouldSaveState && !isPreP) { + callActivityOnSaveInstanceState(r); + } } private void updateVisibility(ActivityClientRecord r, boolean show) { @@ -4292,24 +4317,7 @@ public final class ActivityThread extends ClientTransactionHandler { if (sleeping) { if (!r.stopped && !r.isPreHoneycomb()) { - if (!r.activity.mFinished && r.state == null) { - callCallActivityOnSaveInstanceState(r); - } - - try { - // Now we are idle. - r.activity.performStop(false /*preserveWindow*/); - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to stop activity " - + r.intent.getComponent().toShortString() - + ": " + e.toString(), e); - } - } - r.setState(ON_STOP); - EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName(), "sleeping"); + callActivityOnStop(r, true /* saveState */, "sleeping"); } // Make sure any pending writes are now committed. @@ -4459,21 +4467,7 @@ public final class ActivityThread extends ClientTransactionHandler { performPauseActivityIfNeeded(r, "destroy"); if (!r.stopped) { - try { - r.activity.performStop(r.mPreserveWindow); - } catch (SuperNotCalledException e) { - throw e; - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to stop activity " - + safeToComponentShortString(r.intent) - + ": " + e.toString(), e); - } - } - r.setState(ON_STOP); - EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName(), "destroy"); + callActivityOnStop(r, false /* saveState */, "destroy"); } if (getNonConfigInstance) { try { @@ -4779,11 +4773,11 @@ public final class ActivityThread extends ClientTransactionHandler { // Need to ensure state is saved. if (!r.paused) { - performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity", + performPauseActivity(r, false, "handleRelaunchActivity", null /* pendingActions */); } - if (r.state == null && !r.stopped && !r.isPreHoneycomb()) { - callCallActivityOnSaveInstanceState(r); + if (!r.stopped) { + callActivityOnStop(r, true /* saveState */, "handleRelaunchActivity"); } handleDestroyActivity(r.token, false, configChanges, true); @@ -4816,8 +4810,7 @@ public final class ActivityThread extends ClientTransactionHandler { handleStartActivity(r, pendingActions); handleResumeActivity(r.token, false /* clearHide */, r.isForward, "relaunch"); if (r.startsNotResumed) { - performPauseActivity(r, false /* finished */, r.isPreHoneycomb(), "relaunch", - pendingActions); + performPauseActivity(r, false /* finished */, "relaunch", pendingActions); } if (!tmp.onlyLocalRequest) { @@ -4832,7 +4825,7 @@ public final class ActivityThread extends ClientTransactionHandler { } } - private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) { + private void callActivityOnSaveInstanceState(ActivityClientRecord r) { r.state = new Bundle(); r.state.setAllowFds(false); if (r.isPersistable()) { @@ -5850,6 +5843,10 @@ public final class ActivityThread extends ClientTransactionHandler { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. app = data.info.makeApplication(data.restrictedBackupMode, null); + + // Propagate autofill compat state + app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled); + mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index 382719b4a305364273048ba0b5d42db226c922dc..124f9338f781105735455af9cdc3a2c912f91026 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java @@ -178,6 +178,7 @@ public class AlarmManager { public static final int FLAG_IDLE_UNTIL = 1<<4; private final IAlarmManager mService; + private final Context mContext; private final String mPackageName; private final boolean mAlwaysExact; private final int mTargetSdkVersion; @@ -265,6 +266,7 @@ public class AlarmManager { AlarmManager(IAlarmManager service, Context ctx) { mService = service; + mContext = ctx; mPackageName = ctx.getPackageName(); mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion; mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT); @@ -1028,7 +1030,7 @@ public class AlarmManager { * @see #ACTION_NEXT_ALARM_CLOCK_CHANGED */ public AlarmClockInfo getNextAlarmClock() { - return getNextAlarmClock(UserHandle.myUserId()); + return getNextAlarmClock(mContext.getUserId()); } /** diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index e923fb217beaec2b860d4aa9b2177ab9eba9a52d..4c9fb74c9c801f1f4c8642c2d0067426c5e7b581 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1670,7 +1670,7 @@ public class AppOpsManager { /** @hide */ public void resetAllModes() { try { - mService.resetAllModes(UserHandle.myUserId(), null); + mService.resetAllModes(mContext.getUserId(), null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index a13ac49bb55370b9263fa2bb67bb837ff4939553..81cbbcafe8c421936e81113d86b27009c8c2d27d 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -26,6 +26,7 @@ import android.content.ContextWrapper; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; +import android.view.autofill.AutofillManager; /** * Base class for maintaining global application state. You can provide your own @@ -299,4 +300,37 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } } + + /** @hide */ + @Override + public AutofillManager.AutofillClient getAutofillClient() { + final AutofillManager.AutofillClient client = super.getAutofillClient(); + if (client != null) { + return client; + } + // Okay, ppl use the application context when they should not. This breaks + // autofill among other things. We pick the focused activity since autofill + // interacts only with the currently focused activity and we need the fill + // client only if a call comes from the focused activity. Sigh... + final ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread == null) { + return null; + } + final int activityCount = activityThread.mActivities.size(); + for (int i = 0; i < activityCount; i++) { + final ActivityThread.ActivityClientRecord record = + activityThread.mActivities.valueAt(i); + if (record == null) { + continue; + } + final Activity activity = record.activity; + if (activity == null) { + continue; + } + if (activity.getWindow().getDecorView().hasFocus()) { + return record.activity; + } + } + return null; + } } \ No newline at end of file diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 6b0a2f90c38dca04a81b1571f265db20011885a1..13117bcbc9298f07efdf07e1f34beb35a94111eb 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -139,6 +139,11 @@ public class ApplicationPackageManager extends PackageManager { } } + @Override + public int getUserId() { + return mContext.getUserId(); + } + @Override public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 6496110ac9c6aef46f2c86c186c16943861f2224..4a9b2bcb16ed8e7356ac7247f06af0db3378b371 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -164,7 +164,7 @@ class ContextImpl extends Context { private final @Nullable IBinder mActivityToken; - private final @Nullable UserHandle mUser; + private final @NonNull UserHandle mUser; private final ApplicationContentResolver mContentResolver; @@ -187,6 +187,7 @@ class ContextImpl extends Context { private @Nullable String mSplitName = null; private AutofillClient mAutofillClient = null; + private boolean mIsAutofillCompatEnabled; private final Object mSync = new Object(); @@ -1565,8 +1566,7 @@ class ContextImpl extends Context { public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); - return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), - Process.myUserHandle()); + return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser()); } /** @hide */ @@ -2038,8 +2038,7 @@ class ContextImpl extends Context { @Override public Context createPackageContext(String packageName, int flags) throws NameNotFoundException { - return createPackageContextAsUser(packageName, flags, - mUser != null ? mUser : Process.myUserHandle()); + return createPackageContextAsUser(packageName, flags, mUser); } @Override @@ -2233,6 +2232,12 @@ class ContextImpl extends Context { return file; } + /** {@hide} */ + @Override + public UserHandle getUser() { + return mUser; + } + /** {@hide} */ @Override public int getUserId() { @@ -2251,6 +2256,18 @@ class ContextImpl extends Context { mAutofillClient = client; } + /** @hide */ + @Override + public boolean isAutofillCompatibilityEnabled() { + return mIsAutofillCompatEnabled; + } + + /** @hide */ + @Override + public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) { + mIsAutofillCompatEnabled = autofillCompatEnabled; + } + static ContextImpl createSystemContext(ActivityThread mainThread) { LoadedApk packageInfo = new LoadedApk(mainThread); ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, @@ -2382,7 +2399,7 @@ class ContextImpl extends Context { } } - mContentResolver = new ApplicationContentResolver(this, mainThread, user); + mContentResolver = new ApplicationContentResolver(this, mainThread); } void setResources(Resources r) { @@ -2498,13 +2515,10 @@ class ContextImpl extends Context { private static final class ApplicationContentResolver extends ContentResolver { private final ActivityThread mMainThread; - private final UserHandle mUser; - public ApplicationContentResolver( - Context context, ActivityThread mainThread, UserHandle user) { + public ApplicationContentResolver(Context context, ActivityThread mainThread) { super(context); mMainThread = Preconditions.checkNotNull(mainThread); - mUser = Preconditions.checkNotNull(user); } @Override @@ -2550,7 +2564,7 @@ class ContextImpl extends Context { /** @hide */ protected int resolveUserIdFromAuthority(String auth) { - return ContentProvider.getUserIdFromAuthority(auth, mUser.getIdentifier()); + return ContentProvider.getUserIdFromAuthority(auth, getUserId()); } } } diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java deleted file mode 100644 index d1c244136ec9858a23920e66301857ae4b164160..0000000000000000000000000000000000000000 --- a/core/java/android/app/EphemeralResolverService.java +++ /dev/null @@ -1,104 +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 android.app; - -import android.annotation.SystemApi; -import android.content.pm.EphemeralResolveInfo; -import android.content.pm.InstantAppResolveInfo; -import android.os.Build; -import android.os.Looper; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Base class for implementing the resolver service. - * @hide - * @removed - * @deprecated use InstantAppResolverService instead - */ -@Deprecated -@SystemApi -public abstract class EphemeralResolverService extends InstantAppResolverService { - private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; - private static final String TAG = "PackageManager"; - - /** - * Called to retrieve resolve info for ephemeral applications. - * - * @param digestPrefix The hash prefix of the ephemeral's domain. - * @param prefixMask A mask that was applied to each digest prefix. This should - * be used when comparing against the digest prefixes as all bits might - * not be set. - * @deprecated use {@link #onGetEphemeralResolveInfo(int[])} instead - */ - @Deprecated - public abstract List onEphemeralResolveInfoList( - int digestPrefix[], int prefix); - - /** - * Called to retrieve resolve info for ephemeral applications. - * - * @param digestPrefix The hash prefix of the ephemeral's domain. - */ - public List onGetEphemeralResolveInfo(int digestPrefix[]) { - return onEphemeralResolveInfoList(digestPrefix, 0xFFFFF000); - } - - /** - * Called to retrieve intent filters for ephemeral applications. - * - * @param hostName The name of the host to get intent filters for. - */ - public EphemeralResolveInfo onGetEphemeralIntentFilter(String hostName) { - throw new IllegalStateException("Must define"); - } - - @Override - public Looper getLooper() { - return super.getLooper(); - } - - void _onGetInstantAppResolveInfo(int[] digestPrefix, String token, - InstantAppResolutionCallback callback) { - if (DEBUG_EPHEMERAL) { - Log.d(TAG, "Legacy resolver; getInstantAppResolveInfo;" - + " prefix: " + Arrays.toString(digestPrefix)); - } - final List response = onGetEphemeralResolveInfo(digestPrefix); - final int responseSize = response == null ? 0 : response.size(); - final List resultList = new ArrayList<>(responseSize); - for (int i = 0; i < responseSize; i++) { - resultList.add(response.get(i).getInstantAppResolveInfo()); - } - callback.onInstantAppResolveInfo(resultList); - } - - void _onGetInstantAppIntentFilter(int[] digestPrefix, String token, - String hostName, InstantAppResolutionCallback callback) { - if (DEBUG_EPHEMERAL) { - Log.d(TAG, "Legacy resolver; getInstantAppIntentFilter;" - + " prefix: " + Arrays.toString(digestPrefix)); - } - final EphemeralResolveInfo response = onGetEphemeralIntentFilter(hostName); - final List resultList = new ArrayList<>(1); - resultList.add(response.getInstantAppResolveInfo()); - callback.onInstantAppResolveInfo(resultList); - } -} diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 893a41cc992b353dce9b52f53c1bda35165cb856..9e99a78ccfbda570dd910c949b2d65a177533d3e 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -67,7 +67,7 @@ oneway interface IApplicationThread { int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode, boolean persistent, in Configuration config, in CompatibilityInfo compatInfo, in Map services, - in Bundle coreSettings, in String buildSerial); + in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled); void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs); void scheduleExit(); void scheduleServiceArgs(IBinder token, in ParceledListSlice args); diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java index 89aff36f883a103469fb91515f8ff504ca85e805..2ba4c00c3f469f23e73a7a101037722bbfc795e9 100644 --- a/core/java/android/app/InstantAppResolverService.java +++ b/core/java/android/app/InstantAppResolverService.java @@ -43,7 +43,7 @@ import java.util.List; */ @SystemApi public abstract class InstantAppResolverService extends Service { - private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; + private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE; private static final String TAG = "PackageManager"; /** @hide */ @@ -88,7 +88,7 @@ public abstract class InstantAppResolverService extends Service { public void onGetInstantAppResolveInfo(Intent sanitizedIntent, int[] hostDigestPrefix, String token, InstantAppResolutionCallback callback) { // if not overridden, forward to old methods and filter out non-web intents - if (sanitizedIntent.isBrowsableWebIntent()) { + if (sanitizedIntent.isWebIntent()) { onGetInstantAppResolveInfo(hostDigestPrefix, token, callback); } else { callback.onInstantAppResolveInfo(Collections.emptyList()); @@ -107,7 +107,7 @@ public abstract class InstantAppResolverService extends Service { String token, InstantAppResolutionCallback callback) { Log.e(TAG, "New onGetInstantAppIntentFilter is not overridden"); // if not overridden, forward to old methods and filter out non-web intents - if (sanitizedIntent.isBrowsableWebIntent()) { + if (sanitizedIntent.isWebIntent()) { onGetInstantAppIntentFilter(hostDigestPrefix, token, callback); } else { callback.onInstantAppResolveInfo(Collections.emptyList()); @@ -133,7 +133,7 @@ public abstract class InstantAppResolverService extends Service { @Override public void getInstantAppResolveInfoList(Intent sanitizedIntent, int[] digestPrefix, String token, int sequence, IRemoteCallback callback) { - if (DEBUG_EPHEMERAL) { + if (DEBUG_INSTANT) { Slog.v(TAG, "[" + token + "] Phase1 called; posting"); } final SomeArgs args = SomeArgs.obtain(); @@ -148,7 +148,7 @@ public abstract class InstantAppResolverService extends Service { @Override public void getInstantAppIntentFilterList(Intent sanitizedIntent, int[] digestPrefix, String token, IRemoteCallback callback) { - if (DEBUG_EPHEMERAL) { + if (DEBUG_INSTANT) { Slog.v(TAG, "[" + token + "] Phase2 called; posting"); } final SomeArgs args = SomeArgs.obtain(); @@ -203,7 +203,7 @@ public abstract class InstantAppResolverService extends Service { final String token = (String) args.arg3; final Intent intent = (Intent) args.arg4; final int sequence = message.arg1; - if (DEBUG_EPHEMERAL) { + if (DEBUG_INSTANT) { Slog.d(TAG, "[" + token + "] Phase1 request;" + " prefix: " + Arrays.toString(digestPrefix)); } @@ -217,7 +217,7 @@ public abstract class InstantAppResolverService extends Service { final int[] digestPrefix = (int[]) args.arg2; final String token = (String) args.arg3; final Intent intent = (Intent) args.arg4; - if (DEBUG_EPHEMERAL) { + if (DEBUG_INSTANT) { Slog.d(TAG, "[" + token + "] Phase2 request;" + " prefix: " + Arrays.toString(digestPrefix)); } diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 67f5a2e641ae2aed69659e44b1f17ef7ce217833..7f87814a599407ff7571b67cee8333d5618fc543 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1679,7 +1679,7 @@ public class Instrumentation { public void execStartActivities(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options) { execStartActivitiesAsUser(who, contextThread, token, target, intents, options, - UserHandle.myUserId()); + who.getUserId()); } /** diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 553099f25516fe215043ff95915db2435f8054f1..4a3fcaf3e64ef66befa3dbcf22da87ca07c0dd44 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -407,7 +407,7 @@ public class KeyguardManager { * password. */ public boolean isDeviceLocked() { - return isDeviceLocked(UserHandle.myUserId()); + return isDeviceLocked(mContext.getUserId()); } /** @@ -432,7 +432,7 @@ public class KeyguardManager { * @return true if a PIN, pattern or password was set. */ public boolean isDeviceSecure() { - return isDeviceSecure(UserHandle.myUserId()); + return isDeviceSecure(mContext.getUserId()); } /** diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index c34f4d9f0fe873cc530069429fdb42a8a8ae4b91..1d3459534f0c79c053c0ba7c88cd7986fe780456 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -224,8 +224,8 @@ public class LocalActivityManager { private void performPause(LocalActivityRecord r, boolean finishing) { final boolean needState = r.instanceState == null; - final Bundle instanceState = mActivityThread.performPauseActivity( - r, finishing, needState, "performPause", null /* pendingActions */); + final Bundle instanceState = mActivityThread.performPauseActivity(r, finishing, + "performPause", null /* pendingActions */); if (needState) { r.instanceState = instanceState; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 49c03ab9cfac8aeecee04f5dddd840b0c2bfd81d..538623f26a959e1f1a6aebe94a7c6b7f67359677 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -98,7 +98,7 @@ public class NotificationManager { * This broadcast is only sent to the app whose block state has changed. * * Input: nothing - * Output: nothing + * Output: {@link #EXTRA_BLOCKED_STATE} */ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_APP_BLOCK_STATE_CHANGED = @@ -113,24 +113,31 @@ public class NotificationManager { * This broadcast is only sent to the app that owns the channel that has changed. * * Input: nothing - * Output: {@link #EXTRA_BLOCK_STATE_CHANGED_ID} + * Output: {@link #EXTRA_NOTIFICATION_CHANNEL_ID} + * Output: {@link #EXTRA_BLOCKED_STATE} */ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED = "android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED"; /** - * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} or - * {@link #ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED} containing the id of the - * object which has a new blocked state. + * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} containing the id of the + * {@link NotificationChannel} which has a new blocked state. * - * The value will be the {@link NotificationChannel#getId()} of the channel for - * {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} and - * the {@link NotificationChannelGroup#getId()} of the group for - * {@link #ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED}. + * The value will be the {@link NotificationChannel#getId()} of the channel. */ - public static final String EXTRA_BLOCK_STATE_CHANGED_ID = - "android.app.extra.BLOCK_STATE_CHANGED_ID"; + public static final String EXTRA_NOTIFICATION_CHANNEL_ID = + "android.app.extra.NOTIFICATION_CHANNEL_ID"; + + /** + * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED} containing the id + * of the {@link NotificationChannelGroup} which has a new blocked state. + * + * The value will be the {@link NotificationChannelGroup#getId()} of the group. + */ + public static final String EXTRA_NOTIFICATION_CHANNEL_GROUP_ID = + "android.app.extra.NOTIFICATION_CHANNEL_GROUP_ID"; + /** * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} or @@ -142,7 +149,6 @@ public class NotificationManager { */ public static final String EXTRA_BLOCKED_STATE = "android.app.extra.BLOCKED_STATE"; - /** * Intent that is broadcast when a {@link NotificationChannelGroup} is * {@link NotificationChannelGroup#isBlocked() blocked} or unblocked. @@ -150,7 +156,8 @@ public class NotificationManager { * This broadcast is only sent to the app that owns the channel group that has changed. * * Input: nothing - * Output: {@link #EXTRA_BLOCK_STATE_CHANGED_ID} + * Output: {@link #EXTRA_NOTIFICATION_CHANNEL_GROUP_ID} + * Output: {@link #EXTRA_BLOCKED_STATE} */ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED = @@ -351,7 +358,7 @@ public class NotificationManager { */ public void notify(String tag, int id, Notification notification) { - notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId())); + notifyAsUser(tag, id, notification, mContext.getUser()); } /** @@ -412,7 +419,7 @@ public class NotificationManager { */ public void cancel(String tag, int id) { - cancelAsUser(tag, id, new UserHandle(UserHandle.myUserId())); + cancelAsUser(tag, id, mContext.getUser()); } /** @@ -440,7 +447,7 @@ public class NotificationManager { String pkg = mContext.getPackageName(); if (localLOGV) Log.v(TAG, pkg + ": cancelAll()"); try { - service.cancelAllNotifications(pkg, UserHandle.myUserId()); + service.cancelAllNotifications(pkg, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1264,7 +1271,7 @@ public class NotificationManager { final String pkg = mContext.getPackageName(); try { final ParceledListSlice parceledList - = service.getAppActiveNotifications(pkg, UserHandle.myUserId()); + = service.getAppActiveNotifications(pkg, mContext.getUserId()); final List list = parceledList.getList(); return list.toArray(new StatusBarNotification[list.size()]); } catch (RemoteException e) { diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index d6429ae9e5407ef5c32d4c5b06a85414c7f01176..315259bdf3887801b664d9780016e4eba6f708df 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -345,7 +345,7 @@ public final class PendingIntent implements Parcelable { ActivityManager.INTENT_SENDER_ACTIVITY, packageName, null, null, requestCode, new Intent[] { intent }, resolvedType != null ? new String[] { resolvedType } : null, - flags, options, UserHandle.myUserId()); + flags, options, context.getUserId()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -486,7 +486,7 @@ public final class PendingIntent implements Parcelable { ActivityManager.getService().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, null, null, requestCode, intents, resolvedTypes, flags, options, - UserHandle.myUserId()); + context.getUserId()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -544,8 +544,7 @@ public final class PendingIntent implements Parcelable { */ public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, @Flags int flags) { - return getBroadcastAsUser(context, requestCode, intent, flags, - new UserHandle(UserHandle.myUserId())); + return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser()); } /** @@ -644,7 +643,7 @@ public final class PendingIntent implements Parcelable { serviceKind, packageName, null, null, requestCode, new Intent[] { intent }, resolvedType != null ? new String[] { resolvedType } : null, - flags, null, UserHandle.myUserId()); + flags, null, context.getUserId()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 4310434c70be4f2ff7a8d7a7c3a90abf2a46a33e..87f32b2613bc294bf7074fd303d592cee37c56b7 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -38,6 +38,7 @@ import android.content.ClipboardManager; import android.content.Context; import android.content.IRestrictionsManager; import android.content.RestrictionsManager; +import android.content.pm.ApplicationInfo; import android.content.pm.CrossProfileApps; import android.content.pm.ICrossProfileApps; import android.content.pm.IShortcutService; @@ -724,8 +725,9 @@ final class SystemServiceRegistry { service = IPrintManager.Stub.asInterface(ServiceManager .getServiceOrThrow(Context.PRINT_SERVICE)); } - return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(), - UserHandle.getAppId(Process.myUid())); + final int userId = ctx.getUserId(); + final int appId = UserHandle.getAppId(ctx.getApplicationInfo().uid); + return new PrintManager(ctx.getOuterContext(), service, userId, appId); }}); registerService(Context.COMPANION_DEVICE_SERVICE, CompanionDeviceManager.class, @@ -780,12 +782,12 @@ final class SystemServiceRegistry { }}); registerService(Context.TV_INPUT_SERVICE, TvInputManager.class, - new StaticServiceFetcher() { + new CachedServiceFetcher() { @Override - public TvInputManager createService() throws ServiceNotFoundException { + public TvInputManager createService(ContextImpl ctx) throws ServiceNotFoundException { IBinder iBinder = ServiceManager.getServiceOrThrow(Context.TV_INPUT_SERVICE); ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder); - return new TvInputManager(service, UserHandle.myUserId()); + return new TvInputManager(service, ctx.getUserId()); }}); registerService(Context.NETWORK_SCORE_SERVICE, NetworkScoreManager.class, diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java index ab5974777c9eafd714000fe142faeb7b1aba5e74..b99b32748dcd346558616a4bb85211d75dc2e9a2 100644 --- a/core/java/android/app/TaskStackBuilder.java +++ b/core/java/android/app/TaskStackBuilder.java @@ -230,7 +230,7 @@ public class TaskStackBuilder { * Context.startActivity(Intent, Bundle)} for more details. */ public void startActivities(Bundle options) { - startActivities(options, new UserHandle(UserHandle.myUserId())); + startActivities(options, mSourceContext.getUser()); } /** diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index f21746cdd275c477d2c589d2ab2036df7e3b9bd0..19240e25bcd89af2299de7b911f51f395bdc54b2 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -51,6 +51,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.DeadSystemException; +import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -1002,7 +1003,7 @@ public class WallpaperManager { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); } else { - return sGlobals.mService.getWallpaperInfo(UserHandle.myUserId()); + return sGlobals.mService.getWallpaperInfo(mContext.getUserId()); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1150,7 +1151,7 @@ public class WallpaperManager { ParcelFileDescriptor fd = sGlobals.mService.setWallpaper( "res:" + resources.getResourceName(resid), mContext.getOpPackageName(), null, false, result, which, completion, - UserHandle.myUserId()); + mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; boolean ok = false; @@ -1255,7 +1256,7 @@ public class WallpaperManager { boolean allowBackup, @SetWallpaperFlags int which) throws IOException { return setBitmap(fullImage, visibleCropHint, allowBackup, which, - UserHandle.myUserId()); + mContext.getUserId()); } /** @@ -1329,11 +1330,7 @@ public class WallpaperManager { private void copyStreamToWallpaperFile(InputStream data, FileOutputStream fos) throws IOException { - byte[] buffer = new byte[32768]; - int amt; - while ((amt=data.read(buffer)) > 0) { - fos.write(buffer, 0, amt); - } + FileUtils.copy(data, fos); } /** @@ -1406,7 +1403,7 @@ public class WallpaperManager { try { ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null, mContext.getOpPackageName(), visibleCropHint, allowBackup, - result, which, completion, UserHandle.myUserId()); + result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; try { @@ -1643,7 +1640,7 @@ public class WallpaperManager { @SystemApi @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT) public boolean setWallpaperComponent(ComponentName name) { - return setWallpaperComponent(name, UserHandle.myUserId()); + return setWallpaperComponent(name, mContext.getUserId()); } /** diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java index 085fc79f58e43eef4c974e278c4857b53d2820f2..46566e79d99cc9988e926764108e2355e527e891 100644 --- a/core/java/android/app/WindowConfiguration.java +++ b/core/java/android/app/WindowConfiguration.java @@ -146,6 +146,9 @@ public class WindowConfiguration implements Parcelable, Comparable + *

  • {@link #startUserInBackground(ComponentName, UserHandle)}
  • + *
  • {@link #stopUser(ComponentName, UserHandle)}
  • + *
  • {@link #logoutUser(ComponentName)}
  • + * + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "USER_OPERATION_" }, value = { + USER_OPERATION_SUCCESS, + USER_OPERATION_ERROR_UNKNOWN, + USER_OPERATION_ERROR_MANAGED_PROFILE, + USER_OPERATION_ERROR_MAX_RUNNING_USERS, + USER_OPERATION_ERROR_CURRENT_USER + }) + public @interface UserOperationResult {} + /** * Called by a device owner to start the specified secondary user in background. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param userHandle the user to be stopped. - * @return {@code true} if the user can be started, {@code false} otherwise. + * @param userHandle the user to be started in background. + * @return one of the following result codes: + * {@link #USER_OPERATION_ERROR_UNKNOWN}, + * {@link #USER_OPERATION_SUCCESS}, + * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE}, + * {@link #USER_OPERATION_ERROR_MAX_RUNNING_USERS}, * @throws SecurityException if {@code admin} is not a device owner. * @see #getSecondaryUsers(ComponentName) */ - public boolean startUserInBackground( + public @UserOperationResult int startUserInBackground( @NonNull ComponentName admin, @NonNull UserHandle userHandle) { throwIfParentInstance("startUserInBackground"); try { @@ -6632,11 +6698,16 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param userHandle the user to be stopped. - * @return {@code true} if the user can be stopped, {@code false} otherwise. + * @return one of the following result codes: + * {@link #USER_OPERATION_ERROR_UNKNOWN}, + * {@link #USER_OPERATION_SUCCESS}, + * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE}, + * {@link #USER_OPERATION_ERROR_CURRENT_USER} * @throws SecurityException if {@code admin} is not a device owner. * @see #getSecondaryUsers(ComponentName) */ - public boolean stopUser(@NonNull ComponentName admin, @NonNull UserHandle userHandle) { + public @UserOperationResult int stopUser( + @NonNull ComponentName admin, @NonNull UserHandle userHandle) { throwIfParentInstance("stopUser"); try { return mService.stopUser(admin, userHandle); @@ -6650,11 +6721,15 @@ public class DevicePolicyManager { * calling user and switch back to primary. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @return {@code true} if the exit was successful, {@code false} otherwise. + * @return one of the following result codes: + * {@link #USER_OPERATION_ERROR_UNKNOWN}, + * {@link #USER_OPERATION_SUCCESS}, + * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE}, + * {@link #USER_OPERATION_ERROR_CURRENT_USER} * @throws SecurityException if {@code admin} is not a profile owner affiliated with the device. * @see #getSecondaryUsers(ComponentName) */ - public boolean logoutUser(@NonNull ComponentName admin) { + public @UserOperationResult int logoutUser(@NonNull ComponentName admin) { throwIfParentInstance("logoutUser"); try { return mService.logoutUser(admin); @@ -7607,6 +7682,7 @@ public class DevicePolicyManager { throw re.rethrowFromSystemServer(); } } + /** * Called by a device owner or profile owner of secondary users that is affiliated with the * device to disable the keyguard altogether. @@ -8244,6 +8320,22 @@ public class DevicePolicyManager { } } + /** + * Forces a batch of security logs to be fetched from logd and makes it available for DPC. + * Only callable by ADB. If throttled, returns time to wait in milliseconds, otherwise 0. + * @hide + */ + public long forceSecurityLogs() { + if (mService == null) { + return 0; + } + try { + return mService.forceSecurityLogs(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + /** * Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent * profile. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index cba9311ff68b5b6ce92103597d6f03b340be4a5f..ef990071dbfd806bb311e2eff67155a3f0b7bfe8 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -227,9 +227,9 @@ interface IDevicePolicyManager { UserHandle createAndManageUser(in ComponentName who, in String name, in ComponentName profileOwner, in PersistableBundle adminExtras, in int flags); boolean removeUser(in ComponentName who, in UserHandle userHandle); boolean switchUser(in ComponentName who, in UserHandle userHandle); - boolean startUserInBackground(in ComponentName who, in UserHandle userHandle); - boolean stopUser(in ComponentName who, in UserHandle userHandle); - boolean logoutUser(in ComponentName who); + int startUserInBackground(in ComponentName who, in UserHandle userHandle); + int stopUser(in ComponentName who, in UserHandle userHandle); + int logoutUser(in ComponentName who); List getSecondaryUsers(in ComponentName who); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); @@ -349,6 +349,7 @@ interface IDevicePolicyManager { boolean isSecurityLoggingEnabled(in ComponentName admin); ParceledListSlice retrieveSecurityLogs(in ComponentName admin); ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin); + long forceSecurityLogs(); boolean isUninstallInQueue(String packageName); void uninstallPackageWithActiveAdmins(String packageName); diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 87f227129586635370ff57276030e4bc36a0320c..8f49bc177dcbb8ded8023152824d31160a36f4b9 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -4,6 +4,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.content.ComponentName; +import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; import android.net.Uri; @@ -500,9 +501,8 @@ public class AssistStructure implements Parcelable { ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false); if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) { if (forAutoFill) { - final int autofillFlags = (flags & FillRequest.FLAG_MANUAL_REQUEST) != 0 - ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0; - view.onProvideAutofillStructure(builder, autofillFlags); + final int viewFlags = resolveViewAutofillFlags(view.getContext(), flags); + view.onProvideAutofillStructure(builder, viewFlags); } else { // This is a secure window, so it doesn't want a screenshot, and that // means we should also not copy out its view hierarchy for Assist @@ -512,9 +512,8 @@ public class AssistStructure implements Parcelable { } } if (forAutoFill) { - final int autofillFlags = (flags & FillRequest.FLAG_MANUAL_REQUEST) != 0 - ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0; - view.dispatchProvideAutofillStructure(builder, autofillFlags); + final int viewFlags = resolveViewAutofillFlags(view.getContext(), flags); + view.dispatchProvideAutofillStructure(builder, viewFlags); } else { view.dispatchProvideStructure(builder); } @@ -532,6 +531,12 @@ public class AssistStructure implements Parcelable { mRoot = new ViewNode(reader, 0); } + int resolveViewAutofillFlags(Context context, int fillRequestFlags) { + return (fillRequestFlags & FillRequest.FLAG_MANUAL_REQUEST) != 0 + || context.isAutofillCompatibilityEnabled() + ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0; + } + void writeSelfToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix) { out.writeInt(mX); out.writeInt(mY); diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl index 4461b16fe15c764e717fdbcb84f1e34a69c7a35b..38d9025cc82f87503a82289ae9d6501b1284a6bf 100644 --- a/core/java/android/app/slice/ISliceManager.aidl +++ b/core/java/android/app/slice/ISliceManager.aidl @@ -31,4 +31,7 @@ interface ISliceManager { SliceSpec[] getPinnedSpecs(in Uri uri, String pkg); int checkSlicePermission(in Uri uri, String pkg, int pid, int uid); void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices); + + byte[] getBackupPayload(int user); + void applyRestore(in byte[] payload, int user); } diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index 4c24a2dd881201e0f6aae6b6337f02e39871009f..126deefae282e72d6dddc582f92724784ff6ee45 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -164,8 +164,14 @@ public final class Slice implements Parcelable { public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE"; /** * Key to retrieve an extra added to an intent when the value of a slider is changed. + * @deprecated remove once support lib is update to use EXTRA_RANGE_VALUE instead */ + @Deprecated public static final String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE"; + /** + * Key to retrieve an extra added to an intent when the value of an input range is changed. + */ + public static final String EXTRA_RANGE_VALUE = "android.app.slice.extra.RANGE_VALUE"; /** * Subtype to indicate that this is a message as part of a communication * sequence in this slice. @@ -181,14 +187,20 @@ public final class Slice implements Parcelable { public static final String SUBTYPE_COLOR = "color"; /** * Subtype to tag an item as representing a slider. + * @deprecated remove once support lib is update to use SUBTYPE_RANGE instead */ + @Deprecated public static final String SUBTYPE_SLIDER = "slider"; /** - * Subtype to tag an item as representing the max int value for a {@link #SUBTYPE_SLIDER}. + * Subtype to tag an item as representing a range. + */ + public static final String SUBTYPE_RANGE = "range"; + /** + * Subtype to tag an item as representing the max int value for a {@link #SUBTYPE_RANGE}. */ public static final String SUBTYPE_MAX = "max"; /** - * Subtype to tag an item as representing the current int value for a {@link #SUBTYPE_SLIDER}. + * Subtype to tag an item as representing the current int value for a {@link #SUBTYPE_RANGE}. */ public static final String SUBTYPE_VALUE = "value"; /** diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 2fa9d8e0882f6c2e8f3377c716243b563e600e45..3f13fffb385760088737f8ca1b664d55c7aab553 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -20,9 +20,9 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; +import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; -import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; @@ -193,10 +193,15 @@ public class SliceManager { *

    * Pinned state is not persisted across reboots, so apps are expected to re-pin any slices * they still care about after a reboot. + *

    + * This may only be called by apps that are the default launcher for the device + * or the default voice interaction service. Otherwise will throw {@link SecurityException}. * * @param uri The uri of the slice being pinned. * @param specs The list of supported {@link SliceSpec}s of the callback. * @see SliceProvider#onSlicePinned(Uri) + * @see Intent#ACTION_ASSIST + * @see Intent#CATEGORY_HOME */ public void pinSlice(@NonNull Uri uri, @NonNull List specs) { try { @@ -211,10 +216,15 @@ public class SliceManager { * Remove a pin for a slice. *

    * If the slice has no other pins/callbacks then the slice will be unpinned. + *

    + * This may only be called by apps that are the default launcher for the device + * or the default voice interaction service. Otherwise will throw {@link SecurityException}. * * @param uri The uri of the slice being unpinned. * @see #pinSlice * @see SliceProvider#onSliceUnpinned(Uri) + * @see Intent#ACTION_ASSIST + * @see Intent#CATEGORY_HOME */ public void unpinSlice(@NonNull Uri uri) { try { @@ -262,17 +272,13 @@ public class SliceManager { */ public @NonNull Collection getSliceDescendants(@NonNull Uri uri) { ContentResolver resolver = mContext.getContentResolver(); - IContentProvider provider = resolver.acquireProvider(uri); - try { + try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri); - final Bundle res = provider.call(resolver.getPackageName(), - SliceProvider.METHOD_GET_DESCENDANTS, null, extras); + final Bundle res = provider.call(SliceProvider.METHOD_GET_DESCENDANTS, null, extras); return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS); } catch (RemoteException e) { Log.e(TAG, "Unable to get slice descendants", e); - } finally { - resolver.releaseProvider(provider); } return Collections.emptyList(); } @@ -288,17 +294,15 @@ public class SliceManager { public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); ContentResolver resolver = mContext.getContentResolver(); - IContentProvider provider = resolver.acquireProvider(uri); - if (provider == null) { - throw new IllegalArgumentException("Unknown URI " + uri); - } - try { + try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { + if (provider == null) { + throw new IllegalArgumentException("Unknown URI " + uri); + } Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); - final Bundle res = provider.call(mContext.getPackageName(), SliceProvider.METHOD_SLICE, - null, extras); + final Bundle res = provider.call(SliceProvider.METHOD_SLICE, null, extras); Bundle.setDefusable(res, true); if (res == null) { return null; @@ -308,8 +312,55 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; - } finally { - resolver.releaseProvider(provider); + } + } + + /** + * Turns a slice intent into a slice uri. Expects an explicit intent. If there is no + * {@link android.content.ContentProvider} associated with the given intent this will throw + * {@link IllegalArgumentException}. + * + * @param intent The intent associated with a slice. + * @return The Slice Uri provided by the app or null if none is given. + * @see Slice + * @see SliceProvider#onMapIntentToUri(Intent) + * @see Intent + */ + public @Nullable Uri mapIntentToUri(@NonNull Intent intent) { + Preconditions.checkNotNull(intent, "intent"); + Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null, + "Slice intent must be explicit %s", intent); + ContentResolver resolver = mContext.getContentResolver(); + + // Check if the intent has data for the slice uri on it and use that + final Uri intentData = intent.getData(); + if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) { + return intentData; + } + // Otherwise ask the app + List providers = + mContext.getPackageManager().queryIntentContentProviders(intent, 0); + if (providers == null || providers.isEmpty()) { + throw new IllegalArgumentException("Unable to resolve intent " + intent); + } + String authority = providers.get(0).providerInfo.authority; + Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) + .authority(authority).build(); + try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { + if (provider == null) { + throw new IllegalArgumentException("Unknown URI " + uri); + } + Bundle extras = new Bundle(); + extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); + final Bundle res = provider.call(SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras); + if (res == null) { + return null; + } + return res.getParcelable(SliceProvider.EXTRA_SLICE); + } catch (RemoteException e) { + // Arbitrary and not worth documenting, as Activity + // Manager will kill this process shortly anyway. + return null; } } @@ -329,7 +380,7 @@ public class SliceManager { @NonNull List supportedSpecs) { Preconditions.checkNotNull(intent, "intent"); Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null, - "Slice intent must be explicit " + intent); + "Slice intent must be explicit %s", intent); ContentResolver resolver = mContext.getContentResolver(); // Check if the intent has data for the slice uri on it and use that @@ -340,23 +391,21 @@ public class SliceManager { // Otherwise ask the app List providers = mContext.getPackageManager().queryIntentContentProviders(intent, 0); - if (providers == null) { + if (providers == null || providers.isEmpty()) { throw new IllegalArgumentException("Unable to resolve intent " + intent); } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); - IContentProvider provider = resolver.acquireProvider(uri); - if (provider == null) { - throw new IllegalArgumentException("Unknown URI " + uri); - } - try { + try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { + if (provider == null) { + throw new IllegalArgumentException("Unknown URI " + uri); + } Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); - final Bundle res = provider.call(mContext.getPackageName(), - SliceProvider.METHOD_MAP_INTENT, null, extras); + final Bundle res = provider.call(SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } @@ -365,8 +414,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; - } finally { - resolver.releaseProvider(provider); } } diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java index 00e8ccad0f5f340296106618ca498746f63d319f..af4303263da55a49c54f0706079a08c17ed1ee59 100644 --- a/core/java/android/app/slice/SliceProvider.java +++ b/core/java/android/app/slice/SliceProvider.java @@ -111,6 +111,10 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String METHOD_MAP_INTENT = "map_slice"; + /** + * @hide + */ + public static final String METHOD_MAP_ONLY_INTENT = "map_only"; /** * @hide */ @@ -147,6 +151,14 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String EXTRA_OVERRIDE_PKG = "override_pkg"; + /** + * @hide + */ + public static final String EXTRA_OVERRIDE_UID = "override_uid"; + /** + * @hide + */ + public static final String EXTRA_OVERRIDE_PID = "override_pid"; private static final boolean DEBUG = false; @@ -302,13 +314,20 @@ public abstract class SliceProvider extends ContentProvider { List supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS); String callingPackage = getCallingPackage(); + int callingUid = Binder.getCallingUid(); + int callingPid = Binder.getCallingPid(); if (extras.containsKey(EXTRA_OVERRIDE_PKG)) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Only the system can override calling pkg"); } + // This is safe because we would grant SYSTEM_UID access to all slices + // and want to allow it to bind slices as if it were a less privileged app + // to check their permission levels. callingPackage = extras.getString(EXTRA_OVERRIDE_PKG); + callingUid = extras.getInt(EXTRA_OVERRIDE_UID); + callingPid = extras.getInt(EXTRA_OVERRIDE_PID); } - Slice s = handleBindSlice(uri, supportedSpecs, callingPackage); + Slice s = handleBindSlice(uri, supportedSpecs, callingPackage, callingUid, callingPid); Bundle b = new Bundle(); b.putParcelable(EXTRA_SLICE, s); return b; @@ -319,12 +338,20 @@ public abstract class SliceProvider extends ContentProvider { List supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS); Bundle b = new Bundle(); if (uri != null) { - Slice s = handleBindSlice(uri, supportedSpecs, getCallingPackage()); + Slice s = handleBindSlice(uri, supportedSpecs, getCallingPackage(), + Binder.getCallingUid(), Binder.getCallingPid()); b.putParcelable(EXTRA_SLICE, s); } else { b.putParcelable(EXTRA_SLICE, null); } return b; + } else if (method.equals(METHOD_MAP_ONLY_INTENT)) { + Intent intent = extras.getParcelable(EXTRA_INTENT); + if (intent == null) return null; + Uri uri = onMapIntentToUri(intent); + Bundle b = new Bundle(); + b.putParcelable(EXTRA_SLICE, uri); + return b; } else if (method.equals(METHOD_PIN)) { Uri uri = getUriWithoutUserId(extras.getParcelable(EXTRA_BIND_URI)); if (Binder.getCallingUid() != Process.SYSTEM_UID) { @@ -401,15 +428,15 @@ public abstract class SliceProvider extends ContentProvider { } private Slice handleBindSlice(Uri sliceUri, List supportedSpecs, - String callingPkg) { + String callingPkg, int callingUid, int callingPid) { // This can be removed once Slice#bindSlice is removed and everyone is using // SliceManager#bindSlice. String pkg = callingPkg != null ? callingPkg - : getContext().getPackageManager().getNameForUid(Binder.getCallingUid()); - if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) { + : getContext().getPackageManager().getNameForUid(callingUid); + if (!UserHandle.isSameApp(callingUid, Process.myUid())) { try { mSliceManager.enforceSlicePermission(sliceUri, pkg, - Binder.getCallingPid(), Binder.getCallingUid()); + callingPid, callingUid); } catch (SecurityException e) { return createPermissionSlice(getContext(), sliceUri, pkg); } diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index edb6a74bbea441f35c261a9c35bff21c0bb4c427..cf359026105d069fd49dca0d4bf114baecc5972a 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -301,7 +301,7 @@ public final class UsageStatsManager { */ public boolean isAppInactive(String packageName) { try { - return mService.isAppInactive(packageName, UserHandle.myUserId()); + return mService.isAppInactive(packageName, mContext.getUserId()); } catch (RemoteException e) { // fall through and return default } @@ -313,7 +313,7 @@ public final class UsageStatsManager { */ public void setAppInactive(String packageName, boolean inactive) { try { - mService.setAppInactive(packageName, inactive, UserHandle.myUserId()); + mService.setAppInactive(packageName, inactive, mContext.getUserId()); } catch (RemoteException e) { // fall through } diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index a55bbdaea56fcb934ce4b5bb5f992fd18c644e84..a2c75a6c014c7c495ebda8e23f3590ab86ed77f0 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -459,10 +459,9 @@ public class AppWidgetManager { */ public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider"; + private final Context mContext; private final String mPackageName; - private final IAppWidgetService mService; - private final DisplayMetrics mDisplayMetrics; /** @@ -481,6 +480,7 @@ public class AppWidgetManager { * @hide */ public AppWidgetManager(Context context, IAppWidgetService service) { + mContext = context; mPackageName = context.getOpPackageName(); mService = service; mDisplayMetrics = context.getResources().getDisplayMetrics(); @@ -845,7 +845,7 @@ public class AppWidgetManager { } if (profile == null) { - profile = Process.myUserHandle(); + profile = mContext.getUser(); } try { @@ -924,7 +924,7 @@ public class AppWidgetManager { if (mService == null) { return; } - bindAppWidgetIdIfAllowed(appWidgetId, Process.myUserHandle(), provider, options); + bindAppWidgetIdIfAllowed(appWidgetId, mContext.getUser(), provider, options); } /** @@ -944,7 +944,7 @@ public class AppWidgetManager { if (mService == null) { return false; } - return bindAppWidgetIdIfAllowed(appWidgetId, UserHandle.myUserId(), provider, null); + return bindAppWidgetIdIfAllowed(appWidgetId, mContext.getUserId(), provider, null); } /** @@ -968,7 +968,7 @@ public class AppWidgetManager { if (mService == null) { return false; } - return bindAppWidgetIdIfAllowed(appWidgetId, UserHandle.myUserId(), provider, options); + return bindAppWidgetIdIfAllowed(appWidgetId, mContext.getUserId(), provider, options); } /** @@ -1030,7 +1030,7 @@ public class AppWidgetManager { return false; } try { - return mService.hasBindAppWidgetPermission(packageName, UserHandle.myUserId()); + return mService.hasBindAppWidgetPermission(packageName, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1050,7 +1050,7 @@ public class AppWidgetManager { if (mService == null) { return; } - setBindAppWidgetPermission(packageName, UserHandle.myUserId(), permission); + setBindAppWidgetPermission(packageName, mContext.getUserId(), permission); } /** diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index b255a43cbe3066fb1e4c4d26f92243be2b236648..a2e714eb348a9dc519e6ada46c966e43d3f9ae72 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -262,7 +262,7 @@ public final class BluetoothA2dp implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java index faab000a8997c4cc6ced8cebe910dc4ca04f23f0..13f0aaf47f0c0e2b76d8b7218baa3eb5a171e27a 100755 --- a/core/java/android/bluetooth/BluetoothA2dpSink.java +++ b/core/java/android/bluetooth/BluetoothA2dpSink.java @@ -182,7 +182,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java index 5f0e5d97447e2c9863b9c6354ed87675553b9630..e7c8944788fdad43f5db1bd52aec5dc7b598149e 100644 --- a/core/java/android/bluetooth/BluetoothAvrcpController.java +++ b/core/java/android/bluetooth/BluetoothAvrcpController.java @@ -138,7 +138,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index a2af3422eaec341ed60347363b9faf568cfcb459..3df433643b00bcf50fd2934e12c0c47a67c37322 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -1506,6 +1506,38 @@ public final class BluetoothGatt implements BluetoothProfile { return true; } + /** + * Request an LE connection parameter update. + * + *

    This function will send an LE connection parameters update request to the remote device. + * + * @return true, if the request is send to the Bluetooth stack. + * @hide + */ + public boolean requestLeConnectionUpdate(int minConnectionInterval, + int maxConnectionInterval, + int slaveLatency, int supervisionTimeout) { + if (DBG) { + Log.d(TAG, "requestLeConnectionUpdate() - min=(" + minConnectionInterval + + ")" + (1.25 * minConnectionInterval) + + "msec, max=(" + maxConnectionInterval + ")" + + (1.25 * maxConnectionInterval) + "msec, latency=" + slaveLatency + + ", timeout=" + supervisionTimeout + "msec"); + } + if (mService == null || mClientIf == 0) return false; + + try { + mService.leConnectionUpdate(mClientIf, mDevice.getAddress(), + minConnectionInterval, maxConnectionInterval, + slaveLatency, supervisionTimeout); + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + + return true; + } + /** * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} * with {@link BluetoothProfile#GATT} as argument diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 031287f5ee1236d09cf39d5884aa87cd7d070b2f..397b90656f3eda9864e71609adfeafabe7e84dd2 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -427,7 +427,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java index 57a019755f8f54d19fa1faea3baa04df298d8d3c..b967fb20f02356b0753581a3ba0c4f58448f650a 100644 --- a/core/java/android/bluetooth/BluetoothHealth.java +++ b/core/java/android/bluetooth/BluetoothHealth.java @@ -491,7 +491,7 @@ public final class BluetoothHealth implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth Health Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java index 2fab305ba8bdd34276ab748a5a2d5c072ce87feb..77ab7319046ad10eec820e096626c60fe7464df9 100644 --- a/core/java/android/bluetooth/BluetoothHidDevice.java +++ b/core/java/android/bluetooth/BluetoothHidDevice.java @@ -236,7 +236,7 @@ public final class BluetoothHidDevice implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java index 8ad0f9d064fd86fa850c4da1f643900bcee7a534..0ca39f169a721931d06e89ce379bfa139480cfca 100644 --- a/core/java/android/bluetooth/BluetoothHidHost.java +++ b/core/java/android/bluetooth/BluetoothHidHost.java @@ -279,7 +279,7 @@ public final class BluetoothHidHost implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index 5b55b23680c37d8f6a4cf6aa67766ba9983cba0d..0fa1d5d6295f203391b0a5883f6303af48da77d5 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java @@ -109,7 +109,7 @@ public final class BluetoothMap implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java index af3b662d6a4939c069de1f79d6806def3909a347..4f21d936e56289850d9c30c47f01eb0553dad3ca 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -125,7 +125,7 @@ public final class BluetoothMapClient implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index 866b06308354988d25d566b81023901501d26672..9f401eb3cefc1f1ec8b18a4acf7b5b9caa24d858 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -147,7 +147,7 @@ public final class BluetoothPan implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index 794435457f25c8565cd4a27beac0e1202e83a0e8..c60e9e075c87e3e8787bef5df8a1990182be2534 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -163,7 +163,7 @@ public class BluetoothPbap implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java index 01b3f6e0e841898cabb9bd261dff6f44b438c7c0..1446adc8b9c3c020f1eb9ecb9bba286e6394804b 100644 --- a/core/java/android/bluetooth/BluetoothPbapClient.java +++ b/core/java/android/bluetooth/BluetoothPbapClient.java @@ -116,7 +116,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index 48481620c97f870eccf1a4cd89830581ca9aff4b..c51e39a74186ffe9671a9135a33b08b494ef79f1 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -147,7 +147,7 @@ public final class BluetoothSap implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent); return false; } diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 09f96840f91850a420f73d7d36a21fed80c1f14a..09a5b593e521c7d914ea6c22ae093cea9179a744 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -676,6 +676,35 @@ public final class BluetoothSocket implements Closeable { mExcludeSdp = excludeSdp; } + /** + * Set the LE Transmit Data Length to be the maximum that the BT Controller is capable of. This + * parameter is used by the BT Controller to set the maximum transmission packet size on this + * connection. This function is currently used for testing only. + * @hide + */ + public void requestMaximumTxDataLength() throws IOException { + if (mDevice == null) { + throw new IOException("requestMaximumTxDataLength is called on null device"); + } + + try { + if (mSocketState == SocketState.CLOSED) { + throw new IOException("socket closed"); + } + IBluetooth bluetoothProxy = + BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + throw new IOException("Bluetooth is off"); + } + + if (DBG) Log.d(TAG, "requestMaximumTxDataLength"); + bluetoothProxy.getSocketManager().requestMaximumTxDataLength(mDevice); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + throw new IOException("unable to send RPC: " + e.getMessage()); + } + } + private String convertAddr(final byte[] addr) { return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 8d2e141ae78feefc9c415379e095aadd50eb260d..22496a45d84d5679b4bc70f2930bf466e2791f65 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -165,6 +165,26 @@ public abstract class ContentResolver { /** {@hide} Flag to allow sync to occur on metered network. */ public static final String SYNC_EXTRAS_DISALLOW_METERED = "allow_metered"; + /** + * {@hide} Flag only used by the requestsync command to treat a request as if it was made by + * a foreground app. + * + * Only the system and the shell user can set it. + * + * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle. + */ + public static final String SYNC_VIRTUAL_EXTRAS_FORCE_FG_SYNC = "force_fg_sync"; + + /** + * {@hide} Flag only used by the requestsync command to treat a request as if it was made by + * a background app. + * + * Only the system and the shell user can set it. + * + * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle. + */ + public static final String SYNC_VIRTUAL_EXTRAS_FORCE_BG_SYNC = "force_bg_sync"; + /** * Set by the SyncManager to request that the SyncAdapter initialize itself for * the given account/authority pair. One required initialization step is to @@ -2435,13 +2455,7 @@ public abstract class ContentResolver { public static void addPeriodicSync(Account account, String authority, Bundle extras, long pollFrequency) { validateSyncExtrasBundle(extras); - if (extras.getBoolean(SYNC_EXTRAS_MANUAL, false) - || extras.getBoolean(SYNC_EXTRAS_DO_NOT_RETRY, false) - || extras.getBoolean(SYNC_EXTRAS_IGNORE_BACKOFF, false) - || extras.getBoolean(SYNC_EXTRAS_IGNORE_SETTINGS, false) - || extras.getBoolean(SYNC_EXTRAS_INITIALIZE, false) - || extras.getBoolean(SYNC_EXTRAS_FORCE, false) - || extras.getBoolean(SYNC_EXTRAS_EXPEDITED, false)) { + if (invalidPeriodicExtras(extras)) { throw new IllegalArgumentException("illegal extras were set"); } try { @@ -2998,6 +3012,11 @@ public abstract class ContentResolver { return ContentProvider.getUserIdFromUri(uri, mContext.getUserId()); } + /** @hide */ + public int getUserId() { + return mContext.getUserId(); + } + /** @hide */ public Drawable getTypeDrawable(String mimeType) { return MimeIconUtils.loadMimeIcon(mContext, mimeType); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f2eb4a0285a492e334eb97ce79acb4321c364fd3..b85a3199881cd5e1430cb6d497672d0e2d961d10 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -49,6 +49,7 @@ import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -4678,9 +4679,15 @@ public abstract class Context { * * @hide */ - public abstract Context createPackageContextAsUser( + @SystemApi + public Context createPackageContextAsUser( String packageName, @CreatePackageOptions int flags, UserHandle user) - throws PackageManager.NameNotFoundException; + throws PackageManager.NameNotFoundException { + if (Build.IS_ENG) { + throw new IllegalStateException("createPackageContextAsUser not overridden!"); + } + return this; + } /** * Creates a context given an {@link android.content.pm.ApplicationInfo}. @@ -4705,13 +4712,22 @@ public abstract class Context { throws PackageManager.NameNotFoundException; /** - * Get the userId associated with this context - * @return user id - * + * Get the user associated with this context + * @hide + */ + @TestApi + public UserHandle getUser() { + return android.os.Process.myUserHandle(); + } + + /** + * Get the user associated with this context * @hide */ @TestApi - public abstract @UserIdInt int getUserId(); + public @UserIdInt int getUserId() { + return android.os.UserHandle.myUserId(); + } /** * Return a new Context object for the current Context but whose resources @@ -4908,6 +4924,19 @@ public abstract class Context { public void setAutofillClient(AutofillClient client) { } + /** + * @hide + */ + public boolean isAutofillCompatibilityEnabled() { + return false; + } + + /** + * @hide + */ + public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) { + } + /** * Throws an exception if the Context is using system resources, * which are non-runtime-overlay-themable and may show inconsistent UI. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 8c1293e5b2983f2ec7de13538fccc465453b87e0..a788989a7578c7964b04bffebb439335131b3c14 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -994,4 +994,20 @@ public class ContextWrapper extends Context { public void setAutofillClient(AutofillClient client) { mBase.setAutofillClient(client); } + + /** + * @hide + */ + @Override + public boolean isAutofillCompatibilityEnabled() { + return mBase.isAutofillCompatibilityEnabled(); + } + + /** + * @hide + */ + @Override + public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) { + mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled); + } } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index b3c8737a283112bdecc7c4a39afcfa305fa58e28..fa73e3cbab99798967584dd81df9e04b0929d55d 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1553,16 +1553,6 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE"; - /** - * @hide - * @removed - * @deprecated Do not use. This will go away. - * Replace with {@link #ACTION_INSTALL_INSTANT_APP_PACKAGE}. - */ - @SystemApi - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE - = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE"; /** * Activity Action: Launch instant application installer. *

    @@ -1576,16 +1566,6 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE"; - /** - * @hide - * @removed - * @deprecated Do not use. This will go away. - * Replace with {@link #ACTION_RESOLVE_INSTANT_APP_PACKAGE}. - */ - @SystemApi - @SdkConstant(SdkConstantType.SERVICE_ACTION) - public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE - = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE"; /** * Service Action: Resolve instant application. *

    @@ -1600,16 +1580,6 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE"; - /** - * @hide - * @removed - * @deprecated Do not use. This will go away. - * Replace with {@link #ACTION_INSTANT_APP_RESOLVER_SETTINGS}. - */ - @SystemApi - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS - = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS"; /** * Activity Action: Launch instant app settings. * @@ -4444,32 +4414,77 @@ public class Intent implements Parcelable, Cloneable { /** * A {@link IntentSender} to start after ephemeral installation success. + * @deprecated Use {@link #EXTRA_INSTANT_APP_SUCCESS). + * @removed * @hide */ + @Deprecated public static final String EXTRA_EPHEMERAL_SUCCESS = "android.intent.extra.EPHEMERAL_SUCCESS"; + /** + * A {@link IntentSender} to start after instant app installation success. + * @hide + */ + @SystemApi + public static final String EXTRA_INSTANT_APP_SUCCESS = + "android.intent.extra.INSTANT_APP_SUCCESS"; + /** * A {@link IntentSender} to start after ephemeral installation failure. + * @deprecated Use {@link #EXTRA_INSTANT_APP_FAILURE). + * @removed * @hide */ + @Deprecated public static final String EXTRA_EPHEMERAL_FAILURE = "android.intent.extra.EPHEMERAL_FAILURE"; + /** + * A {@link IntentSender} to start after instant app installation failure. + * @hide + */ + @SystemApi + public static final String EXTRA_INSTANT_APP_FAILURE = + "android.intent.extra.INSTANT_APP_FAILURE"; + /** * The host name that triggered an ephemeral resolution. + * @deprecated Use {@link #EXTRA_INSTANT_APP_HOSTNAME). + * @removed * @hide */ + @Deprecated public static final String EXTRA_EPHEMERAL_HOSTNAME = "android.intent.extra.EPHEMERAL_HOSTNAME"; + /** + * The host name that triggered an instant app resolution. + * @hide + */ + @SystemApi + public static final String EXTRA_INSTANT_APP_HOSTNAME = + "android.intent.extra.INSTANT_APP_HOSTNAME"; + /** * An opaque token to track ephemeral resolution. + * @deprecated Use {@link #EXTRA_INSTANT_APP_TOKEN). + * @removed * @hide */ + @Deprecated public static final String EXTRA_EPHEMERAL_TOKEN = "android.intent.extra.EPHEMERAL_TOKEN"; + /** + * An opaque token to track instant app resolution. + * @hide + */ + @SystemApi + public static final String EXTRA_INSTANT_APP_TOKEN = + "android.intent.extra.INSTANT_APP_TOKEN"; + /** * The action that triggered an instant application resolution. * @hide */ + @SystemApi public static final String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION"; /** @@ -4487,6 +4502,7 @@ public class Intent implements Parcelable, Cloneable { * instant application resolver. * @hide */ + @SystemApi public static final String EXTRA_INSTANT_APP_EXTRAS = "android.intent.extra.INSTANT_APP_EXTRAS"; @@ -4512,12 +4528,14 @@ public class Intent implements Parcelable, Cloneable { * The version code of the app to install components from. * @hide */ + @SystemApi public static final String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE"; /** - * The app that triggered the ephemeral installation. + * The app that triggered the instant app installation. * @hide */ + @SystemApi public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE"; @@ -4526,6 +4544,7 @@ public class Intent implements Parcelable, Cloneable { * installer may use. * @hide */ + @SystemApi public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE"; @@ -10070,9 +10089,8 @@ public class Intent implements Parcelable, Cloneable { } /** @hide */ - public boolean isBrowsableWebIntent() { + public boolean isWebIntent() { return ACTION_VIEW.equals(mAction) - && hasCategory(CATEGORY_BROWSABLE) && hasWebURI(); } diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java index 1a207ba055fcd69e64e49e9d0784fa471fd9f5ed..8464e26ec6cd2bd281b12148b9c2122ccea97a06 100644 --- a/core/java/android/content/om/OverlayInfo.java +++ b/core/java/android/content/om/OverlayInfo.java @@ -16,10 +16,14 @@ package android.content.om; +import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Immutable overlay information about a package. All PackageInfos that * represent an overlay package will have a corresponding OverlayInfo. @@ -27,6 +31,19 @@ import android.os.Parcelable; * @hide */ public final class OverlayInfo implements Parcelable { + + @IntDef(prefix = "STATE_", value = { + STATE_UNKNOWN, + STATE_MISSING_TARGET, + STATE_NO_IDMAP, + STATE_DISABLED, + STATE_ENABLED, + STATE_TARGET_UPGRADING, + STATE_OVERLAY_UPGRADING, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface State {} + /** * An internal state used as the initial state of an overlay. OverlayInfo * objects exposed outside the {@link @@ -60,6 +77,18 @@ public final class OverlayInfo implements Parcelable { */ public static final int STATE_ENABLED = 3; + /** + * The target package is currently being upgraded; the state will change + * once the package installation has finished. + */ + public static final int STATE_TARGET_UPGRADING = 4; + + /** + * The overlay package is currently being upgraded; the state will change + * once the package installation has finished. + */ + public static final int STATE_OVERLAY_UPGRADING = 5; + /** * Package name of the overlay package */ @@ -77,13 +106,8 @@ public final class OverlayInfo implements Parcelable { /** * The state of this OverlayInfo as defined by the STATE_* constants in this class. - * - * @see #STATE_MISSING_TARGET - * @see #STATE_NO_IDMAP - * @see #STATE_DISABLED - * @see #STATE_ENABLED */ - public final int state; + public final @State int state; /** * User handle for which this overlay applies @@ -96,13 +120,13 @@ public final class OverlayInfo implements Parcelable { * @param source the source OverlayInfo to base the new instance on * @param state the new state for the source OverlayInfo */ - public OverlayInfo(@NonNull OverlayInfo source, int state) { + public OverlayInfo(@NonNull OverlayInfo source, @State int state) { this(source.packageName, source.targetPackageName, source.baseCodePath, state, source.userId); } public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName, - @NonNull String baseCodePath, int state, int userId) { + @NonNull String baseCodePath, @State int state, int userId) { this.packageName = packageName; this.targetPackageName = targetPackageName; this.baseCodePath = baseCodePath; @@ -136,6 +160,8 @@ public final class OverlayInfo implements Parcelable { case STATE_NO_IDMAP: case STATE_DISABLED: case STATE_ENABLED: + case STATE_TARGET_UPGRADING: + case STATE_OVERLAY_UPGRADING: break; default: throw new IllegalArgumentException("State " + state + " is not a valid state"); @@ -156,7 +182,8 @@ public final class OverlayInfo implements Parcelable { dest.writeInt(userId); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { @Override public OverlayInfo createFromParcel(Parcel source) { return new OverlayInfo(source); @@ -189,14 +216,9 @@ public final class OverlayInfo implements Parcelable { * Translate a state to a human readable string. Only intended for * debugging purposes. * - * @see #STATE_MISSING_TARGET - * @see #STATE_NO_IDMAP - * @see #STATE_DISABLED - * @see #STATE_ENABLED - * * @return a human readable String representing the state. */ - public static String stateToString(int state) { + public static String stateToString(@State int state) { switch (state) { case STATE_UNKNOWN: return "STATE_UNKNOWN"; @@ -208,6 +230,10 @@ public final class OverlayInfo implements Parcelable { return "STATE_DISABLED"; case STATE_ENABLED: return "STATE_ENABLED"; + case STATE_TARGET_UPGRADING: + return "STATE_TARGET_UPGRADING"; + case STATE_OVERLAY_UPGRADING: + return "STATE_OVERLAY_UPGRADING"; default: return ""; } diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java new file mode 100644 index 0000000000000000000000000000000000000000..2aaac0280a0ec2420fd745383e5a07e939c22cc2 --- /dev/null +++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.content.pm; + +import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; +import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; + +import android.content.pm.PackageParser.Package; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * Updates a package to ensure that if it targets < P that the android.test.base library is + * included by default. + * + *

    This is separated out so that it can be conditionally included at build time depending on + * whether android.test.base is on the bootclasspath or not. In order to include this at + * build time, and remove android.test.base from the bootclasspath pass + * REMOVE_ATB_FROM_BCP=true on the build command line, otherwise this class will not be included + * and the + * + * @hide + */ +@VisibleForTesting +public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater { + + @Override + public void updatePackage(Package pkg) { + // Packages targeted at <= O_MR1 expect the classes in the android.test.base library + // to be accessible so this maintains backward compatibility by adding the + // android.test.base library to those packages. + if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) { + prefixRequiredLibrary(pkg, ANDROID_TEST_BASE); + } else { + // If a package already depends on android.test.runner then add a dependency on + // android.test.base because android.test.runner depends on classes from the + // android.test.base library. + prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_BASE); + } + } +} diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index f6697e8148a0f182d7dc63ec247a155a8f3769bd..db1630b67bd26dfa2865599d3632488e9c4595f1 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -958,6 +958,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * Version of the sandbox the application wants to run in. * @hide */ + @SystemApi public int targetSandboxVersion; /** @@ -1655,7 +1656,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; } - /** @hide */ + /** + * True if the application is installed as an instant app. + * @hide + */ + @SystemApi public boolean isInstantApp() { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0; } diff --git a/core/java/android/content/pm/EphemeralIntentFilter.java b/core/java/android/content/pm/EphemeralIntentFilter.java deleted file mode 100644 index 1dbbf816ed9339a4ebd5a7ee0f2b6deda31e8268..0000000000000000000000000000000000000000 --- a/core/java/android/content/pm/EphemeralIntentFilter.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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. - */ - -package android.content.pm; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.content.IntentFilter; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Information about an ephemeral application intent filter. - * @hide - * @removed - */ -@Deprecated -@SystemApi -public final class EphemeralIntentFilter implements Parcelable { - private final InstantAppIntentFilter mInstantAppIntentFilter; - - public EphemeralIntentFilter(@Nullable String splitName, @NonNull List filters) { - mInstantAppIntentFilter = new InstantAppIntentFilter(splitName, filters); - } - - EphemeralIntentFilter(@NonNull InstantAppIntentFilter intentFilter) { - mInstantAppIntentFilter = intentFilter; - } - - EphemeralIntentFilter(Parcel in) { - mInstantAppIntentFilter = in.readParcelable(null /*loader*/); - } - - public String getSplitName() { - return mInstantAppIntentFilter.getSplitName(); - } - - public List getFilters() { - return mInstantAppIntentFilter.getFilters(); - } - - /** @hide */ - InstantAppIntentFilter getInstantAppIntentFilter() { - return mInstantAppIntentFilter; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(mInstantAppIntentFilter, flags); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - @Override - public EphemeralIntentFilter createFromParcel(Parcel in) { - return new EphemeralIntentFilter(in); - } - @Override - public EphemeralIntentFilter[] newArray(int size) { - return new EphemeralIntentFilter[size]; - } - }; -} diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java deleted file mode 100644 index 12131a3ebc982cbaa759c8aa4f43969815b1d999..0000000000000000000000000000000000000000 --- a/core/java/android/content/pm/EphemeralResolveInfo.java +++ /dev/null @@ -1,224 +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 android.content.pm; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.content.IntentFilter; -import android.content.pm.InstantAppResolveInfo.InstantAppDigest; -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * Information about an ephemeral application. - * @hide - * @removed - */ -@Deprecated -@SystemApi -public final class EphemeralResolveInfo implements Parcelable { - /** Algorithm that will be used to generate the domain digest */ - public static final String SHA_ALGORITHM = "SHA-256"; - - private final InstantAppResolveInfo mInstantAppResolveInfo; - @Deprecated - private final List mLegacyFilters; - - @Deprecated - public EphemeralResolveInfo(@NonNull Uri uri, @NonNull String packageName, - @NonNull List filters) { - if (uri == null || packageName == null || filters == null || filters.isEmpty()) { - throw new IllegalArgumentException(); - } - final List ephemeralFilters = new ArrayList<>(1); - ephemeralFilters.add(new EphemeralIntentFilter(packageName, filters)); - mInstantAppResolveInfo = new InstantAppResolveInfo(uri.getHost(), packageName, - createInstantAppIntentFilterList(ephemeralFilters)); - mLegacyFilters = new ArrayList(filters.size()); - mLegacyFilters.addAll(filters); - } - - @Deprecated - public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName, - @Nullable List filters) { - this(digest, packageName, filters, -1 /*versionCode*/); - } - - public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName, - @Nullable List filters, int versionCode) { - mInstantAppResolveInfo = new InstantAppResolveInfo( - digest.getInstantAppDigest(), packageName, - createInstantAppIntentFilterList(filters), versionCode); - mLegacyFilters = null; - } - - public EphemeralResolveInfo(@NonNull String hostName, @Nullable String packageName, - @Nullable List filters) { - this(new EphemeralDigest(hostName), packageName, filters); - } - - EphemeralResolveInfo(Parcel in) { - mInstantAppResolveInfo = in.readParcelable(null /*loader*/); - mLegacyFilters = new ArrayList(); - in.readList(mLegacyFilters, null /*loader*/); - } - - /** @hide */ - public InstantAppResolveInfo getInstantAppResolveInfo() { - return mInstantAppResolveInfo; - } - - private static List createInstantAppIntentFilterList( - List filters) { - if (filters == null) { - return null; - } - final int filterCount = filters.size(); - final List returnList = new ArrayList<>(filterCount); - for (int i = 0; i < filterCount; i++) { - returnList.add(filters.get(i).getInstantAppIntentFilter()); - } - return returnList; - } - - public byte[] getDigestBytes() { - return mInstantAppResolveInfo.getDigestBytes(); - } - - public int getDigestPrefix() { - return mInstantAppResolveInfo.getDigestPrefix(); - } - - public String getPackageName() { - return mInstantAppResolveInfo.getPackageName(); - } - - public List getIntentFilters() { - final List filters = mInstantAppResolveInfo.getIntentFilters(); - final int filterCount = filters.size(); - final List returnList = new ArrayList<>(filterCount); - for (int i = 0; i < filterCount; i++) { - returnList.add(new EphemeralIntentFilter(filters.get(i))); - } - return returnList; - } - - public int getVersionCode() { - return mInstantAppResolveInfo.getVersionCode(); - } - - @Deprecated - public List getFilters() { - return mLegacyFilters; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(mInstantAppResolveInfo, flags); - out.writeList(mLegacyFilters); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - @Override - public EphemeralResolveInfo createFromParcel(Parcel in) { - return new EphemeralResolveInfo(in); - } - @Override - public EphemeralResolveInfo[] newArray(int size) { - return new EphemeralResolveInfo[size]; - } - }; - - /** - * Helper class to generate and store each of the digests and prefixes - * sent to the Ephemeral Resolver. - *

    - * Since intent filters may want to handle multiple hosts within a - * domain [eg “*.google.com”], the resolver is presented with multiple - * hash prefixes. For example, "a.b.c.d.e" generates digests for - * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e". - * - * @hide - */ - @SystemApi - public static final class EphemeralDigest implements Parcelable { - private final InstantAppDigest mInstantAppDigest; - - public EphemeralDigest(@NonNull String hostName) { - this(hostName, -1 /*maxDigests*/); - } - - /** @hide */ - public EphemeralDigest(@NonNull String hostName, int maxDigests) { - mInstantAppDigest = new InstantAppDigest(hostName, maxDigests); - } - - EphemeralDigest(Parcel in) { - mInstantAppDigest = in.readParcelable(null /*loader*/); - } - - /** @hide */ - InstantAppDigest getInstantAppDigest() { - return mInstantAppDigest; - } - - public byte[][] getDigestBytes() { - return mInstantAppDigest.getDigestBytes(); - } - - public int[] getDigestPrefix() { - return mInstantAppDigest.getDigestPrefix(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(mInstantAppDigest, flags); - } - - @SuppressWarnings("hiding") - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public EphemeralDigest createFromParcel(Parcel in) { - return new EphemeralDigest(in); - } - @Override - public EphemeralDigest[] newArray(int size) { - return new EphemeralDigest[size]; - } - }; - } -} diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl index 0b16852246f8eeae51ace70be06530339857169f..8fddb99b35a8184a8b0fe1663cabc721afc939a4 100644 --- a/core/java/android/content/pm/IPackageInstallerSession.aidl +++ b/core/java/android/content/pm/IPackageInstallerSession.aidl @@ -26,9 +26,12 @@ interface IPackageInstallerSession { void addClientProgress(float progress); String[] getNames(); + ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes); ParcelFileDescriptor openRead(String name); + void write(String name, long offsetBytes, long lengthBytes, in ParcelFileDescriptor fd); + void removeSplit(String splitName); void close(); diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java index 67e4cd56136101cde3bfc9569eb2dca2b35eabc9..a16f81b11ae6e17b8c35b9b1227b644faac1d068 100644 --- a/core/java/android/content/pm/PackageBackwardCompatibility.java +++ b/core/java/android/content/pm/PackageBackwardCompatibility.java @@ -16,6 +16,7 @@ package android.content.pm; +import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK; import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; @@ -52,12 +53,22 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { "android.content.pm.OrgApacheHttpLegacyUpdater", RemoveUnnecessaryOrgApacheHttpLegacyLibrary::new); + // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before + // android.test.mock. packageUpdaters.add(new AndroidTestRunnerSplitUpdater()); + // Attempt to load and add the optional updater that will only be available when + // REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default updater that + // will remove any references to org.apache.http.library from the package so that it does + // not try and load the library when it is on the bootclasspath. + boolean bootClassPathContainsATB = !addOptionalUpdater(packageUpdaters, + "android.content.pm.AndroidTestBaseUpdater", + RemoveUnnecessaryAndroidTestBaseLibrary::new); + PackageSharedLibraryUpdater[] updaterArray = packageUpdaters .toArray(new PackageSharedLibraryUpdater[0]); INSTANCE = new PackageBackwardCompatibility( - bootClassPathContainsOAHL, updaterArray); + bootClassPathContainsOAHL, bootClassPathContainsATB, updaterArray); } /** @@ -105,11 +116,14 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { private final boolean mBootClassPathContainsOAHL; + private final boolean mBootClassPathContainsATB; + private final PackageSharedLibraryUpdater[] mPackageUpdaters; public PackageBackwardCompatibility(boolean bootClassPathContainsOAHL, - PackageSharedLibraryUpdater[] packageUpdaters) { + boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) { this.mBootClassPathContainsOAHL = bootClassPathContainsOAHL; + this.mBootClassPathContainsATB = bootClassPathContainsATB; this.mPackageUpdaters = packageUpdaters; } @@ -139,6 +153,14 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { return INSTANCE.mBootClassPathContainsOAHL; } + /** + * True if the android.test.base is on the bootclasspath, false otherwise. + */ + @VisibleForTesting + public static boolean bootClassPathContainsATB() { + return INSTANCE.mBootClassPathContainsATB; + } + /** * Add android.test.mock dependency for any APK that depends on android.test.runner. * @@ -173,4 +195,18 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { } } + + /** + * Remove any usages of android.test.base from the shared library as the library is on the + * bootclasspath. + */ + @VisibleForTesting + public static class RemoveUnnecessaryAndroidTestBaseLibrary + extends PackageSharedLibraryUpdater { + + @Override + public void updatePackage(Package pkg) { + removeLibrary(pkg, ANDROID_TEST_BASE); + } + } } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index df677d208d36a9a3e53549a7826368907b7e3cd8..d0be6c854020994db2d8127932a2ca415caf58f7 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -829,7 +829,19 @@ public class PackageInstaller { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } + } + /** {@hide} */ + public void write(@NonNull String name, long offsetBytes, long lengthBytes, + @NonNull ParcelFileDescriptor fd) throws IOException { + try { + mSession.write(name, offsetBytes, lengthBytes, fd); + } catch (RuntimeException e) { + ExceptionUtils.maybeUnwrapIOException(e); + throw e; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 0b4231fbc9163e5ccf255d749b5066fd1ff4e2cf..486c86cedba32e865d1c309579d6de9f3cc55cc4 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -441,6 +441,7 @@ public abstract class PackageManager { * @hide */ @SystemApi + @TestApi public static final int MATCH_FACTORY_ONLY = 0x00200000; /** @@ -2965,6 +2966,11 @@ public abstract class PackageManager { */ public static final int VERSION_CODE_HIGHEST = -1; + /** {@hide} */ + public int getUserId() { + return UserHandle.myUserId(); + } + /** * Retrieve overall information about an application package that is * installed on the system. @@ -5212,7 +5218,7 @@ public abstract class PackageManager { */ @Deprecated public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) { - getPackageSizeInfoAsUser(packageName, UserHandle.myUserId(), observer); + getPackageSizeInfoAsUser(packageName, getUserId(), observer); } /** diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 3d26af1f15bba8f8ac5f295d61553bf275682ee3..3afc346af36edfcbcec5945e339d965a5d6a4242 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -78,8 +78,10 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Base64; +import android.util.ByteStringUtils; import android.util.DisplayMetrics; import android.util.Log; +import android.util.PackageUtils; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -5683,7 +5685,10 @@ public class PackageParser { return true; } - /** A container for signing-related data of an application package. */ + /** + * A container for signing-related data of an application package. + * @hide + */ public static final class SigningDetails implements Parcelable { @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN, @@ -5705,15 +5710,54 @@ public class PackageParser { public final ArraySet publicKeys; /** - * Collection of {@code Signature} objects, each of which is formed from a former signing - * certificate of this APK before it was changed by signing certificate rotation. + * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that + * contains two pieces of information: + * 1) the past signing certificates + * 2) the flags that APK wants to assign to each of the past signing certificates. + * + * This collection of {@code Signature} objects, each of which is formed from a former + * signing certificate of this APK before it was changed by signing certificate rotation, + * represents the first piece of information. It is the APK saying to the rest of the + * world: "hey if you trust the old cert, you can trust me!" This is useful, if for + * instance, the platform would like to determine whether or not to allow this APK to do + * something it would've allowed it to do under the old cert (like upgrade). */ @Nullable public final Signature[] pastSigningCertificates; + /** special value used to see if cert is in package - not exposed to callers */ + private static final int PAST_CERT_EXISTS = 0; + + @IntDef( + flag = true, + value = {CertCapabilities.INSTALLED_DATA, + CertCapabilities.SHARED_USER_ID, + CertCapabilities.PERMISSION }) + public @interface CertCapabilities { + + /** accept data from already installed pkg with this cert */ + int INSTALLED_DATA = 1; + + /** accept sharedUserId with pkg with this cert */ + int SHARED_USER_ID = 2; + + /** grant SIGNATURE permissions to pkgs with this cert */ + int PERMISSION = 4; + } + /** - * Flags for the {@code pastSigningCertificates} collection, which indicate the capabilities - * the including APK wishes to grant to its past signing certificates. + * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that + * contains two pieces of information: + * 1) the past signing certificates + * 2) the flags that APK wants to assign to each of the past signing certificates. + * + * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates} + * collection, represent the second piece of information and are viewed as capabilities. + * They are an APK's way of telling the platform: "this is how I want to trust my old certs, + * please enforce that." This is useful for situation where this app itself is using its + * signing certificate as an authorization mechanism, like whether or not to allow another + * app to have its SIGNATURE permission. An app could specify whether to allow other apps + * signed by its old cert 'X' to still get a signature permission it defines, for example. */ @Nullable public final int[] pastSigningCertificatesFlags; @@ -5784,6 +5828,244 @@ public class PackageParser { return pastSigningCertificates != null && pastSigningCertificates.length > 0; } + /** + * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one. + * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates, + * then that means it has authorized a signing certificate rotation, which eventually leads + * to our certificate, and thus can be trusted. If this method evaluates to true, this + * SigningDetails object should be trusted if the previous one is. + */ + public boolean hasAncestorOrSelf(SigningDetails oldDetails) { + if (this == UNKNOWN || oldDetails == UNKNOWN) { + return false; + } + if (oldDetails.signatures.length > 1) { + + // multiple-signer packages cannot rotate signing certs, so we just compare current + // signers for an exact match + return signaturesMatchExactly(oldDetails); + } else { + + // we may have signing certificate rotation history, check to see if the oldDetails + // was one of our old signing certificates + return hasCertificate(oldDetails.signatures[0]); + } + } + + /** + * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails} + * is a descendant of {@code oldDetails}, not if they're the same. This is used to + * determine if this object is newer than the provided one. + */ + public boolean hasAncestor(SigningDetails oldDetails) { + if (this == UNKNOWN || oldDetails == UNKNOWN) { + return false; + } + if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) { + + // the last entry in pastSigningCertificates is the current signer, ignore it + for (int i = 0; i < pastSigningCertificates.length - 1; i++) { + if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) { + return true; + } + } + } + return false; + } + + /** + * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or + * not this one grants it the provided capability, represented by the {@code flags} + * parameter. In the event of signing certificate rotation, a package may still interact + * with entities signed by its old signing certificate and not want to break previously + * functioning behavior. The {@code flags} value determines which capabilities the app + * signed by the newer signing certificate would like to continue to give to its previous + * signing certificate(s). + */ + public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) { + if (this == UNKNOWN || oldDetails == UNKNOWN) { + return false; + } + if (oldDetails.signatures.length > 1) { + + // multiple-signer packages cannot rotate signing certs, so we must have an exact + // match, which also means all capabilities are granted + return signaturesMatchExactly(oldDetails); + } else { + + // we may have signing certificate rotation history, check to see if the oldDetails + // was one of our old signing certificates, and if we grant it the capability it's + // requesting + return hasCertificate(oldDetails.signatures[0], flags); + } + } + + /** + * A special case of {@code checkCapability} which re-encodes both sets of signing + * certificates to counteract a previous re-encoding. + */ + public boolean checkCapabilityRecover(SigningDetails oldDetails, + @CertCapabilities int flags) throws CertificateException { + if (oldDetails == UNKNOWN || this == UNKNOWN) { + return false; + } + if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) { + + // signing certificates may have rotated, check entire history for effective match + for (int i = 0; i < pastSigningCertificates.length; i++) { + if (Signature.areEffectiveMatch( + oldDetails.signatures[0], + pastSigningCertificates[i]) + && pastSigningCertificatesFlags[i] == flags) { + return true; + } + } + } else { + return Signature.areEffectiveMatch(oldDetails.signatures, signatures); + } + return false; + } + + /** + * Determine if {@code signature} is in this SigningDetails' signing certificate history, + * including the current signer. Automatically returns false if this object has multiple + * signing certificates, since rotation is only supported for single-signers; this is + * enforced by {@code hasCertificateInternal}. + */ + public boolean hasCertificate(Signature signature) { + return hasCertificateInternal(signature, PAST_CERT_EXISTS); + } + + /** + * Determine if {@code signature} is in this SigningDetails' signing certificate history, + * including the current signer, and whether or not it has the given permission. + * Certificates which match our current signer automatically get all capabilities. + * Automatically returns false if this object has multiple signing certificates, since + * rotation is only supported for single-signers. + */ + public boolean hasCertificate(Signature signature, @CertCapabilities int flags) { + return hasCertificateInternal(signature, flags); + } + + /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */ + public boolean hasCertificate(byte[] certificate) { + Signature signature = new Signature(certificate); + return hasCertificate(signature); + } + + private boolean hasCertificateInternal(Signature signature, int flags) { + if (this == UNKNOWN) { + return false; + } + + // only single-signed apps can have pastSigningCertificates + if (hasPastSigningCertificates()) { + + // check all past certs, except for the current one, which automatically gets all + // capabilities, since it is the same as the current signature + for (int i = 0; i < pastSigningCertificates.length - 1; i++) { + if (pastSigningCertificates[i].equals(signature)) { + if (flags == PAST_CERT_EXISTS + || (flags & pastSigningCertificatesFlags[i]) == flags) { + return true; + } + } + } + } + + // not in previous certs signing history, just check the current signer and make sure + // we are singly-signed + return signatures.length == 1 && signatures[0].equals(signature); + } + + /** + * Determines if the provided {@code sha256String} is an ancestor of this one, and whether + * or not this one grants it the provided capability, represented by the {@code flags} + * parameter. In the event of signing certificate rotation, a package may still interact + * with entities signed by its old signing certificate and not want to break previously + * functioning behavior. The {@code flags} value determines which capabilities the app + * signed by the newer signing certificate would like to continue to give to its previous + * signing certificate(s). + * + * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an + * app with multiple signers, this represents the hex-encoded sha256 + * digest of the combined hex-encoded sha256 digests of each individual + * signing certificate according to {@link + * PackageUtils#computeSignaturesSha256Digest(Signature[])} + */ + public boolean checkCapability(String sha256String, @CertCapabilities int flags) { + if (this == UNKNOWN) { + return false; + } + + // first see if the hash represents a single-signer in our signing history + byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String); + if (hasSha256Certificate(sha256Bytes, flags)) { + return true; + } + + // Not in signing history, either represents multiple signatures or not a match. + // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match. + // We already check the single-signer case above as part of hasSha256Certificate, so no + // need to verify we have multiple signers, just run the old check + // just consider current signing certs + final String[] mSignaturesSha256Digests = + PackageUtils.computeSignaturesSha256Digests(signatures); + final String mSignaturesSha256Digest = + PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests); + return mSignaturesSha256Digest.equals(sha256String); + } + + /** + * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate + * history, including the current signer. Automatically returns false if this object has + * multiple signing certificates, since rotation is only supported for single-signers. + */ + public boolean hasSha256Certificate(byte[] sha256Certificate) { + return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS); + } + + /** + * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing + * certificate in this SigningDetails' signing certificate history, including the current + * signer, and whether or not it has the given permission. Certificates which match our + * current signer automatically get all capabilities. Automatically returns false if this + * object has multiple signing certificates, since rotation is only supported for + * single-signers. + */ + public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) { + return hasSha256CertificateInternal(sha256Certificate, flags); + } + + private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) { + if (this == UNKNOWN) { + return false; + } + if (hasPastSigningCertificates()) { + + // check all past certs, except for the last one, which automatically gets all + // capabilities, since it is the same as the current signature, and is checked below + for (int i = 0; i < pastSigningCertificates.length - 1; i++) { + byte[] digest = PackageUtils.computeSha256DigestBytes( + pastSigningCertificates[i].toByteArray()); + if (Arrays.equals(sha256Certificate, digest)) { + if (flags == PAST_CERT_EXISTS + || (flags & pastSigningCertificatesFlags[i]) == flags) { + return true; + } + } + } + } + + // not in previous certs signing history, just check the current signer + if (signatures.length == 1) { + byte[] digest = + PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray()); + return Arrays.equals(sha256Certificate, digest); + } + return false; + } + /** Returns true if the signatures in this and other match exactly. */ public boolean signaturesMatchExactly(SigningDetails other) { return Signature.areExactMatch(this.signatures, other.signatures); @@ -6456,31 +6738,6 @@ public class PackageParser { + " " + packageName + "}"; } - public String dumpState_temp() { - String flags = ""; - flags += ((applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ? "U" : ""); - flags += ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? "S" : ""); - if ("".equals(flags)) { - flags = "-"; - } - String privFlags = ""; - privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ? "P" : ""); - privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0 ? "O" : ""); - privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0 ? "V" : ""); - if ("".equals(privFlags)) { - privFlags = "-"; - } - return "Package{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName - + ", ver:" + getLongVersionCode() - + ", path: " + codePath - + ", flags: " + flags - + ", privFlags: " + privFlags - + ", extra: " + (mExtras == null ? "<>" : Integer.toHexString(System.identityHashCode(mExtras)) + "}") - + "}"; - } - @Override public int describeContents() { return 0; diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index 3f63d80f58648b2d0624f7403e70289d9a28a7a8..fc2eba28235275b1bd37daac4f62247c06b50d5e 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -277,7 +277,7 @@ public class ResolveInfo implements Parcelable { dr = pm.getDrawable(ci.packageName, iconResourceId, ai); } if (dr != null) { - return pm.getUserBadgedIcon(dr, new UserHandle(UserHandle.myUserId())); + return pm.getUserBadgedIcon(dr, new UserHandle(pm.getUserId())); } return ci.loadIcon(pm); } diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java index 3fbf664b1a836818086ce5b86d5efb30cfe6627d..83e86636424aeacb2cbb6138c8a80ce639018f14 100644 --- a/core/java/android/content/pm/SharedLibraryNames.java +++ b/core/java/android/content/pm/SharedLibraryNames.java @@ -22,6 +22,8 @@ package android.content.pm; */ public class SharedLibraryNames { + static final String ANDROID_TEST_BASE = "android.test.base"; + static final String ANDROID_TEST_MOCK = "android.test.mock"; static final String ANDROID_TEST_RUNNER = "android.test.runner"; diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index 30222b74bdc11a97ef433c6207d0a669bc89450f..25e0ccd8d551234fdfee6118ef9b382b099fa157 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -770,6 +770,6 @@ public class ShortcutManager { /** @hide injection point */ @VisibleForTesting protected int injectMyUserId() { - return UserHandle.myUserId(); + return mContext.getUserId(); } } diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java index fdc54aedac9663c94080ad8da860eeafe402a56c..a2a14eddd59f8118334248896e50ed18c85ec53d 100644 --- a/core/java/android/content/pm/Signature.java +++ b/core/java/android/content/pm/Signature.java @@ -284,6 +284,29 @@ public class Signature implements Parcelable { return areExactMatch(aPrime, bPrime); } + /** + * Test if given {@link Signature} objects are effectively equal. In rare + * cases, certificates can have slightly malformed encoding which causes + * exact-byte checks to fail. + *

    + * To identify effective equality, we bounce the certificates through an + * decode/encode pass before doing the exact-byte check. To reduce attack + * surface area, we only allow a byte size delta of a few bytes. + * + * @throws CertificateException if the before/after length differs + * substantially, usually a signal of something fishy going on. + * @hide + */ + public static boolean areEffectiveMatch(Signature a, Signature b) + throws CertificateException { + final CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + final Signature aPrime = bounce(cf, a); + final Signature bPrime = bounce(cf, b); + + return aPrime.equals(bPrime); + } + /** * Bounce the given {@link Signature} through a decode/encode cycle. * diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java index fdb702f01e9d948aa70637a6ab224ed9ce46c4e3..76fa008799dd6d2879c7747664bfae7b441cb48f 100644 --- a/core/java/android/database/AbstractCursor.java +++ b/core/java/android/database/AbstractCursor.java @@ -395,7 +395,7 @@ public abstract class AbstractCursor implements CrossProcessCursor { */ @Override public void setNotificationUri(ContentResolver cr, Uri notifyUri) { - setNotificationUri(cr, notifyUri, UserHandle.myUserId()); + setNotificationUri(cr, notifyUri, cr.getUserId()); } /** @hide - set the notification uri but with an observer for a particular user's view */ diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java new file mode 100644 index 0000000000000000000000000000000000000000..c811999ce304bf116869562f7e01cb2eabc66a29 --- /dev/null +++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.os.CancellationSignal; +import android.os.Parcelable; + +import java.util.concurrent.Executor; + +/** + * This is the common interface that all biometric authentication classes should implement. + * @hide + */ +public interface BiometricAuthenticator { + + /** + * Container for biometric data + * @hide + */ + abstract class BiometricIdentifier implements Parcelable {} + + /** + * Container for callback data from {@link BiometricAuthenticator#authenticate( + * CancellationSignal, Executor, AuthenticationCallback)} and + * {@link BiometricAuthenticator#authenticate(CryptoObject, CancellationSignal, Executor, + * AuthenticationCallback)} + */ + class AuthenticationResult { + private BiometricIdentifier mIdentifier; + private CryptoObject mCryptoObject; + private int mUserId; + + /** + * @hide + */ + public AuthenticationResult() { } + + /** + * Authentication result + * @param crypto + * @param identifier + * @param userId + * @hide + */ + public AuthenticationResult(CryptoObject crypto, BiometricIdentifier identifier, + int userId) { + mCryptoObject = crypto; + mIdentifier = identifier; + mUserId = userId; + } + + /** + * Obtain the crypto object associated with this transaction + * @return crypto object provided to {@link BiometricAuthenticator#authenticate( + * CryptoObject, CancellationSignal, Executor, AuthenticationCallback)} + */ + public CryptoObject getCryptoObject() { + return mCryptoObject; + } + + /** + * Obtain the biometric identifier associated with this operation. Applications are strongly + * discouraged from associating specific identifiers with specific applications or + * operations. + * @hide + */ + public BiometricIdentifier getId() { + return mIdentifier; + } + + /** + * Obtain the userId for which this biometric was authenticated. + * @hide + */ + public int getUserId() { + return mUserId; + } + }; + + /** + * Callback structure provided to {@link BiometricAuthenticator#authenticate(CancellationSignal, + * Executor, AuthenticationCallback)} or {@link BiometricAuthenticator#authenticate( + * CryptoObject, CancellationSignal, Executor, AuthenticationCallback)}. Users must provide + * an implementation of this for listening to biometric events. + */ + abstract class AuthenticationCallback { + /** + * Called when an unrecoverable error has been encountered and the operation is complete. + * No further actions will be made on this object. + * @param errorCode An integer identifying the error message + * @param errString A human-readable error string that can be shown on an UI + */ + public void onAuthenticationError(int errorCode, CharSequence errString) {} + + /** + * Called when a recoverable error has been encountered during authentication. The help + * string is provided to give the user guidance for what went wrong, such as "Sensor dirty, + * please clean it." + * @param helpCode An integer identifying the error message + * @param helpString A human-readable string that can be shown on an UI + */ + public void onAuthenticationHelp(int helpCode, CharSequence helpString) {} + + /** + * Called when a biometric is recognized. + * @param result An object containing authentication-related data + */ + public void onAuthenticationSucceeded(AuthenticationResult result) {} + + /** + * Called when a biometric is valid but not recognized. + */ + public void onAuthenticationFailed() {} + + /** + * Called when a biometric has been acquired, but hasn't been processed yet. + * @hide + */ + public void onAuthenticationAcquired(int acquireInfo) {} + }; + + /** + * This call warms up the hardware and starts scanning for valid biometrics. It terminates + * when {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)} is called or when {@link AuthenticationCallback#onAuthenticationSucceeded( + * AuthenticationResult)} is called, at which point the crypto object becomes invalid. This + * operation can be canceled by using the provided cancel object. The application wil receive + * authentication errors through {@link AuthenticationCallback}. Calling + * {@link BiometricAuthenticator#authenticate(CryptoObject, CancellationSignal, Executor, + * AuthenticationCallback)} while an existing authentication attempt is occurring will stop + * the previous client and start a new authentication. The interrupted client will receive a + * cancelled notification through {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)}. + * + * @throws IllegalArgumentException If any of the arguments are null + * + * @param crypto Object associated with the call + * @param cancel An object that can be used to cancel authentication + * @param executor An executor to handle callback events + * @param callback An object to receive authentication events + */ + void authenticate(@NonNull CryptoObject crypto, + @NonNull CancellationSignal cancel, + @NonNull @CallbackExecutor Executor executor, + @NonNull AuthenticationCallback callback); + + /** + * This call warms up the hardware and starts scanning for valid biometrics. It terminates + * when {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)} is called or when {@link AuthenticationCallback#onAuthenticationSucceeded( + * AuthenticationResult)} is called. This operation can be canceled by using the provided cancel + * object. The application wil receive authentication errors through + * {@link AuthenticationCallback}. Calling {@link BiometricAuthenticator#authenticate( + * CryptoObject, CancellationSignal, Executor, AuthenticationCallback)} while an existing + * authentication attempt is occurring will stop the previous client and start a new + * authentication. The interrupted client will receive a cancelled notification through + * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}. + * + * @throws IllegalArgumentException If any of the arguments are null + * + * @param cancel An object that can be used to cancel authentication + * @param executor An executor to handle callback events + * @param callback An object to receive authentication events + */ + void authenticate(@NonNull CancellationSignal cancel, + @NonNull @CallbackExecutor Executor executor, + @NonNull AuthenticationCallback callback); +} diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..638f525bfb10e49d7a2abd0725ffca0d5dcdcbca --- /dev/null +++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics; + +import android.hardware.fingerprint.FingerprintManager; + +/** + * Interface containing all of the fingerprint-specific constants. + * @hide + */ +public interface BiometricFingerprintConstants { + // + // Error messages from fingerprint hardware during initilization, enrollment, authentication or + // removal. Must agree with the list in fingerprint.h + // + + /** + * The hardware is unavailable. Try again later. + */ + public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; + + /** + * Error state returned when the sensor was unable to process the current image. + */ + public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; + + /** + * Error state returned when the current request has been running too long. This is intended to + * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is + * platform and sensor-specific, but is generally on the order of 30 seconds. + */ + public static final int FINGERPRINT_ERROR_TIMEOUT = 3; + + /** + * Error state returned for operations like enrollment; the operation cannot be completed + * because there's not enough storage remaining to complete the operation. + */ + public static final int FINGERPRINT_ERROR_NO_SPACE = 4; + + /** + * The operation was canceled because the fingerprint sensor is unavailable. For example, + * this may happen when the user is switched, the device is locked or another pending operation + * prevents or disables it. + */ + public static final int FINGERPRINT_ERROR_CANCELED = 5; + + /** + * The {@link FingerprintManager#remove} call failed. Typically this will happen when the + * provided fingerprint id was incorrect. + * + * @hide + */ + public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; + + /** + * The operation was canceled because the API is locked out due to too many attempts. + * This occurs after 5 failed attempts, and lasts for 30 seconds. + */ + public static final int FINGERPRINT_ERROR_LOCKOUT = 7; + + /** + * Hardware vendors may extend this list if there are conditions that do not fall under one of + * the above categories. Vendors are responsible for providing error strings for these errors. + * These messages are typically reserved for internal operations such as enrollment, but may be + * used to express vendor errors not covered by the ones in fingerprint.h. Applications are + * expected to show the error message string if they happen, but are advised not to rely on the + * message id since they will be device and vendor-specific + */ + public static final int FINGERPRINT_ERROR_VENDOR = 8; + + /** + * The operation was canceled because FINGERPRINT_ERROR_LOCKOUT occurred too many times. + * Fingerprint authentication is disabled until the user unlocks with strong authentication + * (PIN/Pattern/Password) + */ + public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; + + /** + * The user canceled the operation. Upon receiving this, applications should use alternate + * authentication (e.g. a password). The application should also provide the means to return + * to fingerprint authentication, such as a "use fingerprint" button. + */ + public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; + + /** + * The user does not have any fingerprints enrolled. + */ + public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; + + /** + * The device does not have a fingerprint sensor. + */ + public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; + + /** + * @hide + */ + public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; + + // + // Image acquisition messages. Must agree with those in fingerprint.h + // + + /** + * The image acquired was good. + */ + public static final int FINGERPRINT_ACQUIRED_GOOD = 0; + + /** + * Only a partial fingerprint image was detected. During enrollment, the user should be + * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor." + */ + public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; + + /** + * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or + * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}). + */ + public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; + + /** + * The fingerprint image was too noisy due to suspected or detected dirt on the sensor. + * For example, it's reasonable return this after multiple + * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor + * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor + * when this is returned. + */ + public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; + + /** + * The fingerprint image was unreadable due to lack of motion. This is most appropriate for + * linear array sensors that require a swipe motion. + */ + public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; + + /** + * The fingerprint image was incomplete due to quick motion. While mostly appropriate for + * linear array sensors, this could also happen if the finger was moved during acquisition. + * The user should be asked to move the finger slower (linear) or leave the finger on the sensor + * longer. + */ + public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; + + /** + * Hardware vendors may extend this list if there are conditions that do not fall under one of + * the above categories. Vendors are responsible for providing error strings for these errors. + * @hide + */ + public static final int FINGERPRINT_ACQUIRED_VENDOR = 6; + /** + * @hide + */ + public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; +} diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java new file mode 100644 index 0000000000000000000000000000000000000000..496d9c57f252696fd3528bd2e9498d6c10753a70 --- /dev/null +++ b/core/java/android/hardware/biometrics/CryptoObject.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.biometrics; + +import android.annotation.NonNull; +import android.security.keystore.AndroidKeyStoreProvider; + +import java.security.Signature; + +import javax.crypto.Cipher; +import javax.crypto.Mac; + +/** + * A wrapper class for the crypto objects supported by FingerprintManager. Currently the + * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. + * @hide + */ +public class CryptoObject { + private final Object mCrypto; + + public CryptoObject(@NonNull Signature signature) { + mCrypto = signature; + } + + public CryptoObject(@NonNull Cipher cipher) { + mCrypto = cipher; + } + + public CryptoObject(@NonNull Mac mac) { + mCrypto = mac; + } + + /** + * Get {@link Signature} object. + * @return {@link Signature} object or null if this doesn't contain one. + */ + public Signature getSignature() { + return mCrypto instanceof Signature ? (Signature) mCrypto : null; + } + + /** + * Get {@link Cipher} object. + * @return {@link Cipher} object or null if this doesn't contain one. + */ + public Cipher getCipher() { + return mCrypto instanceof Cipher ? (Cipher) mCrypto : null; + } + + /** + * Get {@link Mac} object. + * @return {@link Mac} object or null if this doesn't contain one. + */ + public Mac getMac() { + return mCrypto instanceof Mac ? (Mac) mCrypto : null; + } + + /** + * @hide + * @return the opId associated with this object or 0 if none + */ + public final long getOpId() { + return mCrypto != null + ? AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0; + } +}; diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 40ee8348ac4cbafbdaaa36d97bd552c429af6ef1..df644012ffb7d021d4dd529f69abd1a93a455481 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -923,6 +923,14 @@ public abstract class CameraDevice implements AutoCloseable { * {@link CameraCaptureSession#setRepeatingRequest} or * {@link CameraCaptureSession#setRepeatingBurst}

    * + *

    Individual physical camera settings will only be honored for camera session + * that was initialiazed with corresponding physical camera id output configuration + * {@link OutputConfiguration#setPhysicalCameraId} and the same output targets are + * also attached in the request by {@link CaptureRequest.Builder#addTarget}.

    + * + *

    The output is undefined for any logical camera streams in case valid physical camera + * settings are attached.

    + * * @param templateType An enumeration selecting the use case for this request. Not all template * types are supported on every device. See the documentation for each template type for * details. diff --git a/core/java/android/hardware/camera2/TotalCaptureResult.java b/core/java/android/hardware/camera2/TotalCaptureResult.java index bae2d04b0a24d6befc0f640cce5201912258485e..0be45a0c9779f0eadc87e791aca6f3de0ed82a16 100644 --- a/core/java/android/hardware/camera2/TotalCaptureResult.java +++ b/core/java/android/hardware/camera2/TotalCaptureResult.java @@ -17,7 +17,6 @@ package android.hardware.camera2; import android.annotation.NonNull; -import android.annotation.Nullable; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.CaptureResultExtras; import android.hardware.camera2.impl.PhysicalCaptureResultInfo; @@ -26,6 +25,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Map; /** *

    The total assembled results of a single image capture from the image sensor.

    @@ -49,9 +49,9 @@ import java.util.List; * *

    For a logical multi-camera device, if the CaptureRequest contains a surface for an underlying * physical camera, the corresponding {@link TotalCaptureResult} object will include the metadata - * for that physical camera. And its keys and values can be accessed by - * {@link #getPhysicalCameraKey}. If all requested surfaces are for the logical camera, no - * metadata for physical camera will be included.

    + * for that physical camera. And the mapping between the physical camera id and result metadata + * can be accessed via {@link #getPhysicalCameraResults}. If all requested surfaces are for the + * logical camera, no metadata for physical camera will be included.

    * *

    {@link TotalCaptureResult} objects are immutable.

    * @@ -62,7 +62,7 @@ public final class TotalCaptureResult extends CaptureResult { private final List mPartialResults; private final int mSessionId; // The map between physical camera id and capture result - private final HashMap mPhysicalCaptureResults; + private final HashMap mPhysicalCaptureResults; /** * Takes ownership of the passed-in camera metadata and the partial results @@ -83,10 +83,12 @@ public final class TotalCaptureResult extends CaptureResult { mSessionId = sessionId; - mPhysicalCaptureResults = new HashMap(); + mPhysicalCaptureResults = new HashMap(); for (PhysicalCaptureResultInfo onePhysicalResult : physicalResults) { + CaptureResult physicalResult = new CaptureResult( + onePhysicalResult.getCameraMetadata(), parent, extras); mPhysicalCaptureResults.put(onePhysicalResult.getCameraId(), - onePhysicalResult.getCameraMetadata()); + physicalResult); } } @@ -101,7 +103,7 @@ public final class TotalCaptureResult extends CaptureResult { mPartialResults = new ArrayList<>(); mSessionId = CameraCaptureSession.SESSION_ID_NONE; - mPhysicalCaptureResults = new HashMap(); + mPhysicalCaptureResults = new HashMap(); } /** @@ -132,36 +134,20 @@ public final class TotalCaptureResult extends CaptureResult { } /** - * Get a capture result field value for a particular physical camera id. + * Get the map between physical camera ids and their capture result metadata * - *

    The field definitions can be found in {@link CaptureResult}.

    - * - *

    This function can be called for logical camera devices, which are devices that have + *

    This function can be called for logical multi-camera devices, which are devices that have * REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA capability and calls to {@link * CameraCharacteristics#getPhysicalCameraIds} return a non-empty list of physical devices that - * are backing the logical camera. The camera id included in physicalCameraId argument - * selects an individual physical device, and returns its specific capture result field.

    - * - *

    This function should only be called if one or more streams from the underlying - * 'physicalCameraId' was requested by the corresponding capture request.

    - * - * @throws IllegalArgumentException if the key was not valid, or the physicalCameraId is not - * applicable to the current camera, or a stream from 'physicalCameraId' is not requested by the - * corresponding capture request. - * - * @param key The result field to read. - * @param physicalCameraId The physical camera the result originates from. + * are backing the logical camera.

    * - * @return The value of that key, or {@code null} if the field is not set. - */ - @Nullable - public T getPhysicalCameraKey(Key key, @NonNull String physicalCameraId) { - if (!mPhysicalCaptureResults.containsKey(physicalCameraId)) { - throw new IllegalArgumentException( - "No TotalCaptureResult exists for physical camera " + physicalCameraId); - } + *

    If one or more streams from the underlying physical cameras were requested by the + * corresponding capture request, this function returns the result metadata for those physical + * cameras. Otherwise, an empty map is returned.

    - CameraMetadataNative physicalMetadata = mPhysicalCaptureResults.get(physicalCameraId); - return physicalMetadata.get(key); + * @return unmodifiable map between physical camera ids and their capture result metadata + */ + public Map getPhysicalCameraResults() { + return Collections.unmodifiableMap(mPhysicalCaptureResults); } } diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index f47cd665fd9c193d3a74d2ab7c43cf737142a68a..b205e2c7649ddeeb39a519714c4fa8b19855f467 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -368,7 +368,7 @@ public final class OutputConfiguration implements Parcelable { * desirable for the camera application to request streams from individual physical cameras. * This call achieves it by mapping the OutputConfiguration to the physical camera id.

    * - *

    The valid physical camera id can be queried by {@link + *

    The valid physical camera ids can be queried by {@link * android.hardware.camera2.CameraCharacteristics#getPhysicalCameraIds}. *

    * @@ -576,7 +576,7 @@ public final class OutputConfiguration implements Parcelable { * * @see #enableSurfaceSharing */ - public static int getMaxSharedSurfaceCount() { + public int getMaxSharedSurfaceCount() { return MAX_SURFACES_COUNT; } diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.aidl b/core/java/android/hardware/display/AmbientBrightnessDayStats.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9070777bab63a9ae2d017ed058d0342e55ba2b3f --- /dev/null +++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +parcelable AmbientBrightnessDayStats; diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java new file mode 100644 index 0000000000000000000000000000000000000000..00f3c36d03613391a5b08c3b9c65b7b22f01c4dd --- /dev/null +++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java @@ -0,0 +1,211 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.time.LocalDate; +import java.util.Arrays; + +/** + * AmbientBrightnessDayStats stores and manipulates brightness stats over a single day. + * {@see DisplayManager.getAmbientBrightnessStats()} + * + * @hide + */ +@SystemApi +@TestApi +public final class AmbientBrightnessDayStats implements Parcelable { + + /** The localdate for which brightness stats are being tracked */ + private final LocalDate mLocalDate; + + /** Ambient brightness values for creating bucket boundaries from */ + private final float[] mBucketBoundaries; + + /** Stats of how much time (in seconds) was spent in each of the buckets */ + private final float[] mStats; + + /** + * @hide + */ + public AmbientBrightnessDayStats(@NonNull LocalDate localDate, + @NonNull float[] bucketBoundaries) { + this(localDate, bucketBoundaries, null); + } + + /** + * @hide + */ + public AmbientBrightnessDayStats(@NonNull LocalDate localDate, + @NonNull float[] bucketBoundaries, float[] stats) { + Preconditions.checkNotNull(localDate); + Preconditions.checkNotNull(bucketBoundaries); + Preconditions.checkArrayElementsInRange(bucketBoundaries, 0, Float.MAX_VALUE, + "bucketBoundaries"); + if (bucketBoundaries.length < 1) { + throw new IllegalArgumentException("Bucket boundaries must contain at least 1 value"); + } + checkSorted(bucketBoundaries); + if (stats == null) { + stats = new float[bucketBoundaries.length]; + } else { + Preconditions.checkArrayElementsInRange(stats, 0, Float.MAX_VALUE, "stats"); + if (bucketBoundaries.length != stats.length) { + throw new IllegalArgumentException( + "Bucket boundaries and stats must be of same size."); + } + } + mLocalDate = localDate; + mBucketBoundaries = bucketBoundaries; + mStats = stats; + } + + public LocalDate getLocalDate() { + return mLocalDate; + } + + public float[] getStats() { + return mStats; + } + + public float[] getBucketBoundaries() { + return mBucketBoundaries; + } + + private AmbientBrightnessDayStats(Parcel source) { + mLocalDate = LocalDate.parse(source.readString()); + mBucketBoundaries = source.createFloatArray(); + mStats = source.createFloatArray(); + } + + public static final Creator CREATOR = + new Creator() { + + @Override + public AmbientBrightnessDayStats createFromParcel(Parcel source) { + return new AmbientBrightnessDayStats(source); + } + + @Override + public AmbientBrightnessDayStats[] newArray(int size) { + return new AmbientBrightnessDayStats[size]; + } + }; + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AmbientBrightnessDayStats other = (AmbientBrightnessDayStats) obj; + return mLocalDate.equals(other.mLocalDate) && Arrays.equals(mBucketBoundaries, + other.mBucketBoundaries) && Arrays.equals(mStats, other.mStats); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = result * prime + mLocalDate.hashCode(); + result = result * prime + Arrays.hashCode(mBucketBoundaries); + result = result * prime + Arrays.hashCode(mStats); + return result; + } + + @Override + public String toString() { + StringBuilder bucketBoundariesString = new StringBuilder(); + StringBuilder statsString = new StringBuilder(); + for (int i = 0; i < mBucketBoundaries.length; i++) { + if (i != 0) { + bucketBoundariesString.append(", "); + statsString.append(", "); + } + bucketBoundariesString.append(mBucketBoundaries[i]); + statsString.append(mStats[i]); + } + return new StringBuilder() + .append(mLocalDate).append(" ") + .append("{").append(bucketBoundariesString).append("} ") + .append("{").append(statsString).append("}").toString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mLocalDate.toString()); + dest.writeFloatArray(mBucketBoundaries); + dest.writeFloatArray(mStats); + } + + /** @hide */ + public void log(float ambientBrightness, float durationSec) { + int bucketIndex = getBucketIndex(ambientBrightness); + if (bucketIndex >= 0) { + mStats[bucketIndex] += durationSec; + } + } + + private int getBucketIndex(float ambientBrightness) { + if (ambientBrightness < mBucketBoundaries[0]) { + return -1; + } + int low = 0; + int high = mBucketBoundaries.length - 1; + while (low < high) { + int mid = (low + high) / 2; + if (mBucketBoundaries[mid] <= ambientBrightness + && ambientBrightness < mBucketBoundaries[mid + 1]) { + return mid; + } else if (mBucketBoundaries[mid] < ambientBrightness) { + low = mid + 1; + } else if (mBucketBoundaries[mid] > ambientBrightness) { + high = mid - 1; + } + } + return low; + } + + private static void checkSorted(float[] values) { + if (values.length <= 1) { + return; + } + float prevValue = values[0]; + for (int i = 1; i < values.length; i++) { + Preconditions.checkState(prevValue < values[i]); + prevValue = values[i]; + } + return; + } +} diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java index 2301824cb9dc1aee110766a3e26546d3c12790b2..02eb28ceb4b97f73354f30fc469213f5d488c15f 100644 --- a/core/java/android/hardware/display/BrightnessChangeEvent.java +++ b/core/java/android/hardware/display/BrightnessChangeEvent.java @@ -54,19 +54,30 @@ public final class BrightnessChangeEvent implements Parcelable { /** Most recent battery level when brightness was changed or Float.NaN */ public final float batteryLevel; + /** Factor applied to brightness due to battery level, 0.0-1.0 */ + public final float powerBrightnessFactor; + /** Color filter active to provide night mode */ public final boolean nightMode; /** If night mode color filter is active this will be the temperature in kelvin */ public final int colorTemperature; - /** Brightness le vel before slider adjustment */ + /** Brightness level before slider adjustment */ public final float lastBrightness; + /** Whether brightness configuration is default version */ + public final boolean isDefaultBrightnessConfig; + + /** Whether brightness curve includes a user brightness point */ + public final boolean isUserSetBrightness; + + /** @hide */ private BrightnessChangeEvent(float brightness, long timeStamp, String packageName, int userId, float[] luxValues, long[] luxTimestamps, float batteryLevel, - boolean nightMode, int colorTemperature, float lastBrightness) { + float powerBrightnessFactor, boolean nightMode, int colorTemperature, + float lastBrightness, boolean isDefaultBrightnessConfig, boolean isUserSetBrightness) { this.brightness = brightness; this.timeStamp = timeStamp; this.packageName = packageName; @@ -74,9 +85,12 @@ public final class BrightnessChangeEvent implements Parcelable { this.luxValues = luxValues; this.luxTimestamps = luxTimestamps; this.batteryLevel = batteryLevel; + this.powerBrightnessFactor = powerBrightnessFactor; this.nightMode = nightMode; this.colorTemperature = colorTemperature; this.lastBrightness = lastBrightness; + this.isDefaultBrightnessConfig = isDefaultBrightnessConfig; + this.isUserSetBrightness = isUserSetBrightness; } /** @hide */ @@ -88,9 +102,12 @@ public final class BrightnessChangeEvent implements Parcelable { this.luxValues = other.luxValues; this.luxTimestamps = other.luxTimestamps; this.batteryLevel = other.batteryLevel; + this.powerBrightnessFactor = other.powerBrightnessFactor; this.nightMode = other.nightMode; this.colorTemperature = other.colorTemperature; this.lastBrightness = other.lastBrightness; + this.isDefaultBrightnessConfig = other.isDefaultBrightnessConfig; + this.isUserSetBrightness = other.isUserSetBrightness; } private BrightnessChangeEvent(Parcel source) { @@ -101,9 +118,12 @@ public final class BrightnessChangeEvent implements Parcelable { luxValues = source.createFloatArray(); luxTimestamps = source.createLongArray(); batteryLevel = source.readFloat(); + powerBrightnessFactor = source.readFloat(); nightMode = source.readBoolean(); colorTemperature = source.readInt(); lastBrightness = source.readFloat(); + isDefaultBrightnessConfig = source.readBoolean(); + isUserSetBrightness = source.readBoolean(); } public static final Creator CREATOR = @@ -130,9 +150,12 @@ public final class BrightnessChangeEvent implements Parcelable { dest.writeFloatArray(luxValues); dest.writeLongArray(luxTimestamps); dest.writeFloat(batteryLevel); + dest.writeFloat(powerBrightnessFactor); dest.writeBoolean(nightMode); dest.writeInt(colorTemperature); dest.writeFloat(lastBrightness); + dest.writeBoolean(isDefaultBrightnessConfig); + dest.writeBoolean(isUserSetBrightness); } /** @hide */ @@ -144,9 +167,12 @@ public final class BrightnessChangeEvent implements Parcelable { private float[] mLuxValues; private long[] mLuxTimestamps; private float mBatteryLevel; + private float mPowerBrightnessFactor; private boolean mNightMode; private int mColorTemperature; private float mLastBrightness; + private boolean mIsDefaultBrightnessConfig; + private boolean mIsUserSetBrightness; /** {@see BrightnessChangeEvent#brightness} */ public Builder setBrightness(float brightness) { @@ -190,6 +216,12 @@ public final class BrightnessChangeEvent implements Parcelable { return this; } + /** {@see BrightnessChangeEvent#powerSaveBrightness} */ + public Builder setPowerBrightnessFactor(float powerBrightnessFactor) { + mPowerBrightnessFactor = powerBrightnessFactor; + return this; + } + /** {@see BrightnessChangeEvent#nightMode} */ public Builder setNightMode(boolean nightMode) { mNightMode = nightMode; @@ -208,11 +240,24 @@ public final class BrightnessChangeEvent implements Parcelable { return this; } + /** {@see BrightnessChangeEvent#isDefaultBrightnessConfig} */ + public Builder setIsDefaultBrightnessConfig(boolean isDefaultBrightnessConfig) { + mIsDefaultBrightnessConfig = isDefaultBrightnessConfig; + return this; + } + + /** {@see BrightnessChangeEvent#userBrightnessPoint} */ + public Builder setUserBrightnessPoint(boolean isUserSetBrightness) { + mIsUserSetBrightness = isUserSetBrightness; + return this; + } + /** Builds a BrightnessChangeEvent */ public BrightnessChangeEvent build() { return new BrightnessChangeEvent(mBrightness, mTimeStamp, mPackageName, mUserId, mLuxValues, mLuxTimestamps, mBatteryLevel, - mNightMode, mColorTemperature, mLastBrightness); + mPowerBrightnessFactor, mNightMode, mColorTemperature, mLastBrightness, + mIsDefaultBrightnessConfig, mIsUserSetBrightness); } } } diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 4de4880b7c171f194f51678715b7a12d92c07926..6b2059e1c84c74fb091b7b9d43265501d03eacdd 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -630,6 +630,16 @@ public final class DisplayManager { return mGlobal.getBrightnessEvents(mContext.getOpPackageName()); } + /** + * Fetch {@link AmbientBrightnessDayStats}s. + * + * @hide until we make it a system api + */ + @RequiresPermission(Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS) + public List getAmbientBrightnessStats() { + return mGlobal.getAmbientBrightnessStats(); + } + /** * Sets the global display brightness configuration. * @@ -639,7 +649,7 @@ public final class DisplayManager { @TestApi @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public void setBrightnessConfiguration(BrightnessConfiguration c) { - setBrightnessConfigurationForUser(c, UserHandle.myUserId(), mContext.getPackageName()); + setBrightnessConfigurationForUser(c, mContext.getUserId(), mContext.getPackageName()); } /** diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 2d5f5e04148685c6aafaaf995144506e7b5d458b..d7f7c865b8fb941b77d384062544b3c372336cc0 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -525,6 +525,21 @@ public final class DisplayManagerGlobal { } } + /** + * Retrieves ambient brightness stats. + */ + public List getAmbientBrightnessStats() { + try { + ParceledListSlice stats = mDm.getAmbientBrightnessStats(); + if (stats == null) { + return Collections.emptyList(); + } + return stats.getList(); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { @Override public void onDisplayEvent(int displayId, int event) { diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 1cfad4f0168f42e453991c45326e6749c1180f15..f468942cc95138ea7a1a780d74ec9533c1f908bc 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -174,9 +174,9 @@ public abstract class DisplayManagerInternal { public abstract boolean isUidPresentOnDisplay(int uid, int displayId); /** - * Persist brightness slider events. + * Persist brightness slider events and ambient brightness stats. */ - public abstract void persistBrightnessSliderEvents(); + public abstract void persistBrightnessTrackerState(); /** * Notifies the display manager that resource overlays have changed. diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 13599cfa0b7d58495b3e9b53220727ab5aaed3d9..0571ae1fe82564b44fe4e7a6e3b89328bb1916b6 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -87,6 +87,9 @@ interface IDisplayManager { // Requires BRIGHTNESS_SLIDER_USAGE permission. ParceledListSlice getBrightnessEvents(String callingPackage); + // Requires ACCESS_AMBIENT_LIGHT_STATS permission. + ParceledListSlice getAmbientBrightnessStats(); + // Sets the global brightness configuration for a given user. Requires // CONFIGURE_DISPLAY_BRIGHTNESS, and INTERACT_ACROSS_USER if the user being configured is not // the same as the calling user. diff --git a/core/java/android/hardware/fingerprint/Fingerprint.java b/core/java/android/hardware/fingerprint/Fingerprint.java index c30763475fa82275d16f12a60c908adb13189dff..c7ce8fad254351c608a1096c9349306f83055f45 100644 --- a/core/java/android/hardware/fingerprint/Fingerprint.java +++ b/core/java/android/hardware/fingerprint/Fingerprint.java @@ -15,6 +15,7 @@ */ package android.hardware.fingerprint; +import android.hardware.biometrics.BiometricAuthenticator; import android.os.Parcel; import android.os.Parcelable; @@ -22,7 +23,7 @@ import android.os.Parcelable; * Container for fingerprint metadata. * @hide */ -public final class Fingerprint implements Parcelable { +public final class Fingerprint extends BiometricAuthenticator.BiometricIdentifier { private CharSequence mName; private int mGroupId; private int mFingerId; diff --git a/core/java/android/hardware/fingerprint/FingerprintDialog.java b/core/java/android/hardware/fingerprint/FingerprintDialog.java index 6b7fab773b43ab30f4faa571b1653e97d823689b..49835963a3b1c62e36a4b23890e9f1634839a289 100644 --- a/core/java/android/hardware/fingerprint/FingerprintDialog.java +++ b/core/java/android/hardware/fingerprint/FingerprintDialog.java @@ -23,19 +23,25 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.content.Context; import android.content.DialogInterface; -import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; -import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; +import android.content.pm.PackageManager; +import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.BiometricFingerprintConstants; +import android.hardware.biometrics.CryptoObject; import android.hardware.fingerprint.IFingerprintDialogReceiver; import android.os.Bundle; import android.os.CancellationSignal; import android.text.TextUtils; +import java.security.Signature; import java.util.concurrent.Executor; +import javax.crypto.Cipher; +import javax.crypto.Mac; + /** * A class that manages a system-provided fingerprint dialog. */ -public class FingerprintDialog { +public class FingerprintDialog implements BiometricAuthenticator, BiometricFingerprintConstants { /** * @hide @@ -200,6 +206,7 @@ public class FingerprintDialog { } } + private PackageManager mPackageManager; private FingerprintManager mFingerprintManager; private Bundle mBundle; private ButtonInfo mPositiveButtonInfo; @@ -227,37 +234,209 @@ public class FingerprintDialog { mPositiveButtonInfo = positiveButtonInfo; mNegativeButtonInfo = negativeButtonInfo; mFingerprintManager = context.getSystemService(FingerprintManager.class); + mPackageManager = context.getPackageManager(); + } + + /** + * A wrapper class for the crypto objects supported by FingerprintManager. Currently the + * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. + */ + public static final class CryptoObject extends android.hardware.biometrics.CryptoObject { + public CryptoObject(@NonNull Signature signature) { + super(signature); + } + + public CryptoObject(@NonNull Cipher cipher) { + super(cipher); + } + + public CryptoObject(@NonNull Mac mac) { + super(mac); + } + + /** + * Get {@link Signature} object. + * @return {@link Signature} object or null if this doesn't contain one. + */ + public Signature getSignature() { + return super.getSignature(); + } + + /** + * Get {@link Cipher} object. + * @return {@link Cipher} object or null if this doesn't contain one. + */ + public Cipher getCipher() { + return super.getCipher(); + } + + /** + * Get {@link Mac} object. + * @return {@link Mac} object or null if this doesn't contain one. + */ + public Mac getMac() { + return super.getMac(); + } + } + + /** + * Container for callback data from {@link #authenticate( + * CancellationSignal, Executor, AuthenticationCallback)} and + * {@link #authenticate(CryptoObject, CancellationSignal, Executor, + * AuthenticationCallback)} + */ + public static class AuthenticationResult extends BiometricAuthenticator.AuthenticationResult { + /** + * Authentication result + * @param crypto + * @param identifier + * @param userId + * @hide + */ + public AuthenticationResult(CryptoObject crypto, BiometricIdentifier identifier, + int userId) { + super(crypto, identifier, userId); + } + /** + * Obtain the crypto object associated with this transaction + * @return crypto object provided to {@link #authenticate( + * CryptoObject, CancellationSignal, Executor, AuthenticationCallback)} + */ + public CryptoObject getCryptoObject() { + return (CryptoObject) super.getCryptoObject(); + } + } + + /** + * Callback structure provided to {@link FingerprintDialog#authenticate(CancellationSignal, + * Executor, AuthenticationCallback)} or {@link FingerprintDialog#authenticate(CryptoObject, + * CancellationSignal, Executor, AuthenticationCallback)}. Users must provide an implementation + * of this for listening to authentication events. + */ + public static abstract class AuthenticationCallback extends + BiometricAuthenticator.AuthenticationCallback { + /** + * Called when an unrecoverable error has been encountered and the operation is complete. + * No further actions will be made on this object. + * @param errorCode An integer identifying the error message + * @param errString A human-readable error string that can be shown on an UI + */ + @Override + public void onAuthenticationError(int errorCode, CharSequence errString) {} + + /** + * Called when a recoverable error has been encountered during authentication. The help + * string is provided to give the user guidance for what went wrong, such as "Sensor dirty, + * please clean it." + * @param helpCode An integer identifying the error message + * @param helpString A human-readable string that can be shown on an UI + */ + @Override + public void onAuthenticationHelp(int helpCode, CharSequence helpString) {} + + /** + * Called when a biometric is recognized. + * @param result An object containing authentication-related data + */ + public void onAuthenticationSucceeded(AuthenticationResult result) {} + + /** + * Called when a biometric is valid but not recognized. + */ + @Override + public void onAuthenticationFailed() {} + + /** + * Called when a biometric has been acquired, but hasn't been processed yet. + * @hide + */ + @Override + public void onAuthenticationAcquired(int acquireInfo) {} + + /** + * @param result An object containing authentication-related data + * @hide + */ + @Override + public void onAuthenticationSucceeded(BiometricAuthenticator.AuthenticationResult result) { + onAuthenticationSucceeded(new AuthenticationResult( + (CryptoObject) result.getCryptoObject(), + result.getId(), + result.getUserId())); + } + } + + + /** + * @param crypto Object associated with the call + * @param cancel An object that can be used to cancel authentication + * @param executor An executor to handle callback events + * @param callback An object to receive authentication events + * @hide + */ + @Override + public void authenticate(@NonNull android.hardware.biometrics.CryptoObject crypto, + @NonNull CancellationSignal cancel, + @NonNull @CallbackExecutor Executor executor, + @NonNull BiometricAuthenticator.AuthenticationCallback callback) { + if (!(callback instanceof FingerprintDialog.AuthenticationCallback)) { + throw new IllegalArgumentException("Callback cannot be casted"); + } + authenticate(crypto, cancel, executor, (AuthenticationCallback) callback); } + /** + * + * @param cancel An object that can be used to cancel authentication + * @param executor An executor to handle callback events + * @param callback An object to receive authentication events + * @hide + */ + @Override + public void authenticate(@NonNull CancellationSignal cancel, + @NonNull @CallbackExecutor Executor executor, + @NonNull BiometricAuthenticator.AuthenticationCallback callback) { + if (!(callback instanceof FingerprintDialog.AuthenticationCallback)) { + throw new IllegalArgumentException("Callback cannot be casted"); + } + authenticate(cancel, executor, (AuthenticationCallback) callback); + } + + /** * This call warms up the fingerprint hardware, displays a system-provided dialog, * and starts scanning for a fingerprint. It terminates when - * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when - * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, - * when {@link AuthenticationCallback#onAuthenticationFailed()} is called or when the user - * dismisses the system-provided dialog, at which point the crypto object becomes invalid. - * This operation can be canceled by using the provided cancel object. The application will - * receive authentication errors through {@link AuthenticationCallback}, and button events - * through the corresponding callback set in - * {@link Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}. - * It is safe to reuse the {@link FingerprintDialog} object, and calling - * {@link FingerprintDialog#authenticate(CancellationSignal, Executor, AuthenticationCallback)} - * while an existing authentication attempt is occurring will stop the previous client and - * start a new authentication. The interrupted client will receive a cancelled notification - * through {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}. + * {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)} is called, when + * {@link AuthenticationCallback#onAuthenticationSucceeded( + * AuthenticationResult)}, or when the user dismisses the system-provided dialog, at which point + * the crypto object becomes invalid. This operation can be canceled by using the provided + * cancel object. The application will receive authentication errors through + * {@link AuthenticationCallback}, and button events through the + * corresponding callback set in {@link Builder#setNegativeButton(CharSequence, + * Executor, DialogInterface.OnClickListener)}. It is safe to reuse the + * {@link FingerprintDialog} object, and calling {@link FingerprintDialog#authenticate( + * CancellationSignal, Executor, AuthenticationCallback)} while an + * existing authentication attempt is occurring will stop the previous client and start a + * new authentication. The interrupted client will receive a cancelled notification through + * {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)}. * - * @throws IllegalArgumentException if any of the arguments are null + * @throws IllegalArgumentException If any of the arguments are null * - * @param crypto object associated with the call - * @param cancel an object that can be used to cancel authentication - * @param executor an executor to handle callback events - * @param callback an object to receive authentication events + * @param crypto Object associated with the call + * @param cancel An object that can be used to cancel authentication + * @param executor An executor to handle callback events + * @param callback An object to receive authentication events */ @RequiresPermission(USE_FINGERPRINT) - public void authenticate(@NonNull FingerprintManager.CryptoObject crypto, + public void authenticate(@NonNull CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, - @NonNull FingerprintManager.AuthenticationCallback callback) { + @NonNull AuthenticationCallback callback) { + if (handlePreAuthenticationErrors(callback, executor)) { + return; + } mFingerprintManager.authenticate(crypto, cancel, mBundle, executor, mDialogReceiver, callback); } @@ -265,29 +444,57 @@ public class FingerprintDialog { /** * This call warms up the fingerprint hardware, displays a system-provided dialog, * and starts scanning for a fingerprint. It terminates when - * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when - * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, - * when {@link AuthenticationCallback#onAuthenticationFailed()} is called or when the user - * dismisses the system-provided dialog. This operation can be canceled by using the provided - * cancel object. The application will receive authentication errors through - * {@link AuthenticationCallback}, and button events through the corresponding callback set in + * {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)} is called, when + * {@link AuthenticationCallback#onAuthenticationSucceeded( + * AuthenticationResult)} is called, or when the user dismisses the system-provided dialog. + * This operation can be canceled by using the provided cancel object. The application will + * receive authentication errors through {@link AuthenticationCallback}, + * and button events through the corresponding callback set in * {@link Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}. * It is safe to reuse the {@link FingerprintDialog} object, and calling - * {@link FingerprintDialog#authenticate(CancellationSignal, Executor, AuthenticationCallback)} - * while an existing authentication attempt is occurring will stop the previous client and - * start a new authentication. The interrupted client will receive a cancelled notification - * through {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}. + * {@link FingerprintDialog#authenticate(CancellationSignal, Executor, + * AuthenticationCallback)} while an existing authentication attempt is + * occurring will stop the previous client and start a new authentication. The interrupted + * client will receive a cancelled notification through + * {@link AuthenticationCallback#onAuthenticationError(int, + * CharSequence)}. * - * @throws IllegalArgumentException if any of the arguments are null + * @throws IllegalArgumentException If any of the arguments are null * - * @param cancel an object that can be used to cancel authentication - * @param executor an executor to handle callback events - * @param callback an object to receive authentication events + * @param cancel An object that can be used to cancel authentication + * @param executor An executor to handle callback events + * @param callback An object to receive authentication events */ @RequiresPermission(USE_FINGERPRINT) public void authenticate(@NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, - @NonNull FingerprintManager.AuthenticationCallback callback) { + @NonNull AuthenticationCallback callback) { + if (handlePreAuthenticationErrors(callback, executor)) { + return; + } mFingerprintManager.authenticate(cancel, mBundle, executor, mDialogReceiver, callback); } + + private boolean handlePreAuthenticationErrors(AuthenticationCallback callback, + Executor executor) { + if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { + sendError(FINGERPRINT_ERROR_HW_NOT_PRESENT, callback, executor); + return true; + } else if (!mFingerprintManager.isHardwareDetected()) { + sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, callback, executor); + return true; + } else if (!mFingerprintManager.hasEnrolledFingerprints()) { + sendError(FINGERPRINT_ERROR_NO_FINGERPRINTS, callback, executor); + return true; + } + return false; + } + + private void sendError(int error, AuthenticationCallback callback, Executor executor) { + executor.execute(() -> { + callback.onAuthenticationError(error, mFingerprintManager.getErrorString( + error, 0 /* vendorCode */)); + }); + } } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 62d92c4ac385cc0ea4bd4faea21caa397324d6a2..92d6bbb0a20fe06cf824d6709edc613b829779af 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -27,6 +27,8 @@ import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.app.ActivityManager; import android.content.Context; +import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.BiometricFingerprintConstants; import android.os.Binder; import android.os.Bundle; import android.os.CancellationSignal; @@ -38,7 +40,6 @@ import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; -import android.security.keystore.AndroidKeyStoreProvider; import android.util.Log; import android.util.Slog; @@ -51,9 +52,14 @@ import javax.crypto.Mac; /** * A class that coordinates access to the fingerprint hardware. + * @deprecated See {@link FingerprintDialog} which shows a system-provided dialog upon starting + * authentication. In a world where devices may have in-display fingerprint sensors, it's much + * more realistic to have a system-provided authentication dialog since the in-display sensor + * location may vary by vendor/device. */ +@Deprecated @SystemService(Context.FINGERPRINT_SERVICE) -public class FingerprintManager { +public class FingerprintManager implements BiometricFingerprintConstants { private static final String TAG = "FingerprintManager"; private static final boolean DEBUG = true; private static final int MSG_ENROLL_RESULT = 100; @@ -64,147 +70,14 @@ public class FingerprintManager { private static final int MSG_REMOVED = 105; private static final int MSG_ENUMERATED = 106; - // - // Error messages from fingerprint hardware during initilization, enrollment, authentication or - // removal. Must agree with the list in fingerprint.h - // - - /** - * The hardware is unavailable. Try again later. - */ - public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; - - /** - * Error state returned when the sensor was unable to process the current image. - */ - public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; - - /** - * Error state returned when the current request has been running too long. This is intended to - * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is - * platform and sensor-specific, but is generally on the order of 30 seconds. - */ - public static final int FINGERPRINT_ERROR_TIMEOUT = 3; - - /** - * Error state returned for operations like enrollment; the operation cannot be completed - * because there's not enough storage remaining to complete the operation. - */ - public static final int FINGERPRINT_ERROR_NO_SPACE = 4; - - /** - * The operation was canceled because the fingerprint sensor is unavailable. For example, - * this may happen when the user is switched, the device is locked or another pending operation - * prevents or disables it. - */ - public static final int FINGERPRINT_ERROR_CANCELED = 5; - - /** - * The {@link FingerprintManager#remove} call failed. Typically this will happen when the - * provided fingerprint id was incorrect. - * - * @hide - */ - public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; - - /** - * The operation was canceled because the API is locked out due to too many attempts. - * This occurs after 5 failed attempts, and lasts for 30 seconds. - */ - public static final int FINGERPRINT_ERROR_LOCKOUT = 7; - - /** - * Hardware vendors may extend this list if there are conditions that do not fall under one of - * the above categories. Vendors are responsible for providing error strings for these errors. - * These messages are typically reserved for internal operations such as enrollment, but may be - * used to express vendor errors not covered by the ones in fingerprint.h. Applications are - * expected to show the error message string if they happen, but are advised not to rely on the - * message id since they will be device and vendor-specific - */ - public static final int FINGERPRINT_ERROR_VENDOR = 8; - - /** - * The operation was canceled because FINGERPRINT_ERROR_LOCKOUT occurred too many times. - * Fingerprint authentication is disabled until the user unlocks with strong authentication - * (PIN/Pattern/Password) - */ - public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; - - /** - * The user canceled the operation. Upon receiving this, applications should use alternate - * authentication (e.g. a password). The application should also provide the means to return - * to fingerprint authentication, such as a "use fingerprint" button. - */ - public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; - - /** - * @hide - */ - public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; - - // - // Image acquisition messages. Must agree with those in fingerprint.h - // - - /** - * The image acquired was good. - */ - public static final int FINGERPRINT_ACQUIRED_GOOD = 0; - - /** - * Only a partial fingerprint image was detected. During enrollment, the user should be - * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor." - */ - public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; - - /** - * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or - * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}). - */ - public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; - - /** - * The fingerprint image was too noisy due to suspected or detected dirt on the sensor. - * For example, it's reasonable return this after multiple - * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor - * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor - * when this is returned. - */ - public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; - - /** - * The fingerprint image was unreadable due to lack of motion. This is most appropriate for - * linear array sensors that require a swipe motion. - */ - public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; - - /** - * The fingerprint image was incomplete due to quick motion. While mostly appropriate for - * linear array sensors, this could also happen if the finger was moved during acquisition. - * The user should be asked to move the finger slower (linear) or leave the finger on the sensor - * longer. - */ - public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; - - /** - * Hardware vendors may extend this list if there are conditions that do not fall under one of - * the above categories. Vendors are responsible for providing error strings for these errors. - * @hide - */ - public static final int FINGERPRINT_ACQUIRED_VENDOR = 6; - /** - * @hide - */ - public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; - private IFingerprintService mService; private Context mContext; private IBinder mToken = new Binder(); - private AuthenticationCallback mAuthenticationCallback; + private BiometricAuthenticator.AuthenticationCallback mAuthenticationCallback; private EnrollmentCallback mEnrollmentCallback; private RemovalCallback mRemovalCallback; private EnumerateCallback mEnumerateCallback; - private CryptoObject mCryptoObject; + private android.hardware.biometrics.CryptoObject mCryptoObject; private Fingerprint mRemovalFingerprint; private Handler mHandler; private Executor mExecutor; @@ -217,9 +90,9 @@ public class FingerprintManager { } private class OnAuthenticationCancelListener implements OnCancelListener { - private CryptoObject mCrypto; + private android.hardware.biometrics.CryptoObject mCrypto; - public OnAuthenticationCancelListener(CryptoObject crypto) { + public OnAuthenticationCancelListener(android.hardware.biometrics.CryptoObject crypto) { mCrypto = crypto; } @@ -233,18 +106,17 @@ public class FingerprintManager { * A wrapper class for the crypto objects supported by FingerprintManager. Currently the * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. */ - public static final class CryptoObject { - + public static final class CryptoObject extends android.hardware.biometrics.CryptoObject { public CryptoObject(@NonNull Signature signature) { - mCrypto = signature; + super(signature); } public CryptoObject(@NonNull Cipher cipher) { - mCrypto = cipher; + super(cipher); } public CryptoObject(@NonNull Mac mac) { - mCrypto = mac; + super(mac); } /** @@ -252,7 +124,7 @@ public class FingerprintManager { * @return {@link Signature} object or null if this doesn't contain one. */ public Signature getSignature() { - return mCrypto instanceof Signature ? (Signature) mCrypto : null; + return super.getSignature(); } /** @@ -260,7 +132,7 @@ public class FingerprintManager { * @return {@link Cipher} object or null if this doesn't contain one. */ public Cipher getCipher() { - return mCrypto instanceof Cipher ? (Cipher) mCrypto : null; + return super.getCipher(); } /** @@ -268,20 +140,9 @@ public class FingerprintManager { * @return {@link Mac} object or null if this doesn't contain one. */ public Mac getMac() { - return mCrypto instanceof Mac ? (Mac) mCrypto : null; + return super.getMac(); } - - /** - * @hide - * @return the opId associated with this object or 0 if none - */ - public long getOpId() { - return mCrypto != null ? - AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0; - } - - private final Object mCrypto; - }; + } /** * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, @@ -334,13 +195,15 @@ public class FingerprintManager { * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to * fingerprint events. */ - public static abstract class AuthenticationCallback { + public static abstract class AuthenticationCallback + extends BiometricAuthenticator.AuthenticationCallback { /** * Called when an unrecoverable error has been encountered and the operation is complete. * No further callbacks will be made on this object. * @param errorCode An integer identifying the error message * @param errString A human-readable error string that can be shown in UI */ + @Override public void onAuthenticationError(int errorCode, CharSequence errString) { } /** @@ -350,6 +213,7 @@ public class FingerprintManager { * @param helpCode An integer identifying the error message * @param helpString A human-readable string that can be shown in UI */ + @Override public void onAuthenticationHelp(int helpCode, CharSequence helpString) { } /** @@ -361,6 +225,7 @@ public class FingerprintManager { /** * Called when a fingerprint is valid but not recognized. */ + @Override public void onAuthenticationFailed() { } /** @@ -369,7 +234,19 @@ public class FingerprintManager { * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants * @hide */ + @Override public void onAuthenticationAcquired(int acquireInfo) {} + + /** + * @hide + * @param result + */ + @Override + public void onAuthenticationSucceeded(BiometricAuthenticator.AuthenticationResult result) { + onAuthenticationSucceeded(new AuthenticationResult( + (CryptoObject) result.getCryptoObject(), + (Fingerprint) result.getId(), result.getUserId())); + } }; /** @@ -489,11 +366,16 @@ public class FingerprintManager { * by Android Keystore * facility. * @throws IllegalStateException if the crypto primitive is not initialized. + * @deprecated See {@link FingerprintDialog#authenticate(CancellationSignal, Executor, + * FingerprintDialog.AuthenticationCallback)} and {@link FingerprintDialog#authenticate( + * FingerprintDialog.CryptoObject, CancellationSignal, Executor, + * FingerprintDialog.AuthenticationCallback)} */ + @Deprecated @RequiresPermission(USE_FINGERPRINT) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { - authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId()); + authenticate(crypto, cancel, flags, callback, handler, mContext.getUserId()); } /** @@ -554,12 +436,12 @@ public class FingerprintManager { * @param userId the user ID that the fingerprint hardware will authenticate for. */ private void authenticate(int userId, - @Nullable CryptoObject crypto, + @Nullable android.hardware.biometrics.CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Bundle bundle, @NonNull @CallbackExecutor Executor executor, @NonNull IFingerprintDialogReceiver receiver, - @NonNull AuthenticationCallback callback) { + @NonNull BiometricAuthenticator.AuthenticationCallback callback) { mCryptoObject = crypto; if (cancel.isCanceled()) { Log.w(TAG, "authentication already canceled"); @@ -598,7 +480,7 @@ public class FingerprintManager { @NonNull Bundle bundle, @NonNull @CallbackExecutor Executor executor, @NonNull IFingerprintDialogReceiver receiver, - @NonNull AuthenticationCallback callback) { + @NonNull BiometricAuthenticator.AuthenticationCallback callback) { if (cancel == null) { throw new IllegalArgumentException("Must supply a cancellation signal"); } @@ -614,7 +496,7 @@ public class FingerprintManager { if (callback == null) { throw new IllegalArgumentException("Must supply a calback"); } - authenticate(UserHandle.myUserId(), null, cancel, bundle, executor, receiver, callback); + authenticate(mContext.getUserId(), null, cancel, bundle, executor, receiver, callback); } /** @@ -626,12 +508,12 @@ public class FingerprintManager { * @param callback * @hide */ - public void authenticate(@NonNull CryptoObject crypto, + public void authenticate(@NonNull android.hardware.biometrics.CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull Bundle bundle, @NonNull @CallbackExecutor Executor executor, @NonNull IFingerprintDialogReceiver receiver, - @NonNull AuthenticationCallback callback) { + @NonNull BiometricAuthenticator.AuthenticationCallback callback) { if (crypto == null) { throw new IllegalArgumentException("Must supply a crypto object"); } @@ -648,9 +530,10 @@ public class FingerprintManager { throw new IllegalArgumentException("Must supply a receiver"); } if (callback == null) { - throw new IllegalArgumentException("Must supply a calback"); + throw new IllegalArgumentException("Must supply a callback"); } - authenticate(UserHandle.myUserId(), crypto, cancel, bundle, executor, receiver, callback); + authenticate(mContext.getUserId(), crypto, cancel, + bundle, executor, receiver, callback); } /** @@ -841,19 +724,22 @@ public class FingerprintManager { */ @RequiresPermission(USE_FINGERPRINT) public List getEnrolledFingerprints() { - return getEnrolledFingerprints(UserHandle.myUserId()); + return getEnrolledFingerprints(mContext.getUserId()); } /** * Determine if there is at least one fingerprint enrolled. * * @return true if at least one fingerprint is enrolled, false otherwise + * @deprecated See {@link FingerprintDialog} and + * {@link FingerprintDialog#FINGERPRINT_ERROR_NO_FINGERPRINTS} */ + @Deprecated @RequiresPermission(USE_FINGERPRINT) public boolean hasEnrolledFingerprints() { if (mService != null) try { return mService.hasEnrolledFingerprints( - UserHandle.myUserId(), mContext.getOpPackageName()); + mContext.getUserId(), mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -879,7 +765,10 @@ public class FingerprintManager { * Determine if fingerprint hardware is present and functional. * * @return true if hardware is present and functional, false otherwise. + * @deprecated See {@link FingerprintDialog} and + * {@link FingerprintDialog#FINGERPRINT_ERROR_HW_UNAVAILABLE} */ + @Deprecated @RequiresPermission(USE_FINGERPRINT) public boolean isHardwareDetected() { if (mService != null) { @@ -1049,8 +938,8 @@ public class FingerprintManager { private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) { if (mAuthenticationCallback != null) { - final AuthenticationResult result = - new AuthenticationResult(mCryptoObject, fp, userId); + final BiometricAuthenticator.AuthenticationResult result = + new BiometricAuthenticator.AuthenticationResult(mCryptoObject, fp, userId); mAuthenticationCallback.onAuthenticationSucceeded(result); } } @@ -1126,7 +1015,7 @@ public class FingerprintManager { } } - private void cancelAuthentication(CryptoObject cryptoObject) { + private void cancelAuthentication(android.hardware.biometrics.CryptoObject cryptoObject) { if (mService != null) try { mService.cancelAuthentication(mToken, mContext.getOpPackageName()); } catch (RemoteException e) { @@ -1160,6 +1049,12 @@ public class FingerprintManager { case FINGERPRINT_ERROR_USER_CANCELED: return mContext.getString( com.android.internal.R.string.fingerprint_error_user_canceled); + case FINGERPRINT_ERROR_NO_FINGERPRINTS: + return mContext.getString( + com.android.internal.R.string.fingerprint_error_no_fingerprints); + case FINGERPRINT_ERROR_HW_NOT_PRESENT: + return mContext.getString( + com.android.internal.R.string.fingerprint_error_hw_not_present); case FINGERPRINT_ERROR_VENDOR: { String[] msgArray = mContext.getResources().getStringArray( com.android.internal.R.array.fingerprint_error_vendor); diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java index b00f6033976e1b75996b53c9359255f2cafe8511..e1d7edfa7d9c2d609d8ee0a74de60d13cef09fcd 100644 --- a/core/java/android/hardware/radio/RadioManager.java +++ b/core/java/android/hardware/radio/RadioManager.java @@ -213,6 +213,7 @@ public class RadioManager { private final boolean mIsBgScanSupported; private final Set mSupportedProgramTypes; private final Set mSupportedIdentifierTypes; + @Nullable private final Map mDabFrequencyTable; @NonNull private final Map mVendorInfo; /** @hide */ @@ -221,6 +222,7 @@ public class RadioManager { boolean isCaptureSupported, BandDescriptor[] bands, boolean isBgScanSupported, @ProgramSelector.ProgramType int[] supportedProgramTypes, @ProgramSelector.IdentifierType int[] supportedIdentifierTypes, + @Nullable Map dabFrequencyTable, Map vendorInfo) { mId = id; mServiceName = TextUtils.isEmpty(serviceName) ? "default" : serviceName; @@ -236,6 +238,13 @@ public class RadioManager { mIsBgScanSupported = isBgScanSupported; mSupportedProgramTypes = arrayToSet(supportedProgramTypes); mSupportedIdentifierTypes = arrayToSet(supportedIdentifierTypes); + if (dabFrequencyTable != null) { + for (Map.Entry entry : dabFrequencyTable.entrySet()) { + Objects.requireNonNull(entry.getKey()); + Objects.requireNonNull(entry.getValue()); + } + } + mDabFrequencyTable = dabFrequencyTable; mVendorInfo = (vendorInfo == null) ? new HashMap<>() : vendorInfo; } @@ -362,6 +371,19 @@ public class RadioManager { return mSupportedIdentifierTypes.contains(type); } + /** + * A frequency table for Digital Audio Broadcasting (DAB). + * + * The key is a channel name, i.e. 5A, 7B. + * + * The value is a frequency, in kHz. + * + * @return a frequency table, or {@code null} if the module doesn't support DAB + */ + public @Nullable Map getDabFrequencyTable() { + return mDabFrequencyTable; + } + /** * A map of vendor-specific opaque strings, passed from HAL without changes. * Format of these strings can vary across vendors. @@ -403,6 +425,7 @@ public class RadioManager { mIsBgScanSupported = in.readInt() == 1; mSupportedProgramTypes = arrayToSet(in.createIntArray()); mSupportedIdentifierTypes = arrayToSet(in.createIntArray()); + mDabFrequencyTable = Utils.readStringIntMap(in); mVendorInfo = Utils.readStringMap(in); } @@ -433,6 +456,7 @@ public class RadioManager { dest.writeInt(mIsBgScanSupported ? 1 : 0); dest.writeIntArray(setToArray(mSupportedProgramTypes)); dest.writeIntArray(setToArray(mSupportedIdentifierTypes)); + Utils.writeStringIntMap(dest, mDabFrequencyTable); Utils.writeStringMap(dest, mVendorInfo); } @@ -456,67 +480,31 @@ public class RadioManager { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + mId; - result = prime * result + mServiceName.hashCode(); - result = prime * result + mClassId; - result = prime * result + ((mImplementor == null) ? 0 : mImplementor.hashCode()); - result = prime * result + ((mProduct == null) ? 0 : mProduct.hashCode()); - result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); - result = prime * result + ((mSerial == null) ? 0 : mSerial.hashCode()); - result = prime * result + mNumTuners; - result = prime * result + mNumAudioSources; - result = prime * result + (mIsCaptureSupported ? 1 : 0); - result = prime * result + Arrays.hashCode(mBands); - result = prime * result + (mIsBgScanSupported ? 1 : 0); - result = prime * result + mVendorInfo.hashCode(); - return result; + return Objects.hash(mId, mServiceName, mClassId, mImplementor, mProduct, mVersion, + mSerial, mNumTuners, mNumAudioSources, mIsCaptureSupported, mBands, + mIsBgScanSupported, mDabFrequencyTable, mVendorInfo); } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof ModuleProperties)) - return false; + if (this == obj) return true; + if (!(obj instanceof ModuleProperties)) return false; ModuleProperties other = (ModuleProperties) obj; - if (mId != other.getId()) - return false; + + if (mId != other.getId()) return false; if (!TextUtils.equals(mServiceName, other.mServiceName)) return false; - if (mClassId != other.getClassId()) - return false; - if (mImplementor == null) { - if (other.getImplementor() != null) - return false; - } else if (!mImplementor.equals(other.getImplementor())) - return false; - if (mProduct == null) { - if (other.getProduct() != null) - return false; - } else if (!mProduct.equals(other.getProduct())) - return false; - if (mVersion == null) { - if (other.getVersion() != null) - return false; - } else if (!mVersion.equals(other.getVersion())) - return false; - if (mSerial == null) { - if (other.getSerial() != null) - return false; - } else if (!mSerial.equals(other.getSerial())) - return false; - if (mNumTuners != other.getNumTuners()) - return false; - if (mNumAudioSources != other.getNumAudioSources()) - return false; - if (mIsCaptureSupported != other.isCaptureSupported()) - return false; - if (!Arrays.equals(mBands, other.getBands())) - return false; - if (mIsBgScanSupported != other.isBackgroundScanningSupported()) - return false; - if (!mVendorInfo.equals(other.mVendorInfo)) return false; + if (mClassId != other.mClassId) return false; + if (!Objects.equals(mImplementor, other.mImplementor)) return false; + if (!Objects.equals(mProduct, other.mProduct)) return false; + if (!Objects.equals(mVersion, other.mVersion)) return false; + if (!Objects.equals(mSerial, other.mSerial)) return false; + if (mNumTuners != other.mNumTuners) return false; + if (mNumAudioSources != other.mNumAudioSources) return false; + if (mIsCaptureSupported != other.mIsCaptureSupported) return false; + if (!Objects.equals(mBands, other.mBands)) return false; + if (mIsBgScanSupported != other.mIsBgScanSupported) return false; + if (!Objects.equals(mDabFrequencyTable, other.mDabFrequencyTable)) return false; + if (!Objects.equals(mVendorInfo, other.mVendorInfo)) return false; return true; } } diff --git a/core/java/android/hardware/radio/Utils.java b/core/java/android/hardware/radio/Utils.java index f1b589746a1464c8f02e1273fd6ccda5e8f66f05..9887f782326986b38c88c66379ad256578e03697 100644 --- a/core/java/android/hardware/radio/Utils.java +++ b/core/java/android/hardware/radio/Utils.java @@ -56,6 +56,29 @@ final class Utils { return map; } + static void writeStringIntMap(@NonNull Parcel dest, @Nullable Map map) { + if (map == null) { + dest.writeInt(0); + return; + } + dest.writeInt(map.size()); + for (Map.Entry entry : map.entrySet()) { + dest.writeString(entry.getKey()); + dest.writeInt(entry.getValue()); + } + } + + static @NonNull Map readStringIntMap(@NonNull Parcel in) { + int size = in.readInt(); + Map map = new HashMap<>(); + while (size-- > 0) { + String key = in.readString(); + int value = in.readInt(); + map.put(key, value); + } + return map; + } + static void writeSet(@NonNull Parcel dest, @Nullable Set set) { if (set == null) { dest.writeInt(0); diff --git a/core/java/android/hardware/usb/AccessoryFilter.java b/core/java/android/hardware/usb/AccessoryFilter.java index d9b7c5be7ddddf26076c162953dac79d35bd89ba..00070fe363beb58273a4485a8b961c345b2e8416 100644 --- a/core/java/android/hardware/usb/AccessoryFilter.java +++ b/core/java/android/hardware/usb/AccessoryFilter.java @@ -16,6 +16,11 @@ package android.hardware.usb; +import android.annotation.NonNull; +import android.service.usb.UsbAccessoryFilterProto; + +import com.android.internal.util.dump.DualDumpOutputStream; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -142,4 +147,17 @@ public class AccessoryFilter { "\", mModel=\"" + mModel + "\", mVersion=\"" + mVersion + "\"]"; } + + /** + * Write a description of the filter to a dump stream. + */ + public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) { + long token = dump.start(idName, id); + + dump.write("manufacturer", UsbAccessoryFilterProto.MANUFACTURER, mManufacturer); + dump.write("model", UsbAccessoryFilterProto.MODEL, mModel); + dump.write("version", UsbAccessoryFilterProto.VERSION, mVersion); + + dump.end(token); + } } diff --git a/core/java/android/hardware/usb/DeviceFilter.java b/core/java/android/hardware/usb/DeviceFilter.java index 439c629758b04cefc8c8ee2360cc0e72cce4d463..6f1aff71b2f33aa7a6b76f693f71234b4ddfc006 100644 --- a/core/java/android/hardware/usb/DeviceFilter.java +++ b/core/java/android/hardware/usb/DeviceFilter.java @@ -16,8 +16,12 @@ package android.hardware.usb; +import android.annotation.NonNull; +import android.service.usb.UsbDeviceFilterProto; import android.util.Slog; +import com.android.internal.util.dump.DualDumpOutputStream; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -310,4 +314,22 @@ public class DeviceFilter { ",mProductName=" + mProductName + ",mSerialNumber=" + mSerialNumber + "]"; } + + /** + * Write a description of the filter to a dump stream. + */ + public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) { + long token = dump.start(idName, id); + + dump.write("vendor_id", UsbDeviceFilterProto.VENDOR_ID, mVendorId); + dump.write("product_id", UsbDeviceFilterProto.PRODUCT_ID, mProductId); + dump.write("class", UsbDeviceFilterProto.CLASS, mClass); + dump.write("subclass", UsbDeviceFilterProto.SUBCLASS, mSubclass); + dump.write("protocol", UsbDeviceFilterProto.PROTOCOL, mProtocol); + dump.write("manufacturer_name", UsbDeviceFilterProto.MANUFACTURER_NAME, mManufacturerName); + dump.write("product_name", UsbDeviceFilterProto.PRODUCT_NAME, mProductName); + dump.write("serial_number", UsbDeviceFilterProto.SERIAL_NUMBER, mSerialNumber); + + dump.end(token); + } } diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index 398dda174ba1f13c863f230834e3c1d5fcd4a43a..91bbdc7dde8047543e3f7b6469dbb1277e5a5dab 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -88,18 +88,22 @@ interface IUsbManager /* Returns true if the specified USB function is enabled. */ boolean isFunctionEnabled(String function); - /* Sets the current USB function as well as whether USB data - * (for example, MTP exposed pictures) should be made available - * on the USB connection. Unlocking data should only be done with - * user involvement, since exposing pictures or other data could - * leak sensitive user information. - */ + /* Sets the current USB function. */ + void setCurrentFunctions(long functions); + + /* Compatibility version of setCurrentFunctions(long). */ void setCurrentFunction(String function, boolean usbDataUnlocked); + /* Gets the current USB functions. */ + long getCurrentFunctions(); + /* Sets the screen unlocked USB function(s), which will be set automatically * when the screen is unlocked. */ - void setScreenUnlockedFunctions(String function); + void setScreenUnlockedFunctions(long functions); + + /* Gets the current screen unlocked functions. */ + long getScreenUnlockedFunctions(); /* Allow USB debugging from the attached host. If alwaysAllow is true, add the * the public key to list of host keys that the user has approved. diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java index a17157087a61b54405b854242cbced324afe781b..6ce420191ed39bb1b5e62763c2ecd39233c9870d 100644 --- a/core/java/android/hardware/usb/UsbConfiguration.java +++ b/core/java/android/hardware/usb/UsbConfiguration.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; + import com.android.internal.util.Preconditions; /** @@ -105,6 +106,17 @@ public class UsbConfiguration implements Parcelable { return (mAttributes & ATTR_REMOTE_WAKEUP) != 0; } + /** + * Returns the attributes of this configuration + * + * @return the configuration's attributes + * + * @hide + */ + public int getAttributes() { + return mAttributes; + } + /** * Returns the configuration's max power consumption, in milliamps. * diff --git a/core/java/android/hardware/usb/UsbConstants.java b/core/java/android/hardware/usb/UsbConstants.java index 0e8d47ca130483521b34bcc130a95275a381ebe6..215e9d5fa94beb1a81dec1210a312981b6959afa 100644 --- a/core/java/android/hardware/usb/UsbConstants.java +++ b/core/java/android/hardware/usb/UsbConstants.java @@ -16,6 +16,8 @@ package android.hardware.usb; +import android.service.ServiceProtoEnums; + /** * Contains constants for the USB protocol. * These constants correspond to definitions in linux/usb/ch9.h in the linux kernel. @@ -35,12 +37,12 @@ public final class UsbConstants { * Used to signify direction of data for a {@link UsbEndpoint} is OUT (host to device) * @see UsbEndpoint#getDirection */ - public static final int USB_DIR_OUT = 0; + public static final int USB_DIR_OUT = ServiceProtoEnums.USB_ENDPOINT_DIR_OUT; // 0 /** * Used to signify direction of data for a {@link UsbEndpoint} is IN (device to host) * @see UsbEndpoint#getDirection */ - public static final int USB_DIR_IN = 0x80; + public static final int USB_DIR_IN = ServiceProtoEnums.USB_ENDPOINT_DIR_IN; // 0x80 /** * Bitmask used for extracting the {@link UsbEndpoint} number its address field. @@ -63,22 +65,26 @@ public final class UsbConstants { * Control endpoint type (endpoint zero) * @see UsbEndpoint#getType */ - public static final int USB_ENDPOINT_XFER_CONTROL = 0; + public static final int USB_ENDPOINT_XFER_CONTROL = + ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_CONTROL; // 0 /** * Isochronous endpoint type (currently not supported) * @see UsbEndpoint#getType */ - public static final int USB_ENDPOINT_XFER_ISOC = 1; + public static final int USB_ENDPOINT_XFER_ISOC = + ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_ISOC; // 1 /** * Bulk endpoint type * @see UsbEndpoint#getType */ - public static final int USB_ENDPOINT_XFER_BULK = 2; + public static final int USB_ENDPOINT_XFER_BULK = + ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_BULK; // 2 /** * Interrupt endpoint type * @see UsbEndpoint#getType */ - public static final int USB_ENDPOINT_XFER_INT = 3; + public static final int USB_ENDPOINT_XFER_INT = + ServiceProtoEnums.USB_ENDPOINT_TYPE_XFER_INT; // 3 /** diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 7617c2bd196f19694c28ebfa768f038d5d371054..8daecac5a1090fbade7813282aa10b0e4ae95e02 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -28,6 +28,7 @@ import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; +import android.hardware.usb.gadget.V1_0.GadgetFunction; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.Process; @@ -37,6 +38,8 @@ import android.util.Log; import com.android.internal.util.Preconditions; import java.util.HashMap; +import java.util.Map; +import java.util.StringJoiner; /** * This class allows you to access the state of USB and communicate with USB devices. @@ -70,7 +73,7 @@ public class UsbManager { * MTP function is enabled *
  • {@link #USB_FUNCTION_PTP} boolean extra indicating whether the * PTP function is enabled - *
  • {@link #USB_FUNCTION_PTP} boolean extra indicating whether the + *
  • {@link #USB_FUNCTION_ACCESSORY} boolean extra indicating whether the * accessory function is enabled *
  • {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the * audio source function is enabled @@ -196,8 +199,7 @@ public class UsbManager { /** * A placeholder indicating that no USB function is being specified. - * Used to distinguish between selecting no function vs. the default function in - * {@link #setCurrentFunction(String)}. + * Used for compatibility with old init scripts to indicate no functions vs. charging function. * * {@hide} */ @@ -298,6 +300,69 @@ public class UsbManager { */ public static final String EXTRA_PERMISSION_GRANTED = "permission"; + /** + * Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)} + * {@hide} + */ + public static final long FUNCTION_NONE = 0; + + /** + * Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)} + * {@hide} + */ + public static final long FUNCTION_MTP = GadgetFunction.MTP; + + /** + * Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)} + * {@hide} + */ + public static final long FUNCTION_PTP = GadgetFunction.PTP; + + /** + * Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)} + * {@hide} + */ + public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS; + + /** + * Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)} + * {@hide} + */ + public static final long FUNCTION_MIDI = GadgetFunction.MIDI; + + /** + * Code for the accessory usb function. + * {@hide} + */ + public static final long FUNCTION_ACCESSORY = GadgetFunction.ACCESSORY; + + /** + * Code for the audio source usb function. + * {@hide} + */ + public static final long FUNCTION_AUDIO_SOURCE = GadgetFunction.AUDIO_SOURCE; + + /** + * Code for the adb usb function. + * {@hide} + */ + public static final long FUNCTION_ADB = GadgetFunction.ADB; + + private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS + | FUNCTION_MIDI; + + private static final Map FUNCTION_NAME_TO_CODE = new HashMap<>(); + + static { + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MTP, FUNCTION_MTP); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_PTP, FUNCTION_PTP); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_RNDIS, FUNCTION_RNDIS); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MIDI, FUNCTION_MIDI); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE); + FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB); + } + private final Context mContext; private final IUsbManager mService; @@ -548,15 +613,14 @@ public class UsbManager { * services offered by the device. *

    * + * @deprecated use getCurrentFunctions() instead. * @param function name of the USB function * @return true if the USB function is enabled * * {@hide} */ + @Deprecated public boolean isFunctionEnabled(String function) { - if (mService == null) { - return false; - } try { return mService.isFunctionEnabled(function); } catch (RemoteException e) { @@ -565,7 +629,7 @@ public class UsbManager { } /** - * Sets the current USB function when in device mode. + * Sets the current USB functions when in device mode. *

    * USB functions represent interfaces which are published to the host to access * services offered by the device. @@ -574,27 +638,59 @@ public class UsbManager { * automatically activate additional functions such as {@link #USB_FUNCTION_ADB} * or {@link #USB_FUNCTION_ACCESSORY} based on other settings and states. *

    - * The allowed values are: {@link #USB_FUNCTION_NONE}, {@link #USB_FUNCTION_AUDIO_SOURCE}, - * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP}, - * or {@link #USB_FUNCTION_RNDIS}. - *

    - * Also sets whether USB data (for example, MTP exposed pictures) should be made available - * on the USB connection when in device mode. Unlocking usb data should only be done with - * user involvement, since exposing pictures or other data could leak sensitive - * user information. + * An argument of 0 indicates that the device is charging, and can pick any + * appropriate function for that purpose. *

    * Note: This function is asynchronous and may fail silently without applying * the requested changes. *

    * - * @param function name of the USB function, or null to restore the default function - * @param usbDataUnlocked whether user data is accessible + * @param functions the USB function(s) to set, as a bitwise mask. + * Must satisfy {@link UsbManager#areSettableFunctions} + * + * {@hide} + */ + public void setCurrentFunctions(long functions) { + try { + mService.setCurrentFunctions(functions); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Sets the current USB functions when in device mode. + * + * @deprecated use setCurrentFunctions(long) instead. + * @param functions the USB function(s) to set. + * @param usbDataUnlocked unused + + * {@hide} + */ + @Deprecated + public void setCurrentFunction(String functions, boolean usbDataUnlocked) { + try { + mService.setCurrentFunction(functions, usbDataUnlocked); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the current USB functions in device mode. + *

    + * This function returns the state of primary USB functions and can return a + * mask containing any usb function(s) except for ADB. + *

    + * + * @return The currently enabled functions, in a bitwise mask. + * A zero mask indicates that the current function is the charging function. * * {@hide} */ - public void setCurrentFunction(String function, boolean usbDataUnlocked) { + public long getCurrentFunctions() { try { - mService.setCurrentFunction(function, usbDataUnlocked); + return mService.getCurrentFunctions(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -604,23 +700,37 @@ public class UsbManager { * Sets the screen unlocked functions, which are persisted and set as the current functions * whenever the screen is unlocked. *

    - * The allowed values are: {@link #USB_FUNCTION_NONE}, - * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP}, - * or {@link #USB_FUNCTION_RNDIS}. - * {@link #USB_FUNCTION_NONE} has the effect of switching off this feature, so functions + * A zero mask has the effect of switching off this feature, so functions * no longer change on screen unlock. *

    * Note: When the screen is on, this method will apply given functions as current functions, * which is asynchronous and may fail silently without applying the requested changes. *

    * - * @param function function to set as default + * @param functions functions to set, in a bitwise mask. + * Must satisfy {@link UsbManager#areSettableFunctions} * * {@hide} */ - public void setScreenUnlockedFunctions(String function) { + public void setScreenUnlockedFunctions(long functions) { try { - mService.setScreenUnlockedFunctions(function); + mService.setScreenUnlockedFunctions(functions); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets the current screen unlocked functions. + * + * @return The currently set screen enabled functions. + * A zero mask indicates that the screen unlocked functions feature is not enabled. + * + * {@hide} + */ + public long getScreenUnlockedFunctions() { + try { + return mService.getScreenUnlockedFunctions(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -719,51 +829,71 @@ public class UsbManager { } } - /** @hide */ - public static String addFunction(String functions, String function) { - if (USB_FUNCTION_NONE.equals(functions)) { - return function; - } - if (!containsFunction(functions, function)) { - if (functions.length() > 0) { - functions += ","; - } - functions += function; - } - return functions; + /** + * Returns whether the given functions are valid inputs to UsbManager. + * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted. + * + * @return Whether the mask is settable. + * + * {@hide} + */ + public static boolean areSettableFunctions(long functions) { + return functions == FUNCTION_NONE + || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1); } - /** @hide */ - public static String removeFunction(String functions, String function) { - String[] split = functions.split(","); - for (int i = 0; i < split.length; i++) { - if (function.equals(split[i])) { - split[i] = null; - } + /** + * Converts the given function mask to string. Maintains ordering with respect to init scripts. + * + * @return String representation of given mask + * + * {@hide} + */ + public static String usbFunctionsToString(long functions) { + StringJoiner joiner = new StringJoiner(","); + if ((functions & FUNCTION_MTP) != 0) { + joiner.add(UsbManager.USB_FUNCTION_MTP); } - if (split.length == 1 && split[0] == null) { - return USB_FUNCTION_NONE; + if ((functions & FUNCTION_PTP) != 0) { + joiner.add(UsbManager.USB_FUNCTION_PTP); } - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < split.length; i++) { - String s = split[i]; - if (s != null) { - if (builder.length() > 0) { - builder.append(","); - } - builder.append(s); - } + if ((functions & FUNCTION_RNDIS) != 0) { + joiner.add(UsbManager.USB_FUNCTION_RNDIS); + } + if ((functions & FUNCTION_MIDI) != 0) { + joiner.add(UsbManager.USB_FUNCTION_MIDI); + } + if ((functions & FUNCTION_ACCESSORY) != 0) { + joiner.add(UsbManager.USB_FUNCTION_ACCESSORY); + } + if ((functions & FUNCTION_AUDIO_SOURCE) != 0) { + joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE); } - return builder.toString(); + if ((functions & FUNCTION_ADB) != 0) { + joiner.add(UsbManager.USB_FUNCTION_ADB); + } + return joiner.toString(); } - /** @hide */ - public static boolean containsFunction(String functions, String function) { - int index = functions.indexOf(function); - if (index < 0) return false; - if (index > 0 && functions.charAt(index - 1) != ',') return false; - int charAfter = index + function.length(); - if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false; - return true; + /** + * Parses a string of usb functions that are comma separated. + * + * @return A mask of all valid functions in the string + * + * {@hide} + */ + public static long usbFunctionsFromString(String functions) { + if (functions == null || functions.equals(USB_FUNCTION_NONE)) { + return FUNCTION_NONE; + } + long ret = 0; + for (String function : functions.split(",")) { + if (FUNCTION_NAME_TO_CODE.containsKey(function)) { + ret |= FUNCTION_NAME_TO_CODE.get(function); + } else if (function.length() > 0) { + throw new IllegalArgumentException("Invalid usb function " + functions); + } + } + return ret; } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 166342dd4e6dc87b7d20da297ac1bb68693d750b..91ba57f334f0ffc4c86a1624cd0acf1c43e5cb69 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -406,6 +406,13 @@ public class ConnectivityManager { @SystemApi public static final int TETHERING_BLUETOOTH = 2; + /** + * WIGIG tethering type. Use a separate type to prevent + * conflicts with TETHERING_WIFI + * @hide + */ + public static final int TETHERING_WIGIG = 3; + /** * Extra used for communicating with the TetherService. Includes the type of tethering to * enable if any. diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 31a30968cbcd2513840099718a95a2c37893a8c9..ecccda588aece3403232462e547aeff6ef3827b1 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -18,9 +18,6 @@ package android.net; import android.annotation.SystemService; import android.content.Context; -import android.net.IEthernetManager; -import android.net.IEthernetServiceListener; -import android.net.IpConfiguration; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -45,18 +42,18 @@ public class EthernetManager { if (msg.what == MSG_AVAILABILITY_CHANGED) { boolean isAvailable = (msg.arg1 == 1); for (Listener listener : mListeners) { - listener.onAvailabilityChanged(isAvailable); + listener.onAvailabilityChanged((String) msg.obj, isAvailable); } } } }; - private final ArrayList mListeners = new ArrayList(); + private final ArrayList mListeners = new ArrayList<>(); private final IEthernetServiceListener.Stub mServiceListener = new IEthernetServiceListener.Stub() { @Override - public void onAvailabilityChanged(boolean isAvailable) { + public void onAvailabilityChanged(String iface, boolean isAvailable) { mHandler.obtainMessage( - MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, null).sendToTarget(); + MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, iface).sendToTarget(); } }; @@ -66,9 +63,10 @@ public class EthernetManager { public interface Listener { /** * Called when Ethernet port's availability is changed. - * @param isAvailable {@code true} if one or more Ethernet port exists. + * @param iface Ethernet interface name + * @param isAvailable {@code true} if Ethernet port exists. */ - public void onAvailabilityChanged(boolean isAvailable); + void onAvailabilityChanged(String iface, boolean isAvailable); } /** @@ -86,9 +84,9 @@ public class EthernetManager { * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. */ - public IpConfiguration getConfiguration() { + public IpConfiguration getConfiguration(String iface) { try { - return mService.getConfiguration(); + return mService.getConfiguration(iface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -97,21 +95,29 @@ public class EthernetManager { /** * Set Ethernet configuration. */ - public void setConfiguration(IpConfiguration config) { + public void setConfiguration(String iface, IpConfiguration config) { try { - mService.setConfiguration(config); + mService.setConfiguration(iface, config); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Indicates whether the system currently has one or more - * Ethernet interfaces. + * Indicates whether the system currently has one or more Ethernet interfaces. */ public boolean isAvailable() { + return getAvailableInterfaces().length > 0; + } + + /** + * Indicates whether the system has given interface. + * + * @param iface Ethernet interface name + */ + public boolean isAvailable(String iface) { try { - return mService.isAvailable(); + return mService.isAvailable(iface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -136,6 +142,17 @@ public class EthernetManager { } } + /** + * Returns an array of available Ethernet interface names. + */ + public String[] getAvailableInterfaces() { + try { + return mService.getAvailableInterfaces(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + /** * Removes a listener. * @param listener A {@link Listener} to remove. diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index 7a92eb955ace641ef2bf7b2251aa3b738afd6c8c..94960b51d329d2112d324c8bfd340c97f86908dc 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -26,9 +26,10 @@ import android.net.IEthernetServiceListener; /** {@hide} */ interface IEthernetManager { - IpConfiguration getConfiguration(); - void setConfiguration(in IpConfiguration config); - boolean isAvailable(); + String[] getAvailableInterfaces(); + IpConfiguration getConfiguration(String iface); + void setConfiguration(String iface, in IpConfiguration config); + boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); } diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/core/java/android/net/IEthernetServiceListener.aidl index 356690e8f7a6a3009daf9c5a08a6d1fb602002b5..782fa19d9df7c8d21e4b4c0323890a925cd2f61e 100644 --- a/core/java/android/net/IEthernetServiceListener.aidl +++ b/core/java/android/net/IEthernetServiceListener.aidl @@ -19,5 +19,5 @@ package android.net; /** @hide */ oneway interface IEthernetServiceListener { - void onAvailabilityChanged(boolean isAvailable); + void onAvailabilityChanged(String iface, boolean isAvailable); } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 9ccdbe2b1bdc9ad3b35b4677e66ac6edec1eedf0..0829b4a3e9fe7d206fb9d67dd0be217d3d081fcb 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -462,7 +462,7 @@ public final class IpSecTransform implements AutoCloseable { mConfig.setMode(MODE_TUNNEL); mConfig.setSourceAddress(sourceAddress.getHostAddress()); mConfig.setSpiResourceId(spi.getResourceId()); - return new IpSecTransform(mContext, mConfig); + return new IpSecTransform(mContext, mConfig).activate(); } /** diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java index 5df742c5a394d0013586ddc2e088388c87d9536b..9f47f62775e188eb42150fb5af6a409ed9c09e3b 100644 --- a/core/java/android/net/NetworkPolicy.java +++ b/core/java/android/net/NetworkPolicy.java @@ -42,6 +42,7 @@ import java.util.Objects; public class NetworkPolicy implements Parcelable, Comparable { private static final int VERSION_INIT = 1; private static final int VERSION_RULE = 2; + private static final int VERSION_RAPID = 3; public static final int CYCLE_NONE = -1; public static final long WARNING_DISABLED = -1; @@ -54,6 +55,7 @@ public class NetworkPolicy implements Parcelable, Comparable { public long limitBytes = LIMIT_DISABLED; public long lastWarningSnooze = SNOOZE_NEVER; public long lastLimitSnooze = SNOOZE_NEVER; + public long lastRapidSnooze = SNOOZE_NEVER; @Deprecated public boolean metered = true; public boolean inferred = false; @@ -82,15 +84,24 @@ public class NetworkPolicy implements Parcelable, Comparable { limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred); } + @Deprecated public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered, boolean inferred) { + this(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze, + SNOOZE_NEVER, metered, inferred); + } + + public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes, + long limitBytes, long lastWarningSnooze, long lastLimitSnooze, long lastRapidSnooze, + boolean metered, boolean inferred) { this.template = Preconditions.checkNotNull(template, "missing NetworkTemplate"); this.cycleRule = Preconditions.checkNotNull(cycleRule, "missing RecurrenceRule"); this.warningBytes = warningBytes; this.limitBytes = limitBytes; this.lastWarningSnooze = lastWarningSnooze; this.lastLimitSnooze = lastLimitSnooze; + this.lastRapidSnooze = lastRapidSnooze; this.metered = metered; this.inferred = inferred; } @@ -102,6 +113,7 @@ public class NetworkPolicy implements Parcelable, Comparable { limitBytes = source.readLong(); lastWarningSnooze = source.readLong(); lastLimitSnooze = source.readLong(); + lastRapidSnooze = source.readLong(); metered = source.readInt() != 0; inferred = source.readInt() != 0; } @@ -114,6 +126,7 @@ public class NetworkPolicy implements Parcelable, Comparable { dest.writeLong(limitBytes); dest.writeLong(lastWarningSnooze); dest.writeLong(lastLimitSnooze); + dest.writeLong(lastRapidSnooze); dest.writeInt(metered ? 1 : 0); dest.writeInt(inferred ? 1 : 0); } @@ -151,6 +164,7 @@ public class NetworkPolicy implements Parcelable, Comparable { public void clearSnooze() { lastWarningSnooze = SNOOZE_NEVER; lastLimitSnooze = SNOOZE_NEVER; + lastRapidSnooze = SNOOZE_NEVER; } /** @@ -176,7 +190,7 @@ public class NetworkPolicy implements Parcelable, Comparable { @Override public int hashCode() { return Objects.hash(template, cycleRule, warningBytes, limitBytes, - lastWarningSnooze, lastLimitSnooze, metered, inferred); + lastWarningSnooze, lastLimitSnooze, lastRapidSnooze, metered, inferred); } @Override @@ -186,7 +200,9 @@ public class NetworkPolicy implements Parcelable, Comparable { return warningBytes == other.warningBytes && limitBytes == other.limitBytes && lastWarningSnooze == other.lastWarningSnooze - && lastLimitSnooze == other.lastLimitSnooze && metered == other.metered + && lastLimitSnooze == other.lastLimitSnooze + && lastRapidSnooze == other.lastRapidSnooze + && metered == other.metered && inferred == other.inferred && Objects.equals(template, other.template) && Objects.equals(cycleRule, other.cycleRule); @@ -203,6 +219,7 @@ public class NetworkPolicy implements Parcelable, Comparable { .append(" limitBytes=").append(limitBytes) .append(" lastWarningSnooze=").append(lastWarningSnooze) .append(" lastLimitSnooze=").append(lastLimitSnooze) + .append(" lastRapidSnooze=").append(lastRapidSnooze) .append(" metered=").append(metered) .append(" inferred=").append(inferred) .append("}").toString(); @@ -224,13 +241,14 @@ public class NetworkPolicy implements Parcelable, Comparable { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); - out.writeInt(VERSION_RULE); + out.writeInt(VERSION_RAPID); out.write(template.getBytesForBackup()); cycleRule.writeToStream(out); out.writeLong(warningBytes); out.writeLong(limitBytes); out.writeLong(lastWarningSnooze); out.writeLong(lastLimitSnooze); + out.writeLong(lastRapidSnooze); out.writeInt(metered ? 1 : 0); out.writeInt(inferred ? 1 : 0); return baos.toByteArray(); @@ -239,35 +257,32 @@ public class NetworkPolicy implements Parcelable, Comparable { public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException, BackupUtils.BadVersionException { final int version = in.readInt(); - switch (version) { - case VERSION_INIT: { - NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in); - int cycleDay = in.readInt(); - String cycleTimeZone = BackupUtils.readString(in); - long warningBytes = in.readLong(); - long limitBytes = in.readLong(); - long lastWarningSnooze = in.readLong(); - long lastLimitSnooze = in.readLong(); - boolean metered = in.readInt() == 1; - boolean inferred = in.readInt() == 1; - return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes, - limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred); - } - case VERSION_RULE: { - NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in); - RecurrenceRule cycleRule = new RecurrenceRule(in); - long warningBytes = in.readLong(); - long limitBytes = in.readLong(); - long lastWarningSnooze = in.readLong(); - long lastLimitSnooze = in.readLong(); - boolean metered = in.readInt() == 1; - boolean inferred = in.readInt() == 1; - return new NetworkPolicy(template, cycleRule, warningBytes, - limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred); - } - default: { - throw new BackupUtils.BadVersionException("Unknown backup version: " + version); - } + if (version > VERSION_RAPID) { + throw new BackupUtils.BadVersionException("Unknown backup version: " + version); + } + + final NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in); + final RecurrenceRule cycleRule; + if (version >= VERSION_RULE) { + cycleRule = new RecurrenceRule(in); + } else { + final int cycleDay = in.readInt(); + final String cycleTimezone = BackupUtils.readString(in); + cycleRule = buildRule(cycleDay, ZoneId.of(cycleTimezone)); + } + final long warningBytes = in.readLong(); + final long limitBytes = in.readLong(); + final long lastWarningSnooze = in.readLong(); + final long lastLimitSnooze = in.readLong(); + final long lastRapidSnooze; + if (version >= VERSION_RAPID) { + lastRapidSnooze = in.readLong(); + } else { + lastRapidSnooze = SNOOZE_NEVER; } + final boolean metered = in.readInt() == 1; + final boolean inferred = in.readInt() == 1; + return new NetworkPolicy(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, + lastLimitSnooze, lastRapidSnooze, metered, inferred); } } diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index 6758d95fa6b682cd06e4223fcc67be8697eb3ace..3a40cf4bf8a399cbf00b215d4f3b2faefdd8e89f 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -1,5 +1,4 @@ ek@google.com -hugobenichi@google.com jsharkey@android.com jchalard@google.com lorenzo@google.com diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index bda720bb6fdd1a91773e784a037eccfdae7e0b07..7922276edb7583152231901b545d8d9a68dd070c 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -439,6 +439,10 @@ public class TrafficStats { } } + private static long addIfSupported(long stat) { + return (stat == UNSUPPORTED) ? 0 : stat; + } + /** * Return number of packets transmitted across mobile networks since device * boot. Counts packets across all mobile network interfaces, and always @@ -451,7 +455,7 @@ public class TrafficStats { public static long getMobileTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - total += getTxPackets(iface); + total += addIfSupported(getTxPackets(iface)); } return total; } @@ -468,7 +472,7 @@ public class TrafficStats { public static long getMobileRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - total += getRxPackets(iface); + total += addIfSupported(getRxPackets(iface)); } return total; } @@ -485,7 +489,7 @@ public class TrafficStats { public static long getMobileTxBytes() { long total = 0; for (String iface : getMobileIfaces()) { - total += getTxBytes(iface); + total += addIfSupported(getTxBytes(iface)); } return total; } @@ -502,7 +506,7 @@ public class TrafficStats { public static long getMobileRxBytes() { long total = 0; for (String iface : getMobileIfaces()) { - total += getRxBytes(iface); + total += addIfSupported(getRxBytes(iface)); } return total; } @@ -517,9 +521,7 @@ public class TrafficStats { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (stat != UNSUPPORTED) { - total += stat; - } + total += addIfSupported(stat); } return total; } @@ -534,9 +536,7 @@ public class TrafficStats { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (stat != UNSUPPORTED) { - total += stat; - } + total += addIfSupported(stat); } return total; } diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index 9edcc0e9b8d4cfe6a82a9d640f2cfd7e10fde937..5ca3a4106a2d9fb35c6151a01e6f4ddc3fcfbbc7 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -720,6 +720,10 @@ public abstract class Uri implements Parcelable, Comparable { LOOP: while (end < length) { switch (uriString.charAt(end)) { case '/': // Start of path + case '\\':// Start of path + // Per http://url.spec.whatwg.org/#host-state, the \ character + // is treated as if it were a / character when encountered in a + // host case '?': // Start of query case '#': // Start of fragment break LOOP; @@ -758,6 +762,10 @@ public abstract class Uri implements Parcelable, Comparable { case '#': // Start of fragment return ""; // Empty path. case '/': // Start of path! + case '\\':// Start of path! + // Per http://url.spec.whatwg.org/#host-state, the \ character + // is treated as if it were a / character when encountered in a + // host break LOOP; } pathStart++; diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 185b1818df4564d059086950e71b881921418933..712576f304d9552ff3b0ef949f93f28d2c9e6a1f 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -192,7 +192,7 @@ public class VpnService extends Service { */ public static Intent prepare(Context context) { try { - if (getService().prepareVpn(context.getPackageName(), null, UserHandle.myUserId())) { + if (getService().prepareVpn(context.getPackageName(), null, context.getUserId())) { return null; } } catch (RemoteException e) { @@ -219,7 +219,7 @@ public class VpnService extends Service { String packageName = context.getPackageName(); try { // Only prepare if we're not already prepared. - int userId = UserHandle.myUserId(); + int userId = context.getUserId(); if (!cm.prepareVpn(packageName, null, userId)) { cm.prepareVpn(null, packageName, userId); } diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index c7d4c65d99c0dfbdffd712c8b01cd10195626439..958063ae0a9f78a844b315db3a8040784b7463ef 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -393,7 +393,7 @@ public final class NfcActivityManager extends IAppCallback.Stub "either scheme file or scheme content"); continue; } - uri = ContentProvider.maybeAddUserId(uri, UserHandle.myUserId()); + uri = ContentProvider.maybeAddUserId(uri, activity.getUserId()); validUris.add(uri); } @@ -410,7 +410,7 @@ public final class NfcActivityManager extends IAppCallback.Stub } finally { Binder.restoreCallingIdentity(ident); } - return new BeamShareData(message, uris, new UserHandle(UserHandle.myUserId()), flags); + return new BeamShareData(message, uris, activity.getUser(), flags); } /** Callback from NFC service, usually on binder thread */ diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index debef6310f14d0d6b8692551c7fd4ff44c531689..b02d48dc438f649aec7ec9e6105f30f383ef279e 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -146,6 +146,19 @@ public final class NfcAdapter { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; + /** + * Broadcast Action: Intent to notify an application that an transaction event has occurred + * on the Secure Element. + * + *

    This intent will only be sent if the application has requested permission for + * {@link android.Manifest.permission#NFC_TRANSACTION_EVENT} and if the application has the + * necessary access to Secure Element which witnessed the particular event. + */ + @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_TRANSACTION_DETECTED = + "android.nfc.action.TRANSACTION_DETECTED"; + /** * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED * @hide @@ -197,6 +210,23 @@ public final class NfcAdapter { */ public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE"; + /** + * Mandatory byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED} + */ + public static final String EXTRA_AID = "android.nfc.extra.AID"; + + /** + * Optional byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED} + */ + public static final String EXTRA_DATA = "android.nfc.extra.DATA"; + + /** + * Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED} + * Indicates the Secure Element on which the transaction occurred. + * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc. + */ + public static final String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME"; + public static final int STATE_OFF = 1; public static final int STATE_TURNING_ON = 2; public static final int STATE_ON = 3; diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 6dd79939659922739c609826bbd57a4d827175e5..15d02f2e5ddf52ef3f0b17258fa70ca6b6783b3a 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -201,7 +201,7 @@ public final class CardEmulation { */ public boolean isDefaultServiceForCategory(ComponentName service, String category) { try { - return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, category); + return sService.isDefaultServiceForCategory(mContext.getUserId(), service, category); } catch (RemoteException e) { // Try one more time recoverService(); @@ -210,7 +210,7 @@ public final class CardEmulation { return false; } try { - return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, + return sService.isDefaultServiceForCategory(mContext.getUserId(), service, category); } catch (RemoteException ee) { Log.e(TAG, "Failed to recover CardEmulationService."); @@ -232,7 +232,7 @@ public final class CardEmulation { */ public boolean isDefaultServiceForAid(ComponentName service, String aid) { try { - return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid); + return sService.isDefaultServiceForAid(mContext.getUserId(), service, aid); } catch (RemoteException e) { // Try one more time recoverService(); @@ -241,7 +241,7 @@ public final class CardEmulation { return false; } try { - return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid); + return sService.isDefaultServiceForAid(mContext.getUserId(), service, aid); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; @@ -326,7 +326,7 @@ public final class CardEmulation { List aids) { AidGroup aidGroup = new AidGroup(aids, category); try { - return sService.registerAidGroupForService(UserHandle.myUserId(), service, aidGroup); + return sService.registerAidGroupForService(mContext.getUserId(), service, aidGroup); } catch (RemoteException e) { // Try one more time recoverService(); @@ -335,7 +335,7 @@ public final class CardEmulation { return false; } try { - return sService.registerAidGroupForService(UserHandle.myUserId(), service, + return sService.registerAidGroupForService(mContext.getUserId(), service, aidGroup); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); @@ -360,7 +360,7 @@ public final class CardEmulation { */ public List getAidsForService(ComponentName service, String category) { try { - AidGroup group = sService.getAidGroupForService(UserHandle.myUserId(), service, + AidGroup group = sService.getAidGroupForService(mContext.getUserId(), service, category); return (group != null ? group.getAids() : null); } catch (RemoteException e) { @@ -370,7 +370,7 @@ public final class CardEmulation { return null; } try { - AidGroup group = sService.getAidGroupForService(UserHandle.myUserId(), service, + AidGroup group = sService.getAidGroupForService(mContext.getUserId(), service, category); return (group != null ? group.getAids() : null); } catch (RemoteException ee) { @@ -397,7 +397,7 @@ public final class CardEmulation { */ public boolean removeAidsForService(ComponentName service, String category) { try { - return sService.removeAidGroupForService(UserHandle.myUserId(), service, category); + return sService.removeAidGroupForService(mContext.getUserId(), service, category); } catch (RemoteException e) { // Try one more time recoverService(); @@ -406,7 +406,7 @@ public final class CardEmulation { return false; } try { - return sService.removeAidGroupForService(UserHandle.myUserId(), service, category); + return sService.removeAidGroupForService(mContext.getUserId(), service, category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; @@ -537,7 +537,7 @@ public final class CardEmulation { */ public boolean setDefaultServiceForCategory(ComponentName service, String category) { try { - return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, category); + return sService.setDefaultServiceForCategory(mContext.getUserId(), service, category); } catch (RemoteException e) { // Try one more time recoverService(); @@ -546,7 +546,7 @@ public final class CardEmulation { return false; } try { - return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, + return sService.setDefaultServiceForCategory(mContext.getUserId(), service, category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); @@ -560,7 +560,7 @@ public final class CardEmulation { */ public boolean setDefaultForNextTap(ComponentName service) { try { - return sService.setDefaultForNextTap(UserHandle.myUserId(), service); + return sService.setDefaultForNextTap(mContext.getUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); @@ -569,7 +569,7 @@ public final class CardEmulation { return false; } try { - return sService.setDefaultForNextTap(UserHandle.myUserId(), service); + return sService.setDefaultForNextTap(mContext.getUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return false; @@ -582,7 +582,7 @@ public final class CardEmulation { */ public List getServices(String category) { try { - return sService.getServices(UserHandle.myUserId(), category); + return sService.getServices(mContext.getUserId(), category); } catch (RemoteException e) { // Try one more time recoverService(); @@ -591,7 +591,7 @@ public final class CardEmulation { return null; } try { - return sService.getServices(UserHandle.myUserId(), category); + return sService.getServices(mContext.getUserId(), category); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return null; diff --git a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java index f2b5ebc15a43223d86005dd375d52970702ee1be..80e8579dd73fa3ef14395f5f5dcd25382a3616c8 100644 --- a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java +++ b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java @@ -118,7 +118,7 @@ public final class NfcFCardEmulation { throw new NullPointerException("service is null"); } try { - return sService.getSystemCodeForService(UserHandle.myUserId(), service); + return sService.getSystemCodeForService(mContext.getUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); @@ -127,7 +127,7 @@ public final class NfcFCardEmulation { return null; } try { - return sService.getSystemCodeForService(UserHandle.myUserId(), service); + return sService.getSystemCodeForService(mContext.getUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); ee.rethrowAsRuntimeException(); @@ -164,7 +164,7 @@ public final class NfcFCardEmulation { throw new NullPointerException("service or systemCode is null"); } try { - return sService.registerSystemCodeForService(UserHandle.myUserId(), + return sService.registerSystemCodeForService(mContext.getUserId(), service, systemCode); } catch (RemoteException e) { // Try one more time @@ -174,7 +174,7 @@ public final class NfcFCardEmulation { return false; } try { - return sService.registerSystemCodeForService(UserHandle.myUserId(), + return sService.registerSystemCodeForService(mContext.getUserId(), service, systemCode); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); @@ -195,7 +195,7 @@ public final class NfcFCardEmulation { throw new NullPointerException("service is null"); } try { - return sService.removeSystemCodeForService(UserHandle.myUserId(), service); + return sService.removeSystemCodeForService(mContext.getUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); @@ -204,7 +204,7 @@ public final class NfcFCardEmulation { return false; } try { - return sService.removeSystemCodeForService(UserHandle.myUserId(), service); + return sService.removeSystemCodeForService(mContext.getUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); ee.rethrowAsRuntimeException(); @@ -230,7 +230,7 @@ public final class NfcFCardEmulation { throw new NullPointerException("service is null"); } try { - return sService.getNfcid2ForService(UserHandle.myUserId(), service); + return sService.getNfcid2ForService(mContext.getUserId(), service); } catch (RemoteException e) { // Try one more time recoverService(); @@ -239,7 +239,7 @@ public final class NfcFCardEmulation { return null; } try { - return sService.getNfcid2ForService(UserHandle.myUserId(), service); + return sService.getNfcid2ForService(mContext.getUserId(), service); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); ee.rethrowAsRuntimeException(); @@ -273,7 +273,7 @@ public final class NfcFCardEmulation { throw new NullPointerException("service or nfcid2 is null"); } try { - return sService.setNfcid2ForService(UserHandle.myUserId(), + return sService.setNfcid2ForService(mContext.getUserId(), service, nfcid2); } catch (RemoteException e) { // Try one more time @@ -283,7 +283,7 @@ public final class NfcFCardEmulation { return false; } try { - return sService.setNfcid2ForService(UserHandle.myUserId(), + return sService.setNfcid2ForService(mContext.getUserId(), service, nfcid2); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); @@ -381,7 +381,7 @@ public final class NfcFCardEmulation { */ public List getNfcFServices() { try { - return sService.getNfcFServices(UserHandle.myUserId()); + return sService.getNfcFServices(mContext.getUserId()); } catch (RemoteException e) { // Try one more time recoverService(); @@ -390,7 +390,7 @@ public final class NfcFCardEmulation { return null; } try { - return sService.getNfcFServices(UserHandle.myUserId()); + return sService.getNfcFServices(mContext.getUserId()); } catch (RemoteException ee) { Log.e(TAG, "Failed to reach CardEmulationService."); return null; diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index eb264d6d308cf013e60ebd38ff8ad0f2be80faa4..682fdb7160f440d6d902ac9f1e019e1808579364 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -21,7 +21,9 @@ import android.annotation.Nullable; import android.util.ExceptionUtils; import android.util.Log; import android.util.Slog; +import android.util.SparseIntArray; +import com.android.internal.os.BinderInternal; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.util.FunctionalUtils.ThrowingSupplier; @@ -782,7 +784,7 @@ final class BinderProxy implements IBinder { private static final int MAIN_INDEX_SIZE = 1 << LOG_MAIN_INDEX_SIZE; private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1; // Debuggable builds will throw an AssertionError if the number of map entries exceeds: - private static final int CRASH_AT_SIZE = 5_000; + private static final int CRASH_AT_SIZE = 20_000; /** * We next warn when we exceed this bucket size. @@ -934,6 +936,7 @@ final class BinderProxy implements IBinder { final int totalUnclearedSize = unclearedSize(); if (totalUnclearedSize >= CRASH_AT_SIZE) { dumpProxyInterfaceCounts(); + dumpPerUidProxyCounts(); Runtime.getRuntime().gc(); throw new AssertionError("Binder ProxyMap has too many entries: " + totalSize + " (total), " + totalUnclearedSize + " (uncleared), " @@ -987,6 +990,20 @@ final class BinderProxy implements IBinder { } } + /** + * Dump per uid binder proxy counts to the logcat. + */ + private void dumpPerUidProxyCounts() { + SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts(); + if (counts.size() == 0) return; + Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:"); + for (int i = 0; i < counts.size(); i++) { + final int uid = counts.keyAt(i); + final int binderCount = counts.valueAt(i); + Log.d(Binder.TAG, "UID : " + uid + " count = " + binderCount); + } + } + // Corresponding ArrayLists in the following two arrays always have the same size. // They contain no empty entries. However WeakReferences in the values ArrayLists // may have been cleared. diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 7c53ec198e7d405cc5b6e5c9596fca0f1aef5099..1160415ce21274f05145fafb5183e026f6f3e7fc 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -16,6 +16,11 @@ package android.os; +import static android.system.OsConstants.SPLICE_F_MORE; +import static android.system.OsConstants.SPLICE_F_MOVE; +import static android.system.OsConstants.S_ISFIFO; +import static android.system.OsConstants.S_ISREG; + import android.annotation.NonNull; import android.annotation.Nullable; import android.provider.DocumentsContract.Document; @@ -28,7 +33,9 @@ import android.util.Slog; import android.webkit.MimeTypeMap; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.SizedInputStream; +import libcore.io.IoUtils; import libcore.util.EmptyArray; import java.io.BufferedInputStream; @@ -41,10 +48,12 @@ import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Comparator; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; @@ -81,6 +90,14 @@ public class FileUtils { private static final File[] EMPTY = new File[0]; + private static final boolean ENABLE_COPY_OPTIMIZATIONS = true; + + private static final long COPY_CHECKPOINT_BYTES = 524288; + + public interface ProgressListener { + public void onProgress(long progress); + } + /** * Set owner and mode of of given {@link File}. * @@ -185,6 +202,9 @@ public class FileUtils { return false; } + /** + * @deprecated use {@link #copy(File, File)} instead. + */ @Deprecated public static boolean copyFile(File srcFile, File destFile) { try { @@ -195,14 +215,19 @@ public class FileUtils { } } - // copy a file from srcFile to destFile, return true if succeed, return - // false if fail + /** + * @deprecated use {@link #copy(File, File)} instead. + */ + @Deprecated public static void copyFileOrThrow(File srcFile, File destFile) throws IOException { try (InputStream in = new FileInputStream(srcFile)) { copyToFileOrThrow(in, destFile); } } + /** + * @deprecated use {@link #copy(InputStream, OutputStream)} instead. + */ @Deprecated public static boolean copyToFile(InputStream inputStream, File destFile) { try { @@ -214,29 +239,247 @@ public class FileUtils { } /** - * Copy data from a source stream to destFile. - * Return true if succeed, return false if failed. + * @deprecated use {@link #copy(InputStream, OutputStream)} instead. */ - public static void copyToFileOrThrow(InputStream inputStream, File destFile) - throws IOException { + @Deprecated + public static void copyToFileOrThrow(InputStream in, File destFile) throws IOException { if (destFile.exists()) { destFile.delete(); } - FileOutputStream out = new FileOutputStream(destFile); - try { - byte[] buffer = new byte[4096]; - int bytesRead; - while ((bytesRead = inputStream.read(buffer)) >= 0) { - out.write(buffer, 0, bytesRead); + try (FileOutputStream out = new FileOutputStream(destFile)) { + copy(in, out); + try { + Os.fsync(out.getFD()); + } catch (ErrnoException e) { + throw e.rethrowAsIOException(); } - } finally { - out.flush(); + } + } + + /** + * Copy the contents of one file to another, replacing any existing content. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @return number of bytes copied. + */ + public static long copy(@NonNull File from, @NonNull File to) throws IOException { + return copy(from, to, null, null); + } + + /** + * Copy the contents of one file to another, replacing any existing content. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @param listener to be periodically notified as the copy progresses. + * @param signal to signal if the copy should be cancelled early. + * @return number of bytes copied. + */ + public static long copy(@NonNull File from, @NonNull File to, + @Nullable ProgressListener listener, @Nullable CancellationSignal signal) + throws IOException { + try (FileInputStream in = new FileInputStream(from); + FileOutputStream out = new FileOutputStream(to)) { + return copy(in, out, listener, signal); + } + } + + /** + * Copy the contents of one stream to another. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @return number of bytes copied. + */ + public static long copy(@NonNull InputStream in, @NonNull OutputStream out) throws IOException { + return copy(in, out, null, null); + } + + /** + * Copy the contents of one stream to another. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @param listener to be periodically notified as the copy progresses. + * @param signal to signal if the copy should be cancelled early. + * @return number of bytes copied. + */ + public static long copy(@NonNull InputStream in, @NonNull OutputStream out, + @Nullable ProgressListener listener, @Nullable CancellationSignal signal) + throws IOException { + if (ENABLE_COPY_OPTIMIZATIONS) { + if (in instanceof FileInputStream && out instanceof FileOutputStream) { + return copy(((FileInputStream) in).getFD(), ((FileOutputStream) out).getFD(), + listener, signal); + } + } + + // Worse case fallback to userspace + return copyInternalUserspace(in, out, listener, signal); + } + + /** + * Copy the contents of one FD to another. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @return number of bytes copied. + */ + public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out) + throws IOException { + return copy(in, out, null, null); + } + + /** + * Copy the contents of one FD to another. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @param listener to be periodically notified as the copy progresses. + * @param signal to signal if the copy should be cancelled early. + * @return number of bytes copied. + */ + public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out, + @Nullable ProgressListener listener, @Nullable CancellationSignal signal) + throws IOException { + return copy(in, out, listener, signal, Long.MAX_VALUE); + } + + /** + * Copy the contents of one FD to another. + *

    + * Attempts to use several optimization strategies to copy the data in the + * kernel before falling back to a userspace copy as a last resort. + * + * @param listener to be periodically notified as the copy progresses. + * @param signal to signal if the copy should be cancelled early. + * @param count the number of bytes to copy. + * @return number of bytes copied. + */ + public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out, + @Nullable ProgressListener listener, @Nullable CancellationSignal signal, long count) + throws IOException { + if (ENABLE_COPY_OPTIMIZATIONS) { try { - out.getFD().sync(); - } catch (IOException e) { + final StructStat st_in = Os.fstat(in); + final StructStat st_out = Os.fstat(out); + if (S_ISREG(st_in.st_mode) && S_ISREG(st_out.st_mode)) { + return copyInternalSendfile(in, out, listener, signal, count); + } else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) { + return copyInternalSplice(in, out, listener, signal, count); + } + } catch (ErrnoException e) { + throw e.rethrowAsIOException(); + } + } + + // Worse case fallback to userspace + return copyInternalUserspace(in, out, listener, signal, count); + } + + /** + * Requires one of input or output to be a pipe. + */ + @VisibleForTesting + public static long copyInternalSplice(FileDescriptor in, FileDescriptor out, + ProgressListener listener, CancellationSignal signal, long count) + throws ErrnoException { + long progress = 0; + long checkpoint = 0; + + long t; + while ((t = Os.splice(in, null, out, null, Math.min(count, COPY_CHECKPOINT_BYTES), + SPLICE_F_MOVE | SPLICE_F_MORE)) != 0) { + progress += t; + checkpoint += t; + count -= t; + + if (checkpoint >= COPY_CHECKPOINT_BYTES) { + if (signal != null) { + signal.throwIfCanceled(); + } + if (listener != null) { + listener.onProgress(progress); + } + checkpoint = 0; } - out.close(); } + return progress; + } + + /** + * Requires both input and output to be a regular file. + */ + @VisibleForTesting + public static long copyInternalSendfile(FileDescriptor in, FileDescriptor out, + ProgressListener listener, CancellationSignal signal, long count) + throws ErrnoException { + long progress = 0; + long checkpoint = 0; + + long t; + while ((t = Os.sendfile(out, in, null, Math.min(count, COPY_CHECKPOINT_BYTES))) != 0) { + progress += t; + checkpoint += t; + count -= t; + + if (checkpoint >= COPY_CHECKPOINT_BYTES) { + if (signal != null) { + signal.throwIfCanceled(); + } + if (listener != null) { + listener.onProgress(progress); + } + checkpoint = 0; + } + } + return progress; + } + + @VisibleForTesting + public static long copyInternalUserspace(FileDescriptor in, FileDescriptor out, + ProgressListener listener, CancellationSignal signal, long count) throws IOException { + if (count != Long.MAX_VALUE) { + return copyInternalUserspace(new SizedInputStream(new FileInputStream(in), count), + new FileOutputStream(out), listener, signal); + } else { + return copyInternalUserspace(new FileInputStream(in), + new FileOutputStream(out), listener, signal); + } + } + + @VisibleForTesting + public static long copyInternalUserspace(InputStream in, OutputStream out, + ProgressListener listener, CancellationSignal signal) throws IOException { + long progress = 0; + long checkpoint = 0; + byte[] buffer = new byte[8192]; + + int t; + while ((t = in.read(buffer)) != -1) { + out.write(buffer, 0, t); + + progress += t; + checkpoint += t; + + if (checkpoint >= COPY_CHECKPOINT_BYTES) { + if (signal != null) { + signal.throwIfCanceled(); + } + if (listener != null) { + listener.onProgress(progress); + } + checkpoint = 0; + } + } + return progress; } /** @@ -797,4 +1040,69 @@ public class FileUtils { } return val * pow; } + + @VisibleForTesting + public static class MemoryPipe extends Thread implements AutoCloseable { + private final FileDescriptor[] pipe; + private final byte[] data; + private final boolean sink; + + private MemoryPipe(byte[] data, boolean sink) throws IOException { + try { + this.pipe = Os.pipe(); + } catch (ErrnoException e) { + throw e.rethrowAsIOException(); + } + this.data = data; + this.sink = sink; + } + + private MemoryPipe startInternal() { + super.start(); + return this; + } + + public static MemoryPipe createSource(byte[] data) throws IOException { + return new MemoryPipe(data, false).startInternal(); + } + + public static MemoryPipe createSink(byte[] data) throws IOException { + return new MemoryPipe(data, true).startInternal(); + } + + public FileDescriptor getFD() { + return sink ? pipe[1] : pipe[0]; + } + + public FileDescriptor getInternalFD() { + return sink ? pipe[0] : pipe[1]; + } + + @Override + public void run() { + final FileDescriptor fd = getInternalFD(); + try { + int i = 0; + while (i < data.length) { + if (sink) { + i += Os.read(fd, data, i, data.length - i); + } else { + i += Os.write(fd, data, i, data.length - i); + } + } + } catch (IOException | ErrnoException e) { + // Ignored + } finally { + if (sink) { + SystemClock.sleep(TimeUnit.SECONDS.toMillis(1)); + } + IoUtils.closeQuietly(fd); + } + } + + @Override + public void close() throws Exception { + IoUtils.closeQuietly(getFD()); + } + } } diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java index 2a088a659b0fb946a8e7e07553a790161605b6d8..cdee1101c27b8fecd32876a5a9ba920ff605b0a2 100644 --- a/core/java/android/os/HwBinder.java +++ b/core/java/android/os/HwBinder.java @@ -87,6 +87,9 @@ public abstract class HwBinder implements IHwBinder { * Configures how many threads the process-wide hwbinder threadpool * has to process incoming requests. * + * @param maxThreads total number of threads to create (includes this thread if + * callerWillJoin is true) + * @param callerWillJoin whether joinRpcThreadpool will be called in advance * @hide */ @SystemApi @@ -125,6 +128,12 @@ public abstract class HwBinder implements IHwBinder { /** * Enable instrumentation if available. + * + * On a non-user build, this method: + * - tries to enable atracing (if enabled) + * - tries to enable coverage dumps (if running in VTS) + * - tries to enable record and replay (if running in VTS) + * * @hide */ @SystemApi diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java index 0c592e1f04b8a654e759f8ade86c5e7e8eff98a2..a565dee5ddd010f73dc9784691e25fac83138512 100644 --- a/core/java/android/os/IHwBinder.java +++ b/core/java/android/os/IHwBinder.java @@ -30,6 +30,11 @@ public interface IHwBinder { /** * Process a hwbinder transaction. * + * @param code interface specific code for interface. + * @param request parceled transaction + * @param reply object to parcel reply into + * @param flags transaction flags to be chosen by wire protocol + * * @hide */ @SystemApi @@ -39,6 +44,7 @@ public interface IHwBinder { /** * Return as IHwInterface instance only if this implements descriptor. + * * @param descriptor for example foo.bar@1.0::IBaz * @hide */ @@ -53,6 +59,8 @@ public interface IHwBinder { public interface DeathRecipient { /** * Callback for a registered process dying. + * + * @param cookie cookie this death recipient was registered with. */ @SystemApi public void serviceDied(long cookie); @@ -61,11 +69,16 @@ public interface IHwBinder { /** * Notifies the death recipient with the cookie when the process containing * this binder dies. + * + * @param recipient callback object to be called on object death. + * @param cookie value to be given to callback on object death. */ @SystemApi public boolean linkToDeath(DeathRecipient recipient, long cookie); /** * Unregisters the death recipient from this binder. + * + * @param recipient callback to no longer recieve death notifications on this binder. */ @SystemApi public boolean unlinkToDeath(DeathRecipient recipient); diff --git a/core/java/android/os/IHwInterface.java b/core/java/android/os/IHwInterface.java index a2f59a9abb81464c696ebaa6dc76b9b54c8a1794..1d9e2b0197c7d559727fb94e1fb723c5dfe4e1a6 100644 --- a/core/java/android/os/IHwInterface.java +++ b/core/java/android/os/IHwInterface.java @@ -21,7 +21,7 @@ import android.annotation.SystemApi; @SystemApi public interface IHwInterface { /** - * Returns the binder object that corresponds to an interface. + * @return the binder object that corresponds to this interface. */ @SystemApi public IHwBinder asBinder(); diff --git a/core/java/android/os/IServiceManager.java b/core/java/android/os/IServiceManager.java index 2176a785e0a26264ee9fad2d53d4dc299756003a..89bf7b98a6c066a3f24e55221805dd5fd77a2e93 100644 --- a/core/java/android/os/IServiceManager.java +++ b/core/java/android/os/IServiceManager.java @@ -76,9 +76,15 @@ public interface IServiceManager extends IInterface int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0; int DUMP_FLAG_PRIORITY_HIGH = 1 << 1; int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2; + /** + * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the + * same priority as NORMAL priority but the services are not called with dump priority + * arguments. + */ + int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3; int DUMP_FLAG_PRIORITY_ALL = DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH - | DUMP_FLAG_PRIORITY_NORMAL; + | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT; /* Allows services to dump sections in protobuf format. */ - int DUMP_FLAG_PROTO = 1 << 3; + int DUMP_FLAG_PROTO = 1 << 4; } diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java index 1336c66b713333437400fd3019a8c24b704ddb41..9b6d6e56407ab2af53099c6282e7afe499add977 100644 --- a/core/java/android/os/IncidentManager.java +++ b/core/java/android/os/IncidentManager.java @@ -33,10 +33,12 @@ import android.util.Slog; @TestApi @SystemService(Context.INCIDENT_SERVICE) public class IncidentManager { - private static final String TAG = "incident"; + private static final String TAG = "IncidentManager"; private final Context mContext; + private IIncidentManager mService; + /** * @hide */ @@ -96,19 +98,45 @@ public class IncidentManager { reportIncidentInternal(args); } - private void reportIncidentInternal(IncidentReportArgs args) { - final IIncidentManager service = IIncidentManager.Stub.asInterface( - ServiceManager.getService(Context.INCIDENT_SERVICE)); - if (service == null) { - Slog.e(TAG, "reportIncident can't find incident binder service"); - return; + private class IncidentdDeathRecipient implements IBinder.DeathRecipient { + @Override + public void binderDied() { + synchronized (this) { + mService = null; + } } + } + private void reportIncidentInternal(IncidentReportArgs args) { try { + final IIncidentManager service = getIIncidentManagerLocked(); + if (service == null) { + Slog.e(TAG, "reportIncident can't find incident binder service"); + return; + } service.reportIncident(args); } catch (RemoteException ex) { Slog.e(TAG, "reportIncident failed", ex); } } + + private IIncidentManager getIIncidentManagerLocked() throws RemoteException { + if (mService != null) { + return mService; + } + + synchronized (this) { + if (mService != null) { + return mService; + } + mService = IIncidentManager.Stub.asInterface( + ServiceManager.getService(Context.INCIDENT_SERVICE)); + if (mService != null) { + mService.asBinder().linkToDeath(new IncidentdDeathRecipient(), 0); + } + return mService; + } + } + } diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java index fd0ebcfea080a8670641c635a58ce658cef0b0a2..9fa129cb98b491901d5236899f50f84fc80d1385 100644 --- a/core/java/android/os/IncidentReportArgs.java +++ b/core/java/android/os/IncidentReportArgs.java @@ -32,6 +32,9 @@ import java.util.ArrayList; @TestApi public final class IncidentReportArgs implements Parcelable { + private static final int DEST_EXPLICIT = 100; + private static final int DEST_AUTO = 200; + private final IntArray mSections = new IntArray(); private final ArrayList mHeaders = new ArrayList(); private boolean mAll; @@ -41,6 +44,7 @@ public final class IncidentReportArgs implements Parcelable { * Construct an incident report args with no fields. */ public IncidentReportArgs() { + mDest = DEST_AUTO; } /** @@ -143,7 +147,14 @@ public final class IncidentReportArgs implements Parcelable { * @hide */ public void setPrivacyPolicy(int dest) { - mDest = dest; + switch (dest) { + case DEST_EXPLICIT: + case DEST_AUTO: + mDest = dest; + break; + default: + mDest = DEST_AUTO; + } } /** diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index 42ec315c10e0c5251e983d275d318c2adec5bf61..3be76d6049f4a03e8762ae8ce63f639c84810d60 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -83,7 +83,7 @@ public final class ServiceManager { * @param service the service object */ public static void addService(String name, IBinder service) { - addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_NORMAL); + addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); } /** @@ -96,7 +96,7 @@ public final class ServiceManager { * to access this service */ public static void addService(String name, IBinder service, boolean allowIsolated) { - addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_NORMAL); + addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); } /** diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index b2b43cfd6ddc3b23072780589d41899c9a0545fc..2093cec769da44387d2b03c6d51073012675474a 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -393,8 +393,9 @@ public class UserManager { public static final String DISALLOW_CONFIG_VPN = "no_config_vpn"; /** - * Specifies if a user is disallowed from configuring location mode. Device owner and profile - * owners can set this restriction and it only applies on the managed user. + * Specifies if a user is disallowed from enabling or disabling location providers. As a + * result, user is disallowed from turning on or off location. Device owner and profile owners + * can set this restriction and it only applies on the managed user. * *

    In a managed profile, location sharing is forced off when it's off on primary user, so * user can still turn off location sharing on managed profile when the restriction is set by @@ -408,11 +409,12 @@ public class UserManager { * *

    Key for user restrictions. *

    Type: Boolean + * @see android.location.LocationManager#isProviderEnabled(String) * @see DevicePolicyManager#addUserRestriction(ComponentName, String) * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) * @see #getUserRestrictions() */ - public static final String DISALLOW_CONFIG_LOCATION_MODE = "no_config_location_mode"; + public static final String DISALLOW_CONFIG_LOCATION = "no_config_location"; /** * Specifies if date, time and timezone configuring is disallowed. diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index f4deeedae69747fb65a67c3bc58ebfcbd12f1102..f593e8056db95a05227d5d6df6140b5209d7907e 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1096,7 +1096,7 @@ public class StorageManager { public @NonNull List getStorageVolumes() { final ArrayList res = new ArrayList<>(); Collections.addAll(res, - getVolumeList(UserHandle.myUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE)); + getVolumeList(mContext.getUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE)); return res; } @@ -1107,7 +1107,7 @@ public class StorageManager { * {@link Context#getExternalFilesDir(String)}. */ public @NonNull StorageVolume getPrimaryStorageVolume() { - return getVolumeList(UserHandle.myUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE)[0]; + return getVolumeList(mContext.getUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE)[0]; } /** {@hide} */ diff --git a/core/java/android/print/PrintFileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java index 747400d486bf9a7dafa59f993d28032207555a8b..a5f93050e3078f6372de9ddd0a0d45850a88c3f5 100644 --- a/core/java/android/print/PrintFileDocumentAdapter.java +++ b/core/java/android/print/PrintFileDocumentAdapter.java @@ -21,6 +21,8 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.CancellationSignal; import android.os.CancellationSignal.OnCancelListener; +import android.os.FileUtils; +import android.os.OperationCanceledException; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -114,28 +116,15 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter { @Override protected Void doInBackground(Void... params) { - InputStream in = null; - OutputStream out = new FileOutputStream(mDestination.getFileDescriptor()); - final byte[] buffer = new byte[8192]; - try { - in = new FileInputStream(mFile); - while (true) { - if (isCancelled()) { - break; - } - final int readByteCount = in.read(buffer); - if (readByteCount < 0) { - break; - } - out.write(buffer, 0, readByteCount); - } - } catch (IOException ioe) { - Log.e(LOG_TAG, "Error writing data!", ioe); - mResultCallback.onWriteFailed(mContext.getString( - R.string.write_fail_reason_cannot_write)); - } finally { - IoUtils.closeQuietly(in); - IoUtils.closeQuietly(out); + try (InputStream in = new FileInputStream(mFile); + OutputStream out = new FileOutputStream(mDestination.getFileDescriptor())) { + FileUtils.copy(in, out, null, mCancellationSignal); + } catch (OperationCanceledException e) { + // Ignored; already handled below + } catch (IOException e) { + Log.e(LOG_TAG, "Error writing data!", e); + mResultCallback.onWriteFailed(mContext.getString( + R.string.write_fail_reason_cannot_write)); } return null; } diff --git a/core/java/android/provider/ContactsInternal.java b/core/java/android/provider/ContactsInternal.java index 2cd1d48e7dc1cf2c65076832cc27aad91275392f..362eba93aaba0d120ec06e05bed04c77f909384e 100644 --- a/core/java/android/provider/ContactsInternal.java +++ b/core/java/android/provider/ContactsInternal.java @@ -68,7 +68,7 @@ public class ContactsInternal { } } // Launch on the current profile. - startQuickContactWithErrorToastForUser(context, intent, Process.myUserHandle()); + startQuickContactWithErrorToastForUser(context, intent, context.getUser()); } public static void startQuickContactWithErrorToastForUser(Context context, Intent intent, diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2440b489f41621bbfe4efa9587e7c6040585924a..e709c532200b6e201bfd3093996d6f4b9e1bfbf2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1903,7 +1903,7 @@ public final class Settings { cp.call(cr.getPackageName(), mCallSetCommand, name, arg); String newValue = getStringForUser(cr, name, userHandle); StatsLog.write(StatsLog.SETTING_CHANGED, name, value, newValue, prevValue, tag, - makeDefault ? 1 : 0, userHandle); + makeDefault, userHandle); } catch (RemoteException e) { Log.w(TAG, "Can't set key " + name + " in " + mUri, e); return false; @@ -2255,7 +2255,7 @@ public final class Settings { * @return the corresponding value, or null if not present */ public static String getString(ContentResolver resolver, String name) { - return getStringForUser(resolver, name, UserHandle.myUserId()); + return getStringForUser(resolver, name, resolver.getUserId()); } /** @hide */ @@ -2282,7 +2282,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putString(ContentResolver resolver, String name, String value) { - return putStringForUser(resolver, name, value, UserHandle.myUserId()); + return putStringForUser(resolver, name, value, resolver.getUserId()); } /** @hide */ @@ -2336,7 +2336,7 @@ public final class Settings { * or not a valid integer. */ public static int getInt(ContentResolver cr, String name, int def) { - return getIntForUser(cr, name, def, UserHandle.myUserId()); + return getIntForUser(cr, name, def, cr.getUserId()); } /** @hide */ @@ -2369,7 +2369,7 @@ public final class Settings { */ public static int getInt(ContentResolver cr, String name) throws SettingNotFoundException { - return getIntForUser(cr, name, UserHandle.myUserId()); + return getIntForUser(cr, name, cr.getUserId()); } /** @hide */ @@ -2397,7 +2397,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putInt(ContentResolver cr, String name, int value) { - return putIntForUser(cr, name, value, UserHandle.myUserId()); + return putIntForUser(cr, name, value, cr.getUserId()); } /** @hide */ @@ -2421,7 +2421,7 @@ public final class Settings { * or not a valid {@code long}. */ public static long getLong(ContentResolver cr, String name, long def) { - return getLongForUser(cr, name, def, UserHandle.myUserId()); + return getLongForUser(cr, name, def, cr.getUserId()); } /** @hide */ @@ -2456,7 +2456,7 @@ public final class Settings { */ public static long getLong(ContentResolver cr, String name) throws SettingNotFoundException { - return getLongForUser(cr, name, UserHandle.myUserId()); + return getLongForUser(cr, name, cr.getUserId()); } /** @hide */ @@ -2484,7 +2484,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putLong(ContentResolver cr, String name, long value) { - return putLongForUser(cr, name, value, UserHandle.myUserId()); + return putLongForUser(cr, name, value, cr.getUserId()); } /** @hide */ @@ -2508,7 +2508,7 @@ public final class Settings { * or not a valid float. */ public static float getFloat(ContentResolver cr, String name, float def) { - return getFloatForUser(cr, name, def, UserHandle.myUserId()); + return getFloatForUser(cr, name, def, cr.getUserId()); } /** @hide */ @@ -2542,7 +2542,7 @@ public final class Settings { */ public static float getFloat(ContentResolver cr, String name) throws SettingNotFoundException { - return getFloatForUser(cr, name, UserHandle.myUserId()); + return getFloatForUser(cr, name, cr.getUserId()); } /** @hide */ @@ -2573,7 +2573,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putFloat(ContentResolver cr, String name, float value) { - return putFloatForUser(cr, name, value, UserHandle.myUserId()); + return putFloatForUser(cr, name, value, cr.getUserId()); } /** @hide */ @@ -2591,7 +2591,7 @@ public final class Settings { * @param outConfig Where to place the configuration settings. */ public static void getConfiguration(ContentResolver cr, Configuration outConfig) { - adjustConfigurationForUser(cr, outConfig, UserHandle.myUserId(), + adjustConfigurationForUser(cr, outConfig, cr.getUserId(), false /* updateSettingsIfEmpty */); } @@ -2644,7 +2644,7 @@ public final class Settings { * @return true if the values were set, false on database errors */ public static boolean putConfiguration(ContentResolver cr, Configuration config) { - return putConfigurationForUser(cr, config, UserHandle.myUserId()); + return putConfigurationForUser(cr, config, cr.getUserId()); } /** @hide */ @@ -2664,7 +2664,7 @@ public final class Settings { /** @deprecated - Do not use */ @Deprecated public static boolean getShowGTalkServiceStatus(ContentResolver cr) { - return getShowGTalkServiceStatusForUser(cr, UserHandle.myUserId()); + return getShowGTalkServiceStatusForUser(cr, cr.getUserId()); } /** @@ -2680,7 +2680,7 @@ public final class Settings { /** @deprecated - Do not use */ @Deprecated public static void setShowGTalkServiceStatus(ContentResolver cr, boolean flag) { - setShowGTalkServiceStatusForUser(cr, flag, UserHandle.myUserId()); + setShowGTalkServiceStatusForUser(cr, flag, cr.getUserId()); } /** @@ -3691,6 +3691,20 @@ public final class Settings { public static final Validator TTY_MODE_VALIDATOR = new SettingsValidators.InclusiveIntegerRangeValidator(0, 3); + /** + * User-selected RTT mode + * 0 = OFF + * 1 = FULL + * 2 = VCO + * 3 = HCO + * Uses the same constants as TTY (e.g. {@link android.telecom.TelecomManager#TTY_MODE_OFF}) + * @hide + */ + public static final String RTT_CALLING_MODE = "rtt_calling_mode"; + + /** @hide */ + public static final Validator RTT_CALLING_MODE_VALIDATOR = TTY_MODE_VALIDATOR; + /** * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is * boolean (1 or 0). @@ -4016,6 +4030,7 @@ public final class Settings { DTMF_TONE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING, HEARING_AID, + RTT_CALLING_MODE, TTY_MODE, MASTER_MONO, SOUND_EFFECTS_ENABLED, @@ -4214,6 +4229,7 @@ public final class Settings { VALIDATORS.put(DTMF_TONE_TYPE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR); VALIDATORS.put(HEARING_AID, HEARING_AID_VALIDATOR); VALIDATORS.put(TTY_MODE, TTY_MODE_VALIDATOR); + VALIDATORS.put(RTT_CALLING_MODE, RTT_CALLING_MODE_VALIDATOR); VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, NOTIFICATION_LIGHT_PULSE_VALIDATOR); VALIDATORS.put(POINTER_LOCATION, POINTER_LOCATION_VALIDATOR); VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR); @@ -4732,7 +4748,7 @@ public final class Settings { * @return the corresponding value, or null if not present */ public static String getString(ContentResolver resolver, String name) { - return getStringForUser(resolver, name, UserHandle.myUserId()); + return getStringForUser(resolver, name, resolver.getUserId()); } /** @hide */ @@ -4786,7 +4802,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putString(ContentResolver resolver, String name, String value) { - return putStringForUser(resolver, name, value, UserHandle.myUserId()); + return putStringForUser(resolver, name, value, resolver.getUserId()); } /** @hide */ @@ -4859,7 +4875,7 @@ public final class Settings { @NonNull String name, @Nullable String value, @Nullable String tag, boolean makeDefault) { return putStringForUser(resolver, name, value, tag, makeDefault, - UserHandle.myUserId()); + resolver.getUserId()); } /** @@ -4880,7 +4896,7 @@ public final class Settings { public static void resetToDefaults(@NonNull ContentResolver resolver, @Nullable String tag) { resetToDefaultsAsUser(resolver, tag, RESET_MODE_PACKAGE_DEFAULTS, - UserHandle.myUserId()); + resolver.getUserId()); } /** @@ -4947,7 +4963,7 @@ public final class Settings { * or not a valid integer. */ public static int getInt(ContentResolver cr, String name, int def) { - return getIntForUser(cr, name, def, UserHandle.myUserId()); + return getIntForUser(cr, name, def, cr.getUserId()); } /** @hide */ @@ -4984,7 +5000,7 @@ public final class Settings { */ public static int getInt(ContentResolver cr, String name) throws SettingNotFoundException { - return getIntForUser(cr, name, UserHandle.myUserId()); + return getIntForUser(cr, name, cr.getUserId()); } /** @hide */ @@ -5016,7 +5032,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putInt(ContentResolver cr, String name, int value) { - return putIntForUser(cr, name, value, UserHandle.myUserId()); + return putIntForUser(cr, name, value, cr.getUserId()); } /** @hide */ @@ -5040,7 +5056,7 @@ public final class Settings { * or not a valid {@code long}. */ public static long getLong(ContentResolver cr, String name, long def) { - return getLongForUser(cr, name, def, UserHandle.myUserId()); + return getLongForUser(cr, name, def, cr.getUserId()); } /** @hide */ @@ -5075,7 +5091,7 @@ public final class Settings { */ public static long getLong(ContentResolver cr, String name) throws SettingNotFoundException { - return getLongForUser(cr, name, UserHandle.myUserId()); + return getLongForUser(cr, name, cr.getUserId()); } /** @hide */ @@ -5103,7 +5119,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putLong(ContentResolver cr, String name, long value) { - return putLongForUser(cr, name, value, UserHandle.myUserId()); + return putLongForUser(cr, name, value, cr.getUserId()); } /** @hide */ @@ -5127,7 +5143,7 @@ public final class Settings { * or not a valid float. */ public static float getFloat(ContentResolver cr, String name, float def) { - return getFloatForUser(cr, name, def, UserHandle.myUserId()); + return getFloatForUser(cr, name, def, cr.getUserId()); } /** @hide */ @@ -5161,7 +5177,7 @@ public final class Settings { */ public static float getFloat(ContentResolver cr, String name) throws SettingNotFoundException { - return getFloatForUser(cr, name, UserHandle.myUserId()); + return getFloatForUser(cr, name, cr.getUserId()); } /** @hide */ @@ -5192,7 +5208,7 @@ public final class Settings { * @return true if the value was set, false on database errors */ public static boolean putFloat(ContentResolver cr, String name, float value) { - return putFloatForUser(cr, name, value, UserHandle.myUserId()); + return putFloatForUser(cr, name, value, cr.getUserId()); } /** @hide */ @@ -7999,7 +8015,7 @@ public final class Settings { */ @Deprecated public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { - return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId()); + return isLocationProviderEnabledForUser(cr, provider, cr.getUserId()); } /** @@ -8031,7 +8047,7 @@ public final class Settings { @Deprecated public static final void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { - setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId()); + setLocationProviderEnabledForUser(cr, provider, enabled, cr.getUserId()); } /** @@ -9314,17 +9330,6 @@ public final class Settings { private static final Validator WIFI_WAKEUP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** - * Value to specify if Wi-Fi Wakeup is available. - * - * Wi-Fi Wakeup will only operate if it's available - * and {@link #WIFI_WAKEUP_ENABLED} is true. - * - * Type: int (0 for false, 1 for true) - * @hide - */ - public static final String WIFI_WAKEUP_AVAILABLE = "wifi_wakeup_available"; - /** * Value to specify whether network quality scores and badging should be shown in the UI. * @@ -10265,6 +10270,20 @@ public final class Settings { */ public static final String BATTERY_TIP_CONSTANTS = "battery_tip_constants"; + /** + * An integer to show the version of the anomaly config. Ex: 1, which means + * current version is 1. + * @hide + */ + public static final String ANOMALY_CONFIG_VERSION = "anomaly_config_version"; + + /** + * A base64-encoded string represents anomaly stats config, used for + * {@link android.app.StatsManager}. + * @hide + */ + public static final String ANOMALY_CONFIG = "anomaly_config"; + /** * Always on display(AOD) specific settings * This is encoded as a key=value list, separated by commas. Ex: @@ -10303,6 +10322,15 @@ public final class Settings { */ public static final String FPS_DEVISOR = "fps_divisor"; + /** + * Flag to enable or disable display panel low power mode (lpm) + * false -> Display panel power saving mode is disabled. + * true -> Display panel power saving mode is enabled. + * + * @hide + */ + public static final String DISPLAY_PANEL_LPM = "display_panel_lpm"; + /** * App standby (app idle) specific settings. * This is encoded as a key=value list, separated by commas. Ex: @@ -10519,6 +10547,18 @@ public final class Settings { */ public static final String NETWORK_WATCHLIST_ENABLED = "network_watchlist_enabled"; + /** + * Flag to keep background restricted profiles running after exiting. If disabled, + * the restricted profile can be put into stopped state as soon as the user leaves it. + * Type: int (0 for false, 1 for true) + * + * Overridden by the system based on device information. If null, the value specified + * by {@code config_keepRestrictedProfilesInBackground} is used. + * + * @hide + */ + public static final String KEEP_PROFILE_IN_BACKGROUND = "keep_profile_in_background"; + /** * Get the key that retrieves a bluetooth headset's priority. * @hide @@ -10738,14 +10778,14 @@ public final class Settings { public static final String LOW_POWER_MODE = "low_power"; /** - * Battery level [1-99] at which low power mode automatically turns on. + * Battery level [1-100] at which low power mode automatically turns on. * If 0, it will not automatically turn on. * @hide */ public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level"; private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR = - new SettingsValidators.InclusiveIntegerRangeValidator(0, 99); + new SettingsValidators.InclusiveIntegerRangeValidator(0, 100); /** * If not 0, the activity manager will aggressively finish activities and @@ -11331,6 +11371,15 @@ public final class Settings { public static final String CHAINED_BATTERY_ATTRIBUTION_ENABLED = "chained_battery_attribution_enabled"; + /** + * The packages whitelisted to be run in autofill compatibility mode. + * + * @hide + */ + @SystemApi + public static final String AUTOFILL_COMPAT_ALLOWED_PACKAGES = + "autofill_compat_allowed_packages"; + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. @@ -11466,7 +11515,7 @@ public final class Settings { * @return the corresponding value, or null if not present */ public static String getString(ContentResolver resolver, String name) { - return getStringForUser(resolver, name, UserHandle.myUserId()); + return getStringForUser(resolver, name, resolver.getUserId()); } /** @hide */ @@ -11489,7 +11538,7 @@ public final class Settings { */ public static boolean putString(ContentResolver resolver, String name, String value) { - return putStringForUser(resolver, name, value, null, false, UserHandle.myUserId()); + return putStringForUser(resolver, name, value, null, false, resolver.getUserId()); } /** @@ -11538,7 +11587,7 @@ public final class Settings { @NonNull String name, @Nullable String value, @Nullable String tag, boolean makeDefault) { return putStringForUser(resolver, name, value, tag, makeDefault, - UserHandle.myUserId()); + resolver.getUserId()); } /** @@ -11559,7 +11608,7 @@ public final class Settings { public static void resetToDefaults(@NonNull ContentResolver resolver, @Nullable String tag) { resetToDefaultsAsUser(resolver, tag, RESET_MODE_PACKAGE_DEFAULTS, - UserHandle.myUserId()); + resolver.getUserId()); } /** @@ -11873,8 +11922,6 @@ public final class Settings { */ public static final String MULTI_SIM_SMS_PROMPT = "multi_sim_sms_prompt"; - - /** User preferred subscriptions setting. * This holds the details of the user selected subscription from the card and * the activation status. Each settings string have the comma separated values diff --git a/core/java/android/se/omapi/Channel.java b/core/java/android/se/omapi/Channel.java index f0b9fa2de5d27d20b19bbfc1065192423857628c..65ce67fcba8f37edf19d38b4e5b9bc803d45fd86 100644 --- a/core/java/android/se/omapi/Channel.java +++ b/core/java/android/se/omapi/Channel.java @@ -25,6 +25,7 @@ package android.se.omapi; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import java.io.IOException; @@ -168,8 +169,10 @@ public class Channel { throw new IOException("Error in communicating with Secure Element"); } return response; - } catch (RemoteException e) { + } catch (ServiceSpecificException e) { throw new IOException(e.getMessage()); + } catch (RemoteException e) { + throw new IllegalStateException(e.getMessage()); } } } @@ -244,8 +247,10 @@ public class Channel { synchronized (mLock) { return mChannel.selectNext(); } - } catch (RemoteException e) { + } catch (ServiceSpecificException e) { throw new IOException(e.getMessage()); + } catch (RemoteException e) { + throw new IllegalStateException(e.getMessage()); } } } diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java index 9f1573973be4e8d4c5dfafb9e3d38ceb8b355d0d..3dec97631e9c81b2920fdfd46efd604cce5d28d7 100644 --- a/core/java/android/se/omapi/Reader.java +++ b/core/java/android/se/omapi/Reader.java @@ -24,6 +24,7 @@ package android.se.omapi; import android.annotation.NonNull; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import java.io.IOException; @@ -45,8 +46,7 @@ public class Reader { private final Object mLock = new Object(); - Reader(SEService service, String name, ISecureElementReader reader) throws - IOException { + Reader(SEService service, String name, ISecureElementReader reader) { if (reader == null || service == null || name == null) { throw new IllegalArgumentException("Parameters cannot be null"); } @@ -96,8 +96,10 @@ public class Reader { ISecureElementSession session; try { session = mReader.openSession(); - } catch (RemoteException e) { + } catch (ServiceSpecificException e) { throw new IOException(e.getMessage()); + } catch (RemoteException e) { + throw new IllegalStateException(e.getMessage()); } if (session == null) { throw new IOException("service session is null."); diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java index 1e37277dcd6d34e96d6b8fa83e57ced564140efc..b8937e69c1432796a7c83b5572b4afc6dc1c6a57 100644 --- a/core/java/android/se/omapi/SEService.java +++ b/core/java/android/se/omapi/SEService.java @@ -42,6 +42,23 @@ import java.util.HashMap; */ public class SEService { + /** + * Error code used with ServiceSpecificException. + * Thrown if there was an error communicating with the Secure Element. + * + * @hide + */ + public static final int IO_ERROR = 1; + + /** + * Error code used with ServiceSpecificException. + * Thrown if AID cannot be selected or is not available when opening + * a logical channel. + * + * @hide + */ + public static final int NO_SUCH_ELEMENT_ERROR = 2; + private static final String TAG = "OMAPI.SEService"; private final Object mLock = new Object(); diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java index bb2a0327ee0da8c8fb710c2b32de73b5510c46a6..19a018ee01bbcf6a71fab4a84bfa8dbed2771661 100644 --- a/core/java/android/se/omapi/Session.java +++ b/core/java/android/se/omapi/Session.java @@ -25,6 +25,7 @@ package android.se.omapi; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import java.io.IOException; @@ -207,8 +208,16 @@ public class Session { return null; } return new Channel(mService, this, channel); + } catch (ServiceSpecificException e) { + if (e.errorCode == SEService.IO_ERROR) { + throw new IOException(e.getMessage()); + } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) { + throw new NoSuchElementException(e.getMessage()); + } else { + throw new IllegalStateException(e.getMessage()); + } } catch (RemoteException e) { - throw new IOException(e.getMessage()); + throw new IllegalStateException(e.getMessage()); } } } @@ -311,8 +320,16 @@ public class Session { return null; } return new Channel(mService, this, channel); + } catch (ServiceSpecificException e) { + if (e.errorCode == SEService.IO_ERROR) { + throw new IOException(e.getMessage()); + } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) { + throw new NoSuchElementException(e.getMessage()); + } else { + throw new IllegalStateException(e.getMessage()); + } } catch (RemoteException e) { - throw new IOException(e.getMessage()); + throw new IllegalStateException(e.getMessage()); } } } diff --git a/core/java/android/security/ConfirmationAlreadyPresentingException.java b/core/java/android/security/ConfirmationAlreadyPresentingException.java new file mode 100644 index 0000000000000000000000000000000000000000..ae4ec5a1bf45da6c5823e5f63f6b9566836d0fa6 --- /dev/null +++ b/core/java/android/security/ConfirmationAlreadyPresentingException.java @@ -0,0 +1,29 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +/** + * This exception is thrown when presenting a prompt fails because another prompt is already + * being presented. + */ +public class ConfirmationAlreadyPresentingException extends Exception { + public ConfirmationAlreadyPresentingException() {} + + public ConfirmationAlreadyPresentingException(String message) { + super(message); + } +} diff --git a/core/java/android/security/ConfirmationCallback.java b/core/java/android/security/ConfirmationCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..4670bce3a9e0dac13d18d0d2dec6175a55f59da1 --- /dev/null +++ b/core/java/android/security/ConfirmationCallback.java @@ -0,0 +1,54 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.annotation.NonNull; + +/** + * Callback class used when signaling that a prompt is no longer being presented. + */ +public abstract class ConfirmationCallback { + /** + * Called when the requested prompt was accepted by the user. + * + * The format of 'dataThatWasConfirmed' parameter is a CBOR + * encoded map (type 5) with (at least) the keys prompt and + * extra. The keys are encoded as CBOR text string (type 3). The value of + * promptText is encoded as CBOR text string (type 3), and the value of extraData is encoded as + * CBOR byte string (type 2). Other keys may be added in the future. + * + * @param dataThatWasConfirmed the data that was confirmed, see above for the format. + */ + public void onConfirmedByUser(@NonNull byte[] dataThatWasConfirmed) {} + + /** + * Called when the requested prompt was dismissed (not accepted) by the user. + */ + public void onDismissedByUser() {} + + /** + * Called when the requested prompt was dismissed by the application. + */ + public void onDismissedByApplication() {} + + /** + * Called when the requested prompt was dismissed because of a low-level error. + * + * @param e an exception representing the error. + */ + public void onError(Exception e) {} +} diff --git a/core/java/android/security/ConfirmationDialog.java b/core/java/android/security/ConfirmationDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..e9df3705db6ef4eb17ad8383d1cd17f2f71729ee --- /dev/null +++ b/core/java/android/security/ConfirmationDialog.java @@ -0,0 +1,283 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.annotation.NonNull; +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import java.util.Locale; +import java.util.concurrent.Executor; + +/** + * Class used for displaying confirmation prompts. + * + *

    Confirmation prompts are prompts shown to the user to confirm a given text and are + * implemented in a way that a positive response indicates with high confidence that the user has + * seen the given text, even if the Android framework (including the kernel) was + * compromised. Implementing confirmation prompts with these guarantees requires dedicated + * hardware-support and may not always be available. + * + *

    Confirmation prompts are typically used with an external entitity - the Relying Party - + * in the following way. The setup steps are as follows: + *

      + *
    • Before first use, the application generates a key-pair with the + * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired + * CONFIRMATION tag} set. Device attestation, + * e.g. {@link java.security.KeyStore#getCertificateChain getCertificateChain()}, is used to + * generate a certificate chain that includes the public key (Kpub in the following) + * of the newly generated key. + *
    • The application sends Kpub and the certificate chain resulting from device + * attestation to the Relying Party. + *
    • The Relying Party validates the certificate chain which involves checking the root + * certificate is what is expected (e.g. a certificate from Google), each certificate signs the + * next one in the chain, ending with Kpub, and that the attestation certificate + * asserts that Kpub has the + * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired + * CONFIRMATION tag} set. + * Additionally the relying party stores Kpub and associates it with the device + * it was received from. + *
    + * + *

    The Relying Party is typically an external device (for example connected via + * Bluetooth) or application server. + * + *

    Before executing a transaction which requires a high assurance of user content, the + * application does the following: + *

      + *
    • The application gets a cryptographic nonce from the Relying Party and passes this as + * the extraData (via the Builder helper class) to the + * {@link #presentPrompt presentPrompt()} method. The Relying Party stores the nonce locally + * since it'll use it in a later step. + *
    • If the user approves the prompt a Confirmation Response is returned in the + * {@link ConfirmationCallback#onConfirmedByUser onConfirmedByUser(byte[])} callback as the + * dataThatWasConfirmed parameter. This blob contains the text that was shown to the + * user, the extraData parameter, and possibly other data. + *
    • The application signs the Confirmation Response with the previously created key and + * sends the blob and the signature to the Relying Party. + *
    • The Relying Party checks that the signature was made with Kpub and then + * extracts promptText matches what is expected and extraData matches the + * previously created nonce. If all checks passes, the transaction is executed. + *
    + * + *

    A common way of implementing the "promptText is what is expected" check in the + * last bullet, is to have the Relying Party generate promptText and store it + * along the nonce in the extraData blob. + */ +public class ConfirmationDialog { + private static final String TAG = "ConfirmationDialog"; + + private CharSequence mPromptText; + private byte[] mExtraData; + private ConfirmationCallback mCallback; + private Executor mExecutor; + + private final KeyStore mKeyStore = KeyStore.getInstance(); + + private void doCallback(int responseCode, byte[] dataThatWasConfirmed, + ConfirmationCallback callback) { + switch (responseCode) { + case KeyStore.CONFIRMATIONUI_OK: + callback.onConfirmedByUser(dataThatWasConfirmed); + break; + + case KeyStore.CONFIRMATIONUI_CANCELED: + callback.onDismissedByUser(); + break; + + case KeyStore.CONFIRMATIONUI_ABORTED: + callback.onDismissedByApplication(); + break; + + case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR: + callback.onError(new Exception("System error returned by ConfirmationUI.")); + break; + + default: + callback.onError(new Exception("Unexpected responseCode=" + responseCode + + " from onConfirmtionPromptCompleted() callback.")); + break; + } + } + + private final android.os.IBinder mCallbackBinder = + new android.security.IConfirmationPromptCallback.Stub() { + @Override + public void onConfirmationPromptCompleted( + int responseCode, final byte[] dataThatWasConfirmed) + throws android.os.RemoteException { + if (mCallback != null) { + ConfirmationCallback callback = mCallback; + Executor executor = mExecutor; + mCallback = null; + mExecutor = null; + if (executor == null) { + doCallback(responseCode, dataThatWasConfirmed, callback); + } else { + executor.execute(new Runnable() { + @Override + public void run() { + doCallback(responseCode, dataThatWasConfirmed, callback); + } + }); + } + } + } + }; + + /** + * A builder that collects arguments, to be shown on the system-provided confirmation dialog. + */ + public static class Builder { + + private CharSequence mPromptText; + private byte[] mExtraData; + + /** + * Creates a builder for the confirmation dialog. + */ + public Builder() { + } + + /** + * Sets the prompt text for the dialog. + * + * @param promptText the text to present in the prompt. + * @return the builder. + */ + public Builder setPromptText(CharSequence promptText) { + mPromptText = promptText; + return this; + } + + /** + * Sets the extra data for the dialog. + * + * @param extraData data to include in the response data. + * @return the builder. + */ + public Builder setExtraData(byte[] extraData) { + mExtraData = extraData; + return this; + } + + /** + * Creates a {@link ConfirmationDialog} with the arguments supplied to this builder. + * + * @param context the application context + * @return a {@link ConfirmationDialog} + * @throws IllegalArgumentException if any of the required fields are not set. + */ + public ConfirmationDialog build(Context context) { + if (TextUtils.isEmpty(mPromptText)) { + throw new IllegalArgumentException("prompt text must be set and non-empty"); + } + if (mExtraData == null) { + throw new IllegalArgumentException("extraData must be set"); + } + return new ConfirmationDialog(mPromptText, mExtraData); + } + } + + private ConfirmationDialog(CharSequence promptText, byte[] extraData) { + mPromptText = promptText; + mExtraData = extraData; + } + + /** + * Requests a confirmation prompt to be presented to the user. + * + * When the prompt is no longer being presented, one of the methods in + * {@link ConfirmationCallback} is called on the supplied callback object. + * + * @param executor the executor identifying the thread that will receive the callback. + * @param callback the callback to use when the dialog is done showing. + * @throws IllegalArgumentException if the prompt text is too long or malfomed. + * @throws ConfirmationAlreadyPresentingException if another prompt is being presented. + * @throws ConfirmationNotAvailableException if confirmation prompts are not supported. + */ + public void presentPrompt(@NonNull Executor executor, @NonNull ConfirmationCallback callback) + throws ConfirmationAlreadyPresentingException, + ConfirmationNotAvailableException { + if (mCallback != null) { + throw new ConfirmationAlreadyPresentingException(); + } + mCallback = callback; + mExecutor = executor; + + int uiOptionsAsFlags = 0; + // TODO: set AccessibilityInverted, AccessibilityMagnified in uiOptionsAsFlags as needed. + String locale = Locale.getDefault().toLanguageTag(); + int responseCode = mKeyStore.presentConfirmationPrompt( + mCallbackBinder, mPromptText.toString(), mExtraData, locale, uiOptionsAsFlags); + switch (responseCode) { + case KeyStore.CONFIRMATIONUI_OK: + return; + + case KeyStore.CONFIRMATIONUI_OPERATION_PENDING: + throw new ConfirmationAlreadyPresentingException(); + + case KeyStore.CONFIRMATIONUI_UNIMPLEMENTED: + throw new ConfirmationNotAvailableException(); + + case KeyStore.CONFIRMATIONUI_UIERROR: + throw new IllegalArgumentException(); + + default: + // Unexpected error code. + Log.w(TAG, + "Unexpected responseCode=" + responseCode + + " from presentConfirmationPrompt() call."); + throw new IllegalArgumentException(); + } + } + + /** + * Cancels a prompt currently being displayed. + * + * On success, the + * {@link ConfirmationCallback#onDismissedByApplication onDismissedByApplication()} method on + * the supplied callback object will be called asynchronously. + * + * @throws IllegalStateException if no prompt is currently being presented. + */ + public void cancelPrompt() { + int responseCode = mKeyStore.cancelConfirmationPrompt(mCallbackBinder); + if (responseCode == KeyStore.CONFIRMATIONUI_OK) { + return; + } else if (responseCode == KeyStore.CONFIRMATIONUI_OPERATION_PENDING) { + throw new IllegalStateException(); + } else { + // Unexpected error code. + Log.w(TAG, + "Unexpected responseCode=" + responseCode + + " from cancelConfirmationPrompt() call."); + throw new IllegalStateException(); + } + } + + /** + * Checks if the device supports confirmation prompts. + * + * @return true if confirmation prompts are supported by the device. + */ + public static boolean isSupported() { + // TODO: read and return system property. + return true; + } +} diff --git a/core/java/android/security/ConfirmationNotAvailableException.java b/core/java/android/security/ConfirmationNotAvailableException.java new file mode 100644 index 0000000000000000000000000000000000000000..8d0e672c0671e72896361c2eb8255df48d51260b --- /dev/null +++ b/core/java/android/security/ConfirmationNotAvailableException.java @@ -0,0 +1,30 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +/** + * This exception is thrown when presenting a prompt fails because the the environment lacks + * facilities for showing confirmations. + */ +public class ConfirmationNotAvailableException extends Exception { + public ConfirmationNotAvailableException() { + } + + public ConfirmationNotAvailableException(String message) { + super(message); + } +} diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index 346437032845011c60e59d88e3460090e9c7b2ef..1d13335043508b11e21304a4658437635a0e7b2e 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -74,6 +74,7 @@ public final class KeymasterDefs { public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505; public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506; public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507; + public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508; public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600; public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601; diff --git a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java index a43952a8104871716cdea793c12f5ef118d9faea..aa09f10de0705c774396dd233917d1348d501ae0 100644 --- a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java +++ b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java @@ -235,17 +235,7 @@ public final class KeyChainProtectionParams implements Parcelable { } /** - * Removes secret from memory than object is no longer used. - * Since finalizer call is not reliable, please use @link {#clearSecret} directly. - */ - @Override - protected void finalize() throws Throwable { - clearSecret(); - super.finalize(); - } - - /** - * Fills mSecret with zeroes. + * Fills secret with zeroes. */ public void clearSecret() { Arrays.fill(mSecret, (byte) 0); diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java index 4e4a0374087e412d17ae7a31f5f4eb45c9029f20..7cd08f76a47eeae493356c0b5fca84edbcc5de6c 100644 --- a/core/java/android/security/keystore/recovery/RecoveryController.java +++ b/core/java/android/security/keystore/recovery/RecoveryController.java @@ -26,9 +26,13 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; +import android.security.KeyStore; +import android.security.keystore.AndroidKeyStoreProvider; import com.android.internal.widget.ILockSettings; +import java.security.Key; +import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; @@ -113,9 +117,11 @@ public class RecoveryController { private final ILockSettings mBinder; + private final KeyStore mKeyStore; - private RecoveryController(ILockSettings binder) { + private RecoveryController(ILockSettings binder, KeyStore keystore) { mBinder = binder; + mKeyStore = keystore; } /** @@ -133,7 +139,7 @@ public class RecoveryController { public static RecoveryController getInstance(Context context) { ILockSettings lockSettings = ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")); - return new RecoveryController(lockSettings); + return new RecoveryController(lockSettings, KeyStore.getInstance()); } /** @@ -430,6 +436,7 @@ public class RecoveryController { } /** + * Deprecated. * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable * key store. Returns the raw material of the key. * @@ -444,7 +451,6 @@ public class RecoveryController { public byte[] generateAndStoreKey(@NonNull String alias, byte[] account) throws InternalRecoveryServiceException, LockScreenRequiredException { try { - // TODO: add account return mBinder.generateAndStoreKey(alias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -456,6 +462,72 @@ public class RecoveryController { } } + /** + * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable + * key store. Returns {@link javax.crypto.SecretKey}. + * + * @param alias The key alias. + * @param account The account associated with the key. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + * @throws LockScreenRequiredException if the user has not set a lock screen. This is required + * to generate recoverable keys, as the snapshots are encrypted using a key derived from the + * lock screen. + * @hide + */ + public Key generateKey(@NonNull String alias, byte[] account) + throws InternalRecoveryServiceException, LockScreenRequiredException { + // TODO: update RecoverySession.recoverKeys + try { + String grantAlias = mBinder.generateKey(alias, account); + if (grantAlias == null) { + return null; + } + Key result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( + mKeyStore, + grantAlias, + KeyStore.UID_SELF); + return result; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (UnrecoverableKeyException e) { + throw new InternalRecoveryServiceException("Access to newly generated key failed for"); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_INSECURE_USER) { + throw new LockScreenRequiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Gets a key called {@code alias} from the recoverable key store. + * + * @param alias The key alias. + * @return The key. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + * @throws UnrecoverableKeyException if key is permanently invalidated or not found. + * @hide + */ + public @Nullable Key getKey(@NonNull String alias) + throws InternalRecoveryServiceException, UnrecoverableKeyException { + try { + String grantAlias = mBinder.getKey(alias); + if (grantAlias == null) { + return null; + } + return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( + mKeyStore, + grantAlias, + KeyStore.UID_SELF); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + /** * Removes a key called {@code alias} from the recoverable key store. * diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index 917efa8bd5f4dce2c614e22869d69742d0713646..7a304c7f55d262d95e1d19d366840ead3bf7fb0d 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -468,9 +468,8 @@ import com.android.internal.os.SomeArgs; *

    Typically, field classification can be used to detect fields that can be autofilled with * user data that is not associated with a specific app—such as email and physical * address. Once the service identifies that a such field was manually filled by the user, the - * service could use this signal to improve its heuristics, either locally (i.e., in the same - * device) or globally (i.e., by crowdsourcing the results back to the service's server so it can - * be used by other users). + * service could use this signal to improve its heuristics on subsequent requests (for example, by + * infering which resource ids are associated with known fields). * *

    The field classification workflow involves 4 steps: * @@ -481,8 +480,8 @@ import com.android.internal.os.SomeArgs; *

  • Identify which fields should be analysed by calling * {@link FillResponse.Builder#setFieldClassificationIds(AutofillId...)}. *
  • Verify the results through {@link FillEventHistory.Event#getFieldsClassification()}. - *
  • Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in future - * requests. + *
  • Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in + * subsequent requests. * * *

    The field classification is an expensive operation and should be used carefully, otherwise it @@ -491,8 +490,45 @@ import com.android.internal.os.SomeArgs; * strong suspicious that it could. For example, if an activity has four or more fields and one of * them is a list, chances are that these are address fields (like address, city, state, and * zip code). + * + * + *

    Compatibility mode

    + * + *

    Apps that use standard Android widgets support autofill out-of-the-box and need to do + * very little to improve their user experience (annotating autofillable views and providing + * autofill hints). However, some apps do their own rendering and the rendered content may + * contain semantic structure that needs to be surfaced to the autofill framework. The platform + * exposes APIs to achieve this, however it could take some time until these apps implement + * autofill support. + * + *

    To enable autofill for such apps the platform provides a compatibility mode in which the + * platform would fall back to the accessibility APIs to generate the state reported to autofill + * services and fill data. This mode needs to be explicitly requested for a given package up + * to a specified max version code allowing clean migration path when the target app begins to + * support autofill natively. Note that enabling compatibility may degrade performance for the + * target package and should be used with caution. The platform supports whitelisting which packages + * can be targeted in compatibility mode to ensure this mode is used only when needed and as long + * as needed. + * + *

    You can request compatibility mode for packages of interest in the meta-data resource + * associated with your service. Below is a sample service declaration: + * + *

     <service android:name=".MyAutofillService"
    + *              android:permission="android.permission.BIND_AUTOFILL_SERVICE">
    + *     <intent-filter>
    + *         <action android:name="android.service.autofill.AutofillService" />
    + *     </intent-filter>
    + *     <meta-data android:name="android.autofillservice" android:resource="@xml/autofillservice" />
    + * </service>
    + * + *

    In the XML file you can specify one or more packages for which to enable compatibility + * mode. Below is a sample meta-data declaration: + * + *

     <autofill-service xmlns:android="http://schemas.android.com/apk/res/android">
    + *     <compatibility-package android:name="foo.bar.baz" android:maxLongVersionCode="1000000000"/>
    + * </autofill-service>
    */ -// TODO(b/70407264): add code snippets above??? +// TODO(b/70407264): add code snippets to field classification ??? public abstract class AutofillService extends Service { private static final String TAG = "AutofillService"; diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java index 5c7388f79a49f56e428ed687b82d3b698de25394..29c6cea14980bd884b274bc338d9102f3ebdc950 100644 --- a/core/java/android/service/autofill/AutofillServiceInfo.java +++ b/core/java/android/service/autofill/AutofillServiceInfo.java @@ -20,22 +20,31 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppGlobals; import android.content.ComponentName; +import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.metrics.LogMaker; import android.os.RemoteException; +import android.text.TextUtils; +import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; import android.util.Xml; import com.android.internal.R; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; + +import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.Map; /** * {@link ServiceInfo} and meta-data about an {@link AutofillService}. @@ -45,6 +54,9 @@ import java.io.IOException; public final class AutofillServiceInfo { private static final String TAG = "AutofillServiceInfo"; + private static final String TAG_AUTOFILL_SERVICE = "autofill-service"; + private static final String TAG_COMPATIBILITY_PACKAGE = "compatibility-package"; + private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle) throws PackageManager.NameNotFoundException { try { @@ -66,76 +78,142 @@ public final class AutofillServiceInfo { @Nullable private final String mSettingsActivity; - public AutofillServiceInfo(PackageManager pm, ComponentName comp, int userHandle) - throws PackageManager.NameNotFoundException { - this(pm, getServiceInfoOrThrow(comp, userHandle)); - } + @Nullable + private final Map mCompatibilityPackages; - public AutofillServiceInfo(PackageManager pm, ServiceInfo si) { - mServiceInfo = si; - final TypedArray metaDataArray = getMetaDataArray(pm, si); - if (metaDataArray != null) { - mSettingsActivity = metaDataArray - .getString(R.styleable.AutofillService_settingsActivity); - metaDataArray.recycle(); - } else { - mSettingsActivity = null; - } + public AutofillServiceInfo(Context context, ComponentName comp, int userHandle) + throws PackageManager.NameNotFoundException { + this(context, getServiceInfoOrThrow(comp, userHandle)); } - /** - * Gets the meta-data as a {@link TypedArray}, or {@code null} if not provided, - * or throws if invalid. - */ - @Nullable - private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) { + public AutofillServiceInfo(Context context, ServiceInfo si) { // Check for permissions. if (!Manifest.permission.BIND_AUTOFILL_SERVICE.equals(si.permission)) { - Log.w(TAG, "AutofillService from '" + si.packageName + "' does not require permission " - + Manifest.permission.BIND_AUTOFILL_SERVICE); - throw new SecurityException("Service does not require permission " - + Manifest.permission.BIND_AUTOFILL_SERVICE); + if (Manifest.permission.BIND_AUTOFILL.equals(si.permission)) { + // Let it go for now... + Log.w(TAG, "AutofillService from '" + si.packageName + "' uses unsupported " + + "permission " + Manifest.permission.BIND_AUTOFILL + ". It works for " + + "now, but might not be supported on future releases"); + new MetricsLogger().write(new LogMaker(MetricsEvent.AUTOFILL_INVALID_PERMISSION) + .setPackageName(si.packageName)); + } else { + Log.w(TAG, "AutofillService from '" + si.packageName + + "' does not require permission " + + Manifest.permission.BIND_AUTOFILL_SERVICE); + throw new SecurityException("Service does not require permission " + + Manifest.permission.BIND_AUTOFILL_SERVICE); + } } + mServiceInfo = si; + // Get the AutoFill metadata, if declared. - XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA); + final XmlResourceParser parser = si.loadXmlMetaData(context.getPackageManager(), + AutofillService.SERVICE_META_DATA); if (parser == null) { - return null; + mSettingsActivity = null; + mCompatibilityPackages = null; + return; } - // Parse service info and get the tag as an AttributeSet. - AttributeSet attrs; + String settingsActivity = null; + Map compatibilityPackages = null; + try { - // Move the XML parser to the first tag. - try { - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && type != XmlPullParser.START_TAG) { - } - } catch (XmlPullParserException | IOException e) { - Log.e(TAG, "Error parsing auto fill service meta-data", e); - return null; + final Resources resources = context.getPackageManager().getResourcesForApplication( + si.applicationInfo); + + int type = 0; + while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { + type = parser.next(); } - if (!"autofill-service".equals(parser.getName())) { + if (TAG_AUTOFILL_SERVICE.equals(parser.getName())) { + final AttributeSet allAttributes = Xml.asAttributeSet(parser); + TypedArray afsAttributes = null; + try { + afsAttributes = resources.obtainAttributes(allAttributes, + com.android.internal.R.styleable.AutofillService); + settingsActivity = afsAttributes.getString( + R.styleable.AutofillService_settingsActivity); + } finally { + if (afsAttributes != null) { + afsAttributes.recycle(); + } + } + compatibilityPackages = parseCompatibilityPackages(parser, resources); + } else { Log.e(TAG, "Meta-data does not start with autofill-service tag"); - return null; } - attrs = Xml.asAttributeSet(parser); - - // Get resources required to read the AttributeSet. - Resources res; - try { - res = pm.getResourcesForApplication(si.applicationInfo); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Error getting application resources", e); - return null; + } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) { + Log.e(TAG, "Error parsing auto fill service meta-data", e); + } + + mSettingsActivity = settingsActivity; + mCompatibilityPackages = compatibilityPackages; + } + + private Map parseCompatibilityPackages(XmlPullParser parser, Resources resources) + throws IOException, XmlPullParserException { + Map compatibilityPackages = null; + + final int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; } - return res.obtainAttributes(attrs, R.styleable.AutofillService); - } finally { - parser.close(); + if (TAG_COMPATIBILITY_PACKAGE.equals(parser.getName())) { + TypedArray cpAttributes = null; + try { + final AttributeSet allAttributes = Xml.asAttributeSet(parser); + + cpAttributes = resources.obtainAttributes(allAttributes, + R.styleable.AutofillService_CompatibilityPackage); + + final String name = cpAttributes.getString( + R.styleable.AutofillService_CompatibilityPackage_name); + if (TextUtils.isEmpty(name)) { + Log.e(TAG, "Invalid compatibility package:" + name); + break; + } + + final String maxVersionCodeStr = cpAttributes.getString( + R.styleable.AutofillService_CompatibilityPackage_maxLongVersionCode); + final Long maxVersionCode; + if (maxVersionCodeStr != null) { + try { + maxVersionCode = Long.parseLong(maxVersionCodeStr); + } catch (NumberFormatException e) { + Log.e(TAG, "Invalid compatibility max version code:" + + maxVersionCodeStr); + break; + } + if (maxVersionCode < 0) { + Log.e(TAG, "Invalid compatibility max version code:" + + maxVersionCode); + break; + } + } else { + maxVersionCode = Long.MAX_VALUE; + } + + if (compatibilityPackages == null) { + compatibilityPackages = new ArrayMap<>(); + } + compatibilityPackages.put(name, maxVersionCode); + } finally { + XmlUtils.skipCurrentTag(parser); + if (cpAttributes != null) { + cpAttributes.recycle(); + } + } + } } + + return compatibilityPackages; } public ServiceInfo getServiceInfo() { @@ -147,8 +225,26 @@ public final class AutofillServiceInfo { return mSettingsActivity; } + @Nullable + public boolean isCompatibilityModeRequested(String packageName, long versionCode) { + if (mCompatibilityPackages == null) { + return false; + } + final Long maxVersionCode = mCompatibilityPackages.get(packageName); + if (maxVersionCode == null) { + return false; + } + return versionCode <= maxVersionCode; + } + @Override public String toString() { - return mServiceInfo == null ? "null" : mServiceInfo.toString(); + final StringBuilder builder = new StringBuilder(); + builder.append(getClass().getSimpleName()); + builder.append("[").append(mServiceInfo); + builder.append(", settings:").append(mSettingsActivity); + builder.append(", hasCompatPckgs:").append(mCompatibilityPackages != null + && !mCompatibilityPackages.isEmpty()).append("]"); + return builder.toString(); } } diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java index b8e8b19f978609f9453a3f3e484cdffe9c8ad771..fb468a8dad6f871a52aecd2dd3b4b1bc225900b8 100644 --- a/core/java/android/service/autofill/CustomDescription.java +++ b/core/java/android/service/autofill/CustomDescription.java @@ -173,7 +173,10 @@ public final class CustomDescription implements Parcelable { } /** - * Updates the {@link RemoteViews presentation template} when a condition is satisfied. + * Updates the {@link RemoteViews presentation template} when a condition is satisfied by + * applying a series of remote view operations. This allows dynamic customization of the + * portion of the save UI that is controlled by the autofill service. Such dynamic + * customization is based on the content of target views. * *

    The updates are applied in the sequence they are added, after the * {@link #addChild(int, Transformation) transformations} are applied to the children diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index 266bcda7797a005b5256748c6272c42afbac734b..f32dee1ec9f226cfa02fdb390b0c4c88969ab25d 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -29,7 +29,6 @@ import android.widget.RemoteViews; import com.android.internal.util.Preconditions; -import java.io.Serializable; import java.util.ArrayList; import java.util.regex.Pattern; @@ -99,7 +98,7 @@ public final class Dataset implements Parcelable { private final ArrayList mFieldIds; private final ArrayList mFieldValues; private final ArrayList mFieldPresentations; - private final ArrayList mFieldFilters; + private final ArrayList mFieldFilters; private final RemoteViews mPresentation; private final IntentSender mAuthentication; @Nullable String mId; @@ -132,7 +131,7 @@ public final class Dataset implements Parcelable { /** @hide */ @Nullable - public Pattern getFilter(int index) { + public DatasetFieldFilter getFilter(int index) { return mFieldFilters.get(index); } @@ -189,7 +188,7 @@ public final class Dataset implements Parcelable { private ArrayList mFieldIds; private ArrayList mFieldValues; private ArrayList mFieldPresentations; - private ArrayList mFieldFilters; + private ArrayList mFieldFilters; private RemoteViews mPresentation; private IntentSender mAuthentication; private boolean mDestroyed; @@ -363,19 +362,21 @@ public final class Dataset implements Parcelable { * @param value the value to be autofilled. Pass {@code null} if you do not have the value * but the target view is a logical part of the dataset. For example, if * the dataset needs authentication and you have no access to the value. - * @param filter regex used to determine if the dataset should be shown in the autofill UI. + * @param filter regex used to determine if the dataset should be shown in the autofill UI; + * when {@code null}, it disables filtering on that dataset (this is the recommended + * approach when {@code value} is not {@code null} and field contains sensitive data + * such as passwords). * * @return this builder. * @throws IllegalStateException if the builder was constructed without a * {@link RemoteViews presentation}. */ public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, - @NonNull Pattern filter) { + @Nullable Pattern filter) { throwIfDestroyed(); - Preconditions.checkNotNull(filter, "filter cannot be null"); Preconditions.checkState(mPresentation != null, "Dataset presentation not set on constructor"); - setLifeTheUniverseAndEverything(id, value, null, filter); + setLifeTheUniverseAndEverything(id, value, null, new DatasetFieldFilter(filter)); return this; } @@ -398,23 +399,26 @@ public final class Dataset implements Parcelable { * @param value the value to be autofilled. Pass {@code null} if you do not have the value * but the target view is a logical part of the dataset. For example, if * the dataset needs authentication and you have no access to the value. + * @param filter regex used to determine if the dataset should be shown in the autofill UI; + * when {@code null}, it disables filtering on that dataset (this is the recommended + * approach when {@code value} is not {@code null} and field contains sensitive data + * such as passwords). * @param presentation the presentation used to visualize this field. - * @param filter regex used to determine if the dataset should be shown in the autofill UI. * * @return this builder. */ public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, - @NonNull Pattern filter, @NonNull RemoteViews presentation) { + @Nullable Pattern filter, @NonNull RemoteViews presentation) { throwIfDestroyed(); - Preconditions.checkNotNull(filter, "filter cannot be null"); Preconditions.checkNotNull(presentation, "presentation cannot be null"); - setLifeTheUniverseAndEverything(id, value, presentation, filter); + setLifeTheUniverseAndEverything(id, value, presentation, + new DatasetFieldFilter(filter)); return this; } private void setLifeTheUniverseAndEverything(@NonNull AutofillId id, @Nullable AutofillValue value, @Nullable RemoteViews presentation, - @Nullable Pattern filter) { + @Nullable DatasetFieldFilter filter) { Preconditions.checkNotNull(id, "id cannot be null"); if (mFieldIds != null) { final int existingIdx = mFieldIds.indexOf(id); @@ -477,8 +481,8 @@ public final class Dataset implements Parcelable { parcel.writeParcelable(mPresentation, flags); parcel.writeTypedList(mFieldIds, flags); parcel.writeTypedList(mFieldValues, flags); - parcel.writeParcelableList(mFieldPresentations, flags); - parcel.writeSerializable(mFieldFilters); + parcel.writeTypedList(mFieldPresentations, flags); + parcel.writeTypedList(mFieldFilters, flags); parcel.writeParcelable(mAuthentication, flags); parcel.writeString(mId); } @@ -493,22 +497,19 @@ public final class Dataset implements Parcelable { final Builder builder = (presentation == null) ? new Builder() : new Builder(presentation); - final ArrayList ids = parcel.createTypedArrayList(AutofillId.CREATOR); + final ArrayList ids = + parcel.createTypedArrayList(AutofillId.CREATOR); final ArrayList values = parcel.createTypedArrayList(AutofillValue.CREATOR); - final ArrayList presentations = new ArrayList<>(); - parcel.readParcelableList(presentations, null); - @SuppressWarnings("unchecked") - final ArrayList filters = - (ArrayList) parcel.readSerializable(); - final int idCount = (ids != null) ? ids.size() : 0; - final int valueCount = (values != null) ? values.size() : 0; - for (int i = 0; i < idCount; i++) { + final ArrayList presentations = + parcel.createTypedArrayList(RemoteViews.CREATOR); + final ArrayList filters = + parcel.createTypedArrayList(DatasetFieldFilter.CREATOR); + for (int i = 0; i < ids.size(); i++) { final AutofillId id = ids.get(i); - final AutofillValue value = (valueCount > i) ? values.get(i) : null; - final RemoteViews fieldPresentation = presentations.isEmpty() ? null - : presentations.get(i); - final Pattern filter = (Pattern) filters.get(i); + final AutofillValue value = values.get(i); + final RemoteViews fieldPresentation = presentations.get(i); + final DatasetFieldFilter filter = filters.get(i); builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation, filter); } builder.setAuthentication(parcel.readParcelable(null)); @@ -521,4 +522,55 @@ public final class Dataset implements Parcelable { return new Dataset[size]; } }; + + /** + * Helper class used to indicate when the service explicitly set a {@link Pattern} filter for a + * dataset field‐ we cannot use a {@link Pattern} directly because then we wouldn't be + * able to differentiate whether the service explicitly passed a {@code null} filter to disable + * filter, or when it called the methods that does not take a filter {@link Pattern}. + * + * @hide + */ + public static final class DatasetFieldFilter implements Parcelable { + + @Nullable + public final Pattern pattern; + + private DatasetFieldFilter(@Nullable Pattern pattern) { + this.pattern = pattern; + } + + @Override + public String toString() { + if (!sDebug) return super.toString(); + + // Cannot log pattern because it could contain PII + return pattern == null ? "null" : pattern.pattern().length() + "_chars"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeSerializable(pattern); + } + + @SuppressWarnings("hiding") + public static final Creator CREATOR = + new Creator() { + + @Override + public DatasetFieldFilter createFromParcel(Parcel parcel) { + return new DatasetFieldFilter((Pattern) parcel.readSerializable()); + } + + @Override + public DatasetFieldFilter[] newArray(int size) { + return new DatasetFieldFilter[size]; + } + }; + } } diff --git a/core/java/android/service/autofill/DateTransformation.java b/core/java/android/service/autofill/DateTransformation.java new file mode 100644 index 0000000000000000000000000000000000000000..4e1425d863802b1eb0dcdfa3451cf2451681353e --- /dev/null +++ b/core/java/android/service/autofill/DateTransformation.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +import static android.view.autofill.Helper.sDebug; + +import android.annotation.NonNull; +import android.annotation.TestApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; +import android.view.autofill.AutofillId; +import android.view.autofill.AutofillValue; +import android.widget.RemoteViews; +import android.widget.TextView; + +import com.android.internal.util.Preconditions; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Replaces a {@link TextView} child of a {@link CustomDescription} with the contents of a field + * that is expected to have a {@link AutofillValue#forDate(long) date value}. + * + *

    For example, a transformation to display a credit card expiration date as month/year would be: + * + *

    + * new DateTransformation(ccExpDate, new java.text.SimpleDateFormat("MM/yyyy")
    + * 
    + */ +public final class DateTransformation extends InternalTransformation implements + Transformation, Parcelable { + private static final String TAG = "DateTransformation"; + + private final AutofillId mFieldId; + private final DateFormat mDateFormat; + + /** + * Creates a new transformation. + * + * @param id id of the screen field. + * @param dateFormat object used to transform the date value of the field to a String. + */ + public DateTransformation(@NonNull AutofillId id, @NonNull DateFormat dateFormat) { + mFieldId = Preconditions.checkNotNull(id); + mDateFormat = Preconditions.checkNotNull(dateFormat); + } + + /** @hide */ + @Override + @TestApi + public void apply(@NonNull ValueFinder finder, @NonNull RemoteViews parentTemplate, + int childViewId) throws Exception { + final AutofillValue value = finder.findRawValueByAutofillId(mFieldId); + if (value == null) { + Log.w(TAG, "No value for id " + mFieldId); + return; + } + if (!value.isDate()) { + Log.w(TAG, "Value for " + mFieldId + " is not date: " + value); + return; + } + + try { + final Date date = new Date(value.getDateValue()); + final String transformed = mDateFormat.format(date); + if (sDebug) Log.d(TAG, "Transformed " + date + " to " + transformed); + + parentTemplate.setCharSequence(childViewId, "setText", transformed); + } catch (Exception e) { + Log.w(TAG, "Could not apply " + mDateFormat + " to " + value + ": " + e); + } + } + + ///////////////////////////////////// + // Object "contract" methods. // + ///////////////////////////////////// + @Override + public String toString() { + if (!sDebug) return super.toString(); + + return "DateTransformation: [id=" + mFieldId + ", format=" + mDateFormat + "]"; + } + + ///////////////////////////////////// + // Parcelable "contract" methods. // + ///////////////////////////////////// + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeParcelable(mFieldId, flags); + parcel.writeSerializable(mDateFormat); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DateTransformation createFromParcel(Parcel parcel) { + return new DateTransformation(parcel.readParcelable(null), + (DateFormat) parcel.readSerializable()); + } + + @Override + public DateTransformation[] newArray(int size) { + return new DateTransformation[size]; + } + }; +} diff --git a/core/java/android/service/autofill/DateValueSanitizer.java b/core/java/android/service/autofill/DateValueSanitizer.java new file mode 100644 index 0000000000000000000000000000000000000000..0f7b540f8a24ae1640a9f9ca2358bbabcd6bd898 --- /dev/null +++ b/core/java/android/service/autofill/DateValueSanitizer.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +import static android.view.autofill.Helper.sDebug; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.TestApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; +import android.view.autofill.AutofillValue; + +import com.android.internal.util.Preconditions; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Sanitizes a date {@link AutofillValue} using a {@link DateFormat}. + * + *

    For example, to sanitize a credit card expiration date to just its month and year: + * + *

    + * new DateValueSanitizer(new java.text.SimpleDateFormat("MM/yyyy");
    + * 
    + */ +public final class DateValueSanitizer extends InternalSanitizer implements Sanitizer, Parcelable { + + private static final String TAG = "DateValueSanitizer"; + + private final DateFormat mDateFormat; + + /** + * Default constructor. + * + * @param dateFormat date format applied to the actual date value of an input field. + */ + public DateValueSanitizer(@NonNull DateFormat dateFormat) { + mDateFormat = Preconditions.checkNotNull(dateFormat); + } + + /** @hide */ + @Override + @TestApi + @Nullable + public AutofillValue sanitize(@NonNull AutofillValue value) { + if (value == null) { + Log.w(TAG, "sanitize() called with null value"); + return null; + } + if (!value.isDate()) { + if (sDebug) Log.d(TAG, value + " is not a date"); + return null; + } + + try { + final Date date = new Date(value.getDateValue()); + + // First convert it to string + final String converted = mDateFormat.format(date); + if (sDebug) Log.d(TAG, "Transformed " + date + " to " + converted); + // Then parse it back to date + final Date sanitized = mDateFormat.parse(converted); + if (sDebug) Log.d(TAG, "Sanitized to " + sanitized); + return AutofillValue.forDate(sanitized.getTime()); + } catch (Exception e) { + Log.w(TAG, "Could not apply " + mDateFormat + " to " + value + ": " + e); + return null; + } + } + + ///////////////////////////////////// + // Object "contract" methods. // + ///////////////////////////////////// + @Override + public String toString() { + if (!sDebug) return super.toString(); + + return "DateValueSanitizer: [dateFormat=" + mDateFormat + "]"; + } + + ///////////////////////////////////// + // Parcelable "contract" methods. // + ///////////////////////////////////// + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeSerializable(mDateFormat); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DateValueSanitizer createFromParcel(Parcel parcel) { + return new DateValueSanitizer((DateFormat) parcel.readSerializable()); + } + + @Override + public DateValueSanitizer[] newArray(int size) { + return new DateValueSanitizer[size]; + } + }; +} diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java index 9017848055e27ed24c0bc27964272729385df524..6bab6aa823756f3e953524679b8c46cebf367d23 100644 --- a/core/java/android/service/autofill/UserData.java +++ b/core/java/android/service/autofill/UserData.java @@ -30,6 +30,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.provider.Settings; import android.service.autofill.FieldClassification.Match; +import android.text.TextUtils; import android.util.Log; import android.view.autofill.AutofillManager; import android.view.autofill.Helper; @@ -52,12 +53,14 @@ public final class UserData implements Parcelable { private static final int DEFAULT_MIN_VALUE_LENGTH = 5; private static final int DEFAULT_MAX_VALUE_LENGTH = 100; + private final String mId; private final String mAlgorithm; private final Bundle mAlgorithmArgs; private final String[] mRemoteIds; private final String[] mValues; private UserData(Builder builder) { + mId = builder.mId; mAlgorithm = builder.mAlgorithm; mAlgorithmArgs = builder.mAlgorithmArgs; mRemoteIds = new String[builder.mRemoteIds.size()]; @@ -75,6 +78,13 @@ public final class UserData implements Parcelable { return mAlgorithm; } + /** + * Gets the id. + */ + public String getId() { + return mId; + } + /** @hide */ public Bundle getAlgorithmArgs() { return mAlgorithmArgs; @@ -92,6 +102,7 @@ public final class UserData implements Parcelable { /** @hide */ public void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("id: "); pw.print(mId); pw.print(prefix); pw.print("Algorithm: "); pw.print(mAlgorithm); pw.print(" Args: "); pw.println(mAlgorithmArgs); @@ -121,6 +132,7 @@ public final class UserData implements Parcelable { * A builder for {@link UserData} objects. */ public static final class Builder { + private final String mId; private final ArrayList mRemoteIds; private final ArrayList mValues; private String mAlgorithm; @@ -131,16 +143,28 @@ public final class UserData implements Parcelable { * Creates a new builder for the user data used for field * classification. * + *

    The user data must contain at least one pair of {@code remoteId} -> {@code value}, and + * more pairs can be added through the {@link #add(String, String)} method. + * + * @param id id used to identify the whole {@link UserData} object. This id is also returned + * by {@link AutofillManager#getUserDataId()}, which can be used to check if the + * {@link UserData} is up-to-date without fetching the whole object (through + * {@link AutofillManager#getUserData()}). + * @param remoteId unique string used to identify a user data value. + * @param value value of the user data. + * * @throws IllegalArgumentException if any of the following occurs: *

      + *
    1. {@code id} is empty *
    2. {@code remoteId} is empty *
    3. {@code value} is empty *
    4. the length of {@code value} is lower than {@link UserData#getMinValueLength()} *
    5. the length of {@code value} is higher than {@link UserData#getMaxValueLength()} *
    */ - public Builder(@NonNull String remoteId, @NonNull String value) { - checkValidRemoteId(remoteId); + public Builder(@NonNull String id, @NonNull String remoteId, @NonNull String value) { + mId = checkNotEmpty("id", id); + checkNotEmpty("remoteId", remoteId); checkValidValue(value); final int capacity = getMaxUserDataSize(); mRemoteIds = new ArrayList<>(capacity); @@ -188,7 +212,7 @@ public final class UserData implements Parcelable { */ public Builder add(@NonNull String remoteId, @NonNull String value) { throwIfDestroyed(); - checkValidRemoteId(remoteId); + checkNotEmpty("remoteId", remoteId); checkValidValue(value); Preconditions.checkState(!mRemoteIds.contains(remoteId), @@ -205,9 +229,10 @@ public final class UserData implements Parcelable { return this; } - private void checkValidRemoteId(@Nullable String remoteId) { - Preconditions.checkNotNull(remoteId); - Preconditions.checkArgument(!remoteId.isEmpty(), "remoteId cannot be empty"); + private String checkNotEmpty(@NonNull String name, @Nullable String value) { + Preconditions.checkNotNull(value); + Preconditions.checkArgument(!TextUtils.isEmpty(value), "%s cannot be empty", name); + return value; } private void checkValidValue(@Nullable String value) { @@ -246,7 +271,8 @@ public final class UserData implements Parcelable { public String toString() { if (!sDebug) return super.toString(); - final StringBuilder builder = new StringBuilder("UserData: [algorithm=").append(mAlgorithm); + final StringBuilder builder = new StringBuilder("UserData: [id=").append(mId) + .append(", algorithm=").append(mAlgorithm); // Cannot disclose remote ids or values because they could contain PII builder.append(", remoteIds="); Helper.appendRedacted(builder, mRemoteIds); @@ -266,6 +292,7 @@ public final class UserData implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(mId); parcel.writeStringArray(mRemoteIds); parcel.writeStringArray(mValues); parcel.writeString(mAlgorithm); @@ -279,9 +306,10 @@ public final class UserData implements Parcelable { // Always go through the builder to ensure the data ingested by // the system obeys the contract of the builder to avoid attacks // using specially crafted parcels. + final String id = parcel.readString(); final String[] remoteIds = parcel.readStringArray(); final String[] values = parcel.readStringArray(); - final Builder builder = new Builder(remoteIds[0], values[0]) + final Builder builder = new Builder(id, remoteIds[0], values[0]) .setFieldClassificationAlgorithm(parcel.readString(), parcel.readBundle()); for (int i = 1; i < remoteIds.length; i++) { builder.add(remoteIds[i], values[i]); diff --git a/core/java/android/service/autofill/ValueFinder.java b/core/java/android/service/autofill/ValueFinder.java index 1705b7d922aa99b909995ab295af5836bf0affdd..7f195d67c60123e63f67c92f8c07049e0ba86659 100644 --- a/core/java/android/service/autofill/ValueFinder.java +++ b/core/java/android/service/autofill/ValueFinder.java @@ -19,6 +19,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillValue; /** * Helper object used to obtain the value of a field in the screen being autofilled. @@ -28,8 +29,18 @@ import android.view.autofill.AutofillId; @TestApi public interface ValueFinder { + /** + * Gets the value of a field as String, or {@code null} when not found. + */ + @Nullable + default String findByAutofillId(@NonNull AutofillId id) { + final AutofillValue value = findRawValueByAutofillId(id); + return (value == null || !value.isText()) ? null : value.getTextValue().toString(); + } + /** * Gets the value of a field, or {@code null} when not found. */ - @Nullable String findByAutofillId(@NonNull AutofillId id); + @Nullable + AutofillValue findRawValueByAutofillId(@NonNull AutofillId id); } diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 23ae4b96810f126aeb645e206ab074b5e8fbdb42..d66322c3aa8904523528d4625ba06a43c482f53a 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -17,6 +17,7 @@ package android.service.notification; import android.app.ActivityManager; +import android.app.AlarmManager; import android.app.NotificationManager; import android.app.NotificationManager.Policy; import android.content.ComponentName; @@ -1445,4 +1446,99 @@ public class ZenModeConfig implements Parcelable { return !config.allowAlarms && !config.allowMediaSystemOther && areAllPriorityOnlyNotificationZenSoundsMuted(config); } + + /** + * Returns a description of the current do not disturb settings from config. + * - If turned on manually and end time is known, returns end time. + * - If turned on by an automatic rule, returns the automatic rule name. + * - If on due to an app, returns the app name. + * - If there's a combination of rules/apps that trigger, then shows the one that will + * last the longest if applicable. + * @return null if do not disturb is off. + */ + public static String getDescription(Context context, boolean zenOn, ZenModeConfig config) { + if (!zenOn) { + return null; + } + + String secondaryText = ""; + long latestEndTime = -1; + + // DND turned on by manual rule + if (config.manualRule != null) { + final Uri id = config.manualRule.conditionId; + if (config.manualRule.enabler != null) { + // app triggered manual rule + String appName = getOwnerCaption(context, config.manualRule.enabler); + if (!appName.isEmpty()) { + secondaryText = appName; + } + } else { + if (id == null) { + // Do not disturb manually triggered to remain on forever until turned off + // No subtext + return null; + } else { + latestEndTime = tryParseCountdownConditionId(id); + if (latestEndTime > 0) { + final CharSequence formattedTime = getFormattedTime(context, + latestEndTime, isToday(latestEndTime), + context.getUserId()); + secondaryText = context.getString(R.string.zen_mode_until, formattedTime); + } + } + } + } + + // DND turned on by an automatic rule + for (ZenRule automaticRule : config.automaticRules.values()) { + if (automaticRule.isAutomaticActive()) { + if (isValidEventConditionId(automaticRule.conditionId) + || isValidScheduleConditionId(automaticRule.conditionId)) { + // set text if automatic rule end time is the latest active rule end time + long endTime = parseAutomaticRuleEndTime(context, automaticRule.conditionId); + if (endTime > latestEndTime) { + latestEndTime = endTime; + secondaryText = automaticRule.name; + } + } else { + // set text if 3rd party rule + return automaticRule.name; + } + } + } + + return !secondaryText.equals("") ? secondaryText : null; + } + + private static long parseAutomaticRuleEndTime(Context context, Uri id) { + if (isValidEventConditionId(id)) { + // cannot look up end times for events + return Long.MAX_VALUE; + } + + if (isValidScheduleConditionId(id)) { + ScheduleCalendar schedule = toScheduleCalendar(id); + long endTimeMs = schedule.getNextChangeTime(System.currentTimeMillis()); + + // check if automatic rule will end on next alarm + if (schedule.exitAtAlarm()) { + long nextAlarm = getNextAlarm(context); + schedule.maybeSetNextAlarm(System.currentTimeMillis(), nextAlarm); + if (schedule.shouldExitForAlarm(endTimeMs)) { + return nextAlarm; + } + } + + return endTimeMs; + } + + return -1; + } + + private static long getNextAlarm(Context context) { + final AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + final AlarmManager.AlarmClockInfo info = alarms.getNextAlarmClock(context.getUserId()); + return info != null ? info.getTriggerTime() : 0; + } } diff --git a/core/java/android/service/settings/suggestions/Suggestion.java b/core/java/android/service/settings/suggestions/Suggestion.java index 11e1e674a7470c3a7b01f7a08f61eb8a56c65855..e97f963a0986536b6e097b8188638a6b73d3488d 100644 --- a/core/java/android/service/settings/suggestions/Suggestion.java +++ b/core/java/android/service/settings/suggestions/Suggestion.java @@ -40,6 +40,7 @@ public final class Suggestion implements Parcelable { */ @IntDef(flag = true, prefix = { "FLAG_" }, value = { FLAG_HAS_BUTTON, + FLAG_ICON_TINTABLE, }) @Retention(RetentionPolicy.SOURCE) public @interface Flags { @@ -49,6 +50,10 @@ public final class Suggestion implements Parcelable { * Flag for suggestion type with a single button */ public static final int FLAG_HAS_BUTTON = 1 << 0; + /** + * @hide + */ + public static final int FLAG_ICON_TINTABLE = 1 << 1; private final String mId; private final CharSequence mTitle; diff --git a/core/java/android/service/textclassifier/ITextClassificationCallback.aidl b/core/java/android/service/textclassifier/ITextClassificationCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..10bfe632450917a5c15e3e1685e05c734301808e --- /dev/null +++ b/core/java/android/service/textclassifier/ITextClassificationCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.textclassifier; + +import android.view.textclassifier.TextClassification; + +/** + * Callback for a TextClassification request. + * @hide + */ +oneway interface ITextClassificationCallback { + void onSuccess(in TextClassification classification); + void onFailure(); +} diff --git a/core/java/android/service/textclassifier/ITextClassifierService.aidl b/core/java/android/service/textclassifier/ITextClassifierService.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d2ffe345ae381d89dfdf8cb19eb73fed1de7ff1a --- /dev/null +++ b/core/java/android/service/textclassifier/ITextClassifierService.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.textclassifier; + +import android.service.textclassifier.ITextClassificationCallback; +import android.service.textclassifier.ITextLinksCallback; +import android.service.textclassifier.ITextSelectionCallback; +import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextLinks; +import android.view.textclassifier.TextSelection; + +/** + * TextClassifierService binder interface. + * See TextClassifier for interface documentation. + * {@hide} + */ +oneway interface ITextClassifierService { + + void onSuggestSelection( + in CharSequence text, int selectionStartIndex, int selectionEndIndex, + in TextSelection.Options options, + in ITextSelectionCallback c); + + void onClassifyText( + in CharSequence text, int startIndex, int endIndex, + in TextClassification.Options options, + in ITextClassificationCallback c); + + void onGenerateLinks( + in CharSequence text, + in TextLinks.Options options, + in ITextLinksCallback c); +} diff --git a/core/java/android/service/textclassifier/ITextLinksCallback.aidl b/core/java/android/service/textclassifier/ITextLinksCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a9e0dde567738800a9ab066b8bf7f82544389794 --- /dev/null +++ b/core/java/android/service/textclassifier/ITextLinksCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.textclassifier; + +import android.view.textclassifier.TextLinks; + +/** + * Callback for a TextLinks request. + * @hide + */ +oneway interface ITextLinksCallback { + void onSuccess(in TextLinks links); + void onFailure(); +} \ No newline at end of file diff --git a/core/java/android/service/textclassifier/ITextSelectionCallback.aidl b/core/java/android/service/textclassifier/ITextSelectionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1b4c4d10d4273ffc28c40e72e5e760bd492e700d --- /dev/null +++ b/core/java/android/service/textclassifier/ITextSelectionCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.textclassifier; + +import android.view.textclassifier.TextSelection; + +/** + * Callback for a TextSelection request. + * @hide + */ +oneway interface ITextSelectionCallback { + void onSuccess(in TextSelection selection); + void onFailure(); +} \ No newline at end of file diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java new file mode 100644 index 0000000000000000000000000000000000000000..6c8c8bc361270a03a0979065c473a23ba0eb5112 --- /dev/null +++ b/core/java/android/service/textclassifier/TextClassifierService.java @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.textclassifier; + +import android.Manifest; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; +import android.os.CancellationSignal; +import android.os.IBinder; +import android.os.RemoteException; +import android.text.TextUtils; +import android.util.Slog; +import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextClassifier; +import android.view.textclassifier.TextLinks; +import android.view.textclassifier.TextSelection; + +import com.android.internal.R; + +/** + * Abstract base class for the TextClassifier service. + * + *

    A TextClassifier service provides text classification related features for the system. + * The system's default TextClassifierService is configured in + * {@code config_defaultTextClassifierService}. If this config has no value, a + * {@link android.view.textclassifier.TextClassifierImpl} is loaded in the calling app's process. + * + *

    See: {@link TextClassifier}. + * See: {@link android.view.textclassifier.TextClassificationManager}. + * + *

    Include the following in the manifest: + * + *

    + * {@literal
    + * 
    + *     
    + *         
    + *     
    + * }
    + * + * @see TextClassifier + * @hide + */ +@SystemApi +public abstract class TextClassifierService extends Service { + + private static final String LOG_TAG = "TextClassifierService"; + + /** + * The {@link Intent} that must be declared as handled by the service. + * To be supported, the service must also require the + * {@link android.Manifest.permission#BIND_TEXTCLASSIFIER_SERVICE} permission so + * that other applications can not abuse it. + */ + @SystemApi + public static final String SERVICE_INTERFACE = + "android.service.textclassifier.TextClassifierService"; + + private final ITextClassifierService.Stub mBinder = new ITextClassifierService.Stub() { + + // TODO(b/72533911): Implement cancellation signal + @NonNull private final CancellationSignal mCancellationSignal = new CancellationSignal(); + + /** {@inheritDoc} */ + @Override + public void onSuggestSelection( + CharSequence text, int selectionStartIndex, int selectionEndIndex, + TextSelection.Options options, ITextSelectionCallback callback) + throws RemoteException { + TextClassifierService.this.onSuggestSelection( + text, selectionStartIndex, selectionEndIndex, options, mCancellationSignal, + new Callback() { + @Override + public void onSuccess(TextSelection result) { + try { + callback.onSuccess(result); + } catch (RemoteException e) { + Slog.d(LOG_TAG, "Error calling callback"); + } + } + + @Override + public void onFailure(CharSequence error) { + try { + if (callback.asBinder().isBinderAlive()) { + callback.onFailure(); + } + } catch (RemoteException e) { + Slog.d(LOG_TAG, "Error calling callback"); + } + } + }); + } + + /** {@inheritDoc} */ + @Override + public void onClassifyText( + CharSequence text, int startIndex, int endIndex, + TextClassification.Options options, ITextClassificationCallback callback) + throws RemoteException { + TextClassifierService.this.onClassifyText( + text, startIndex, endIndex, options, mCancellationSignal, + new Callback() { + @Override + public void onSuccess(TextClassification result) { + try { + callback.onSuccess(result); + } catch (RemoteException e) { + Slog.d(LOG_TAG, "Error calling callback"); + } + } + + @Override + public void onFailure(CharSequence error) { + try { + callback.onFailure(); + } catch (RemoteException e) { + Slog.d(LOG_TAG, "Error calling callback"); + } + } + }); + } + + /** {@inheritDoc} */ + @Override + public void onGenerateLinks( + CharSequence text, TextLinks.Options options, ITextLinksCallback callback) + throws RemoteException { + TextClassifierService.this.onGenerateLinks( + text, options, mCancellationSignal, + new Callback() { + @Override + public void onSuccess(TextLinks result) { + try { + callback.onSuccess(result); + } catch (RemoteException e) { + Slog.d(LOG_TAG, "Error calling callback"); + } + } + + @Override + public void onFailure(CharSequence error) { + try { + callback.onFailure(); + } catch (RemoteException e) { + Slog.d(LOG_TAG, "Error calling callback"); + } + } + }); + } + }; + + @Nullable + @Override + public final IBinder onBind(Intent intent) { + if (SERVICE_INTERFACE.equals(intent.getAction())) { + return mBinder; + } + return null; + } + + /** + * Returns suggested text selection start and end indices, recognized entity types, and their + * associated confidence scores. The entity types are ordered from highest to lowest scoring. + * + * @param text text providing context for the selected text (which is specified + * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex) + * @param selectionStartIndex start index of the selected part of text + * @param selectionEndIndex end index of the selected part of text + * @param options optional input parameters + * @param cancellationSignal object to watch for canceling the current operation + * @param callback the callback to return the result to + */ + public abstract void onSuggestSelection( + @NonNull CharSequence text, + @IntRange(from = 0) int selectionStartIndex, + @IntRange(from = 0) int selectionEndIndex, + @Nullable TextSelection.Options options, + @NonNull CancellationSignal cancellationSignal, + @NonNull Callback callback); + + /** + * Classifies the specified text and returns a {@link TextClassification} object that can be + * used to generate a widget for handling the classified text. + * + * @param text text providing context for the text to classify (which is specified + * by the sub sequence starting at startIndex and ending at endIndex) + * @param startIndex start index of the text to classify + * @param endIndex end index of the text to classify + * @param options optional input parameters + * @param cancellationSignal object to watch for canceling the current operation + * @param callback the callback to return the result to + */ + public abstract void onClassifyText( + @NonNull CharSequence text, + @IntRange(from = 0) int startIndex, + @IntRange(from = 0) int endIndex, + @Nullable TextClassification.Options options, + @NonNull CancellationSignal cancellationSignal, + @NonNull Callback callback); + + /** + * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with + * links information. + * + * @param text the text to generate annotations for + * @param options configuration for link generation + * @param cancellationSignal object to watch for canceling the current operation + * @param callback the callback to return the result to + */ + public abstract void onGenerateLinks( + @NonNull CharSequence text, + @Nullable TextLinks.Options options, + @NonNull CancellationSignal cancellationSignal, + @NonNull Callback callback); + + /** + * Callbacks for TextClassifierService results. + * + * @param the type of the result + * @hide + */ + @SystemApi + public interface Callback { + /** + * Returns the result. + */ + void onSuccess(T result); + + /** + * Signals a failure. + */ + void onFailure(CharSequence error); + } + + /** + * Returns the component name of the system default textclassifier service if it can be found + * on the system. Otherwise, returns null. + * @hide + */ + @Nullable + public static ComponentName getServiceComponentName(Context context) { + final String str = context.getString(R.string.config_defaultTextClassifierService); + if (!TextUtils.isEmpty(str)) { + try { + final ComponentName componentName = ComponentName.unflattenFromString(str); + final Intent intent = new Intent(SERVICE_INTERFACE).setComponent(componentName); + final ServiceInfo si = context.getPackageManager() + .getServiceInfo(intent.getComponent(), 0); + final String permission = si == null ? null : si.permission; + if (Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE.equals(permission)) { + return componentName; + } + Slog.w(LOG_TAG, String.format( + "Service %s should require %s permission. Found %s permission", + intent.getComponent().flattenToString(), + Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE, + si.permission)); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(LOG_TAG, String.format("Service %s not found", str)); + } + } else { + Slog.d(LOG_TAG, "No configured system TextClassifierService"); + } + return null; + } +} diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index de2dcce5bc5dfb3d906b2b5c5952000eb535157a..eba9129e81be5571b2f0caa73e05a081a10feb9f 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -166,7 +166,7 @@ public class DateFormat { * @return true if 24 hour time format is selected, false otherwise. */ public static boolean is24HourFormat(Context context) { - return is24HourFormat(context, UserHandle.myUserId()); + return is24HourFormat(context, context.getUserId()); } /** @@ -270,7 +270,7 @@ public class DateFormat { * @hide */ public static String getTimeFormatString(Context context) { - return getTimeFormatString(context, UserHandle.myUserId()); + return getTimeFormatString(context, context.getUserId()); } /** @@ -431,7 +431,7 @@ public class DateFormat { int c = s.charAt(i); if (c == QUOTE) { - count = appendQuotedText(s, i, len); + count = appendQuotedText(s, i); len = s.length(); continue; } @@ -574,36 +574,48 @@ public class DateFormat { : String.format(Locale.getDefault(), "%d", year); } - private static int appendQuotedText(SpannableStringBuilder s, int i, int len) { - if (i + 1 < len && s.charAt(i + 1) == QUOTE) { - s.delete(i, i + 1); + + /** + * Strips quotation marks from the {@code formatString} and appends the result back to the + * {@code formatString}. + * + * @param formatString the format string, as described in + * {@link android.text.format.DateFormat}, to be modified + * @param index index of the first quote + * @return the length of the quoted text that was appended. + * @hide + */ + public static int appendQuotedText(SpannableStringBuilder formatString, int index) { + int length = formatString.length(); + if (index + 1 < length && formatString.charAt(index + 1) == QUOTE) { + formatString.delete(index, index + 1); return 1; } int count = 0; // delete leading quote - s.delete(i, i + 1); - len--; + formatString.delete(index, index + 1); + length--; - while (i < len) { - char c = s.charAt(i); + while (index < length) { + char c = formatString.charAt(index); if (c == QUOTE) { // QUOTEQUOTE -> QUOTE - if (i + 1 < len && s.charAt(i + 1) == QUOTE) { + if (index + 1 < length && formatString.charAt(index + 1) == QUOTE) { - s.delete(i, i + 1); - len--; + formatString.delete(index, index + 1); + length--; count++; - i++; + index++; } else { // Closing QUOTE ends quoted text copying - s.delete(i, i + 1); + formatString.delete(index, index + 1); break; } } else { - i++; + index++; count++; } } diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java index 35241796c3c3446f21d28a05a1c1273870dddd64..cd199b3547c9a2ea5f9f08d32992e07178e0711f 100644 --- a/core/java/android/text/style/DrawableMarginSpan.java +++ b/core/java/android/text/style/DrawableMarginSpan.java @@ -16,60 +16,100 @@ package android.text.style; +import android.annotation.NonNull; +import android.annotation.Px; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.Spanned; -public class DrawableMarginSpan -implements LeadingMarginSpan, LineHeightSpan -{ - public DrawableMarginSpan(Drawable b) { - mDrawable = b; +/** + * A span which adds a drawable and a padding to the paragraph it's attached to. + *

    + * If the height of the drawable is bigger than the height of the line it's attached to then the + * line height is increased to fit the drawable. DrawableMarginSpan allows setting a + * padding between the drawable and the text. The default value is 0. The span must be set from the + * beginning of the text, otherwise either the span won't be rendered or it will be rendered + * incorrectly. + *

    + * For example, a drawable and a padding of 20px can be added like this: + *

    {@code SpannableString string = new SpannableString("Text with a drawable.");
    + * string.setSpan(new DrawableMarginSpan(drawable, 20), 0, string.length(),
    + * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}
    + * + *
    Text with a drawable and a padding.
    + *

    + * + * @see IconMarginSpan for working with a {@link android.graphics.Bitmap} instead of + * a {@link Drawable}. + */ +public class DrawableMarginSpan implements LeadingMarginSpan, LineHeightSpan { + private static final int STANDARD_PAD_WIDTH = 0; + + @NonNull + private final Drawable mDrawable; + @Px + private final int mPad; + + /** + * Creates a {@link DrawableMarginSpan} from a {@link Drawable}. The pad width will be 0. + * + * @param drawable the drawable to be added + */ + public DrawableMarginSpan(@NonNull Drawable drawable) { + this(drawable, STANDARD_PAD_WIDTH); } - public DrawableMarginSpan(Drawable b, int pad) { - mDrawable = b; + /** + * Creates a {@link DrawableMarginSpan} from a {@link Drawable} and a padding, in pixels. + * + * @param drawable the drawable to be added + * @param pad the distance between the drawable and the text + */ + public DrawableMarginSpan(@NonNull Drawable drawable, int pad) { + mDrawable = drawable; mPad = pad; } + @Override public int getLeadingMargin(boolean first) { return mDrawable.getIntrinsicWidth() + mPad; } - public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, - int top, int baseline, int bottom, - CharSequence text, int start, int end, - boolean first, Layout layout) { + @Override + public void drawLeadingMargin(@NonNull Canvas c, @NonNull Paint p, int x, int dir, + int top, int baseline, int bottom, + @NonNull CharSequence text, int start, int end, + boolean first, @NonNull Layout layout) { int st = ((Spanned) text).getSpanStart(this); - int ix = (int)x; - int itop = (int)layout.getLineTop(layout.getLineForOffset(st)); + int ix = (int) x; + int itop = (int) layout.getLineTop(layout.getLineForOffset(st)); int dw = mDrawable.getIntrinsicWidth(); int dh = mDrawable.getIntrinsicHeight(); // XXX What to do about Paint? - mDrawable.setBounds(ix, itop, ix+dw, itop+dh); + mDrawable.setBounds(ix, itop, ix + dw, itop + dh); mDrawable.draw(c); } - public void chooseHeight(CharSequence text, int start, int end, - int istartv, int v, - Paint.FontMetricsInt fm) { + @Override + public void chooseHeight(@NonNull CharSequence text, int start, int end, + int istartv, int v, + @NonNull Paint.FontMetricsInt fm) { if (end == ((Spanned) text).getSpanEnd(this)) { int ht = mDrawable.getIntrinsicHeight(); int need = ht - (v + fm.descent - fm.ascent - istartv); - if (need > 0) + if (need > 0) { fm.descent += need; + } need = ht - (v + fm.bottom - fm.top - istartv); - if (need > 0) + if (need > 0) { fm.bottom += need; + } } } - - private Drawable mDrawable; - private int mPad; } diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java index 5b8a6dd3bf6fbb709832abe2745b3d79a915b5ec..1b16f3345bfa31762a2b493caacb81facb12ec9d 100644 --- a/core/java/android/text/style/DynamicDrawableSpan.java +++ b/core/java/android/text/style/DynamicDrawableSpan.java @@ -16,6 +16,9 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; @@ -24,32 +27,71 @@ import android.graphics.drawable.Drawable; import java.lang.ref.WeakReference; /** + * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with + * the bottom or with the baseline of the surrounding text. + *

    + * For an implementation that constructs the drawable from various sources (Bitmap, + * Drawable, resource id or Uri) use {@link ImageSpan}. + *

    + * A simple implementation of DynamicDrawableSpan that uses drawables from resources + * looks like this: + *

    + * class MyDynamicDrawableSpan extends DynamicDrawableSpan {
      *
    + * private final Context mContext;
    + * private final int mResourceId;
    + *
    + * public MyDynamicDrawableSpan(Context context, @DrawableRes int resourceId) {
    + *     mContext = context;
    + *     mResourceId = resourceId;
    + * }
    + *
    + * {@literal @}Override
    + * public Drawable getDrawable() {
    + *      Drawable drawable = mContext.getDrawable(mResourceId);
    + *      drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    + *      return drawable;
    + * }
    + * }
    + * The class can be used like this: + *
    + * SpannableString string = new SpannableString("Text with a drawable span");
    + * string.setSpan(new MyDynamicDrawableSpan(context, R.mipmap.ic_launcher), 12, 20, Spanned
    + * .SPAN_EXCLUSIVE_EXCLUSIVE);
    + * + *
    Replacing text with a drawable.
    */ public abstract class DynamicDrawableSpan extends ReplacementSpan { - private static final String TAG = "DynamicDrawableSpan"; - + /** * A constant indicating that the bottom of this span should be aligned * with the bottom of the surrounding text, i.e., at the same level as the * lowest descender in the text. */ public static final int ALIGN_BOTTOM = 0; - + /** * A constant indicating that the bottom of this span should be aligned * with the baseline of the surrounding text. */ public static final int ALIGN_BASELINE = 1; - + protected final int mVerticalAlignment; - + + private WeakReference mDrawableRef; + + /** + * Creates a {@link DynamicDrawableSpan}. The default vertical alignment is + * {@link #ALIGN_BOTTOM} + */ public DynamicDrawableSpan() { mVerticalAlignment = ALIGN_BOTTOM; } /** - * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}. + * Creates a {@link DynamicDrawableSpan} based on a vertical alignment.\ + * + * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE} */ protected DynamicDrawableSpan(int verticalAlignment) { mVerticalAlignment = verticalAlignment; @@ -64,22 +106,22 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { } /** - * Your subclass must implement this method to provide the bitmap + * Your subclass must implement this method to provide the bitmap * to be drawn. The dimensions of the bitmap must be the same * from each call to the next. */ public abstract Drawable getDrawable(); @Override - public int getSize(Paint paint, CharSequence text, - int start, int end, - Paint.FontMetricsInt fm) { + public int getSize(@NonNull Paint paint, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, + @Nullable Paint.FontMetricsInt fm) { Drawable d = getCachedDrawable(); Rect rect = d.getBounds(); if (fm != null) { - fm.ascent = -rect.bottom; - fm.descent = 0; + fm.ascent = -rect.bottom; + fm.descent = 0; fm.top = fm.ascent; fm.bottom = 0; @@ -89,12 +131,12 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { } @Override - public void draw(Canvas canvas, CharSequence text, - int start, int end, float x, - int top, int y, int bottom, Paint paint) { + public void draw(@NonNull Canvas canvas, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x, + int top, int y, int bottom, @NonNull Paint paint) { Drawable b = getCachedDrawable(); canvas.save(); - + int transY = bottom - b.getBounds().bottom; if (mVerticalAlignment == ALIGN_BASELINE) { transY -= paint.getFontMetricsInt().descent; @@ -109,8 +151,9 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { WeakReference wr = mDrawableRef; Drawable d = null; - if (wr != null) + if (wr != null) { d = wr.get(); + } if (d == null) { d = getDrawable(); @@ -119,7 +162,5 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { return d; } - - private WeakReference mDrawableRef; } diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java index 304c83f19f02cf44496bd4c4ab00889b1971f316..ad78bd57469606fae0461de67ad1182e0b434b6e 100644 --- a/core/java/android/text/style/IconMarginSpan.java +++ b/core/java/android/text/style/IconMarginSpan.java @@ -16,57 +16,98 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Px; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.text.Layout; import android.text.Spanned; -public class IconMarginSpan -implements LeadingMarginSpan, LineHeightSpan -{ - public IconMarginSpan(Bitmap b) { - mBitmap = b; +/** + * Paragraph affecting span, that draws a bitmap at the beginning of a text. The span also allows + * setting a padding between the bitmap and the text. The default value of the padding is 0px. The + * span should be attached from the first character of the text. + *

    + * For example, an IconMarginSpan with a bitmap and a padding of 30px can be set + * like this: + *

    + * SpannableString string = new SpannableString("Text with icon and padding");
    + * string.setSpan(new IconMarginSpan(bitmap, 30), 0, string.length(),
    + * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * 
    + * + *
    Text with IconMarginSpan
    + *

    + * + * @see DrawableMarginSpan for working with a {@link android.graphics.drawable.Drawable} instead of + * a {@link Bitmap}. + */ +public class IconMarginSpan implements LeadingMarginSpan, LineHeightSpan { + + @NonNull + private final Bitmap mBitmap; + @Px + private final int mPad; + + /** + * Creates an {@link IconMarginSpan} from a {@link Bitmap}. + * + * @param bitmap bitmap to be rendered at the beginning of the text + */ + public IconMarginSpan(@NonNull Bitmap bitmap) { + this(bitmap, 0); } - public IconMarginSpan(Bitmap b, int pad) { - mBitmap = b; + /** + * Creates an {@link IconMarginSpan} from a {@link Bitmap}. + * + * @param bitmap bitmap to be rendered at the beginning of the text + * @param pad padding width, in pixels, between the bitmap and the text + */ + public IconMarginSpan(@NonNull Bitmap bitmap, @IntRange(from = 0) int pad) { + mBitmap = bitmap; mPad = pad; } + @Override public int getLeadingMargin(boolean first) { return mBitmap.getWidth() + mPad; } + @Override public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, - int top, int baseline, int bottom, - CharSequence text, int start, int end, - boolean first, Layout layout) { + int top, int baseline, int bottom, + CharSequence text, int start, int end, + boolean first, Layout layout) { int st = ((Spanned) text).getSpanStart(this); int itop = layout.getLineTop(layout.getLineForOffset(st)); - if (dir < 0) + if (dir < 0) { x -= mBitmap.getWidth(); + } c.drawBitmap(mBitmap, x, itop, p); } + @Override public void chooseHeight(CharSequence text, int start, int end, - int istartv, int v, - Paint.FontMetricsInt fm) { + int istartv, int v, + Paint.FontMetricsInt fm) { if (end == ((Spanned) text).getSpanEnd(this)) { int ht = mBitmap.getHeight(); int need = ht - (v + fm.descent - fm.ascent - istartv); - if (need > 0) + if (need > 0) { fm.descent += need; + } need = ht - (v + fm.bottom - fm.top - istartv); - if (need > 0) + if (need > 0) { fm.bottom += need; + } } } - private Bitmap mBitmap; - private int mPad; } diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java index b0bff680f390a209e67220be9d420686bc38770a..95f0b43341a27160c5596d8723459b3f3d3dcd59 100644 --- a/core/java/android/text/style/ImageSpan.java +++ b/core/java/android/text/style/ImageSpan.java @@ -17,6 +17,8 @@ package android.text.style; import android.annotation.DrawableRes; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -27,18 +29,49 @@ import android.util.Log; import java.io.InputStream; +/** + * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with + * the bottom or with the baseline of the surrounding text. The drawable can be constructed from + * varied sources: + *

      + *
    • {@link Bitmap} - see {@link #ImageSpan(Context, Bitmap)} and + * {@link #ImageSpan(Context, Bitmap, int)} + *
    • + *
    • {@link Drawable} - see {@link #ImageSpan(Drawable, int)}
    • + *
    • resource id - see {@link #ImageSpan(Context, int, int)}
    • + *
    • {@link Uri} - see {@link #ImageSpan(Context, Uri, int)}
    • + *
    + * The default value for the vertical alignment is {@link DynamicDrawableSpan#ALIGN_BOTTOM} + *

    + * For example, an ImagedSpan can be used like this: + *

    + * SpannableString string = SpannableString("Bottom: span.\nBaseline: span.");
    + * // using the default alignment: ALIGN_BOTTOM
    + * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher), 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE),
    + * 22, 23, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * 
    + * + *
    Text with ImageSpans aligned bottom and baseline.
    + */ public class ImageSpan extends DynamicDrawableSpan { + + @Nullable private Drawable mDrawable; + @Nullable private Uri mContentUri; + @DrawableRes private int mResourceId; + @Nullable private Context mContext; + @Nullable private String mSource; /** * @deprecated Use {@link #ImageSpan(Context, Bitmap)} instead. */ @Deprecated - public ImageSpan(Bitmap b) { + public ImageSpan(@NonNull Bitmap b) { this(null, b, ALIGN_BOTTOM); } @@ -46,80 +79,143 @@ public class ImageSpan extends DynamicDrawableSpan { * @deprecated Use {@link #ImageSpan(Context, Bitmap, int)} instead. */ @Deprecated - public ImageSpan(Bitmap b, int verticalAlignment) { + public ImageSpan(@NonNull Bitmap b, int verticalAlignment) { this(null, b, verticalAlignment); } - public ImageSpan(Context context, Bitmap b) { - this(context, b, ALIGN_BOTTOM); + /** + * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Bitmap} with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * + * @param context context used to create a drawable from {@param bitmap} based on the display + * metrics of the resources + * @param bitmap bitmap to be rendered + */ + public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap) { + this(context, bitmap, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Bitmap} and a vertical + * alignment. + * + * @param context context used to create a drawable from {@param bitmap} based on + * the display metrics of the resources + * @param bitmap bitmap to be rendered * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Context context, Bitmap b, int verticalAlignment) { + public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap, int verticalAlignment) { super(verticalAlignment); mContext = context; mDrawable = context != null - ? new BitmapDrawable(context.getResources(), b) - : new BitmapDrawable(b); + ? new BitmapDrawable(context.getResources(), bitmap) + : new BitmapDrawable(bitmap); int width = mDrawable.getIntrinsicWidth(); int height = mDrawable.getIntrinsicHeight(); - mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); + mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); } - public ImageSpan(Drawable d) { - this(d, ALIGN_BOTTOM); + /** + * Constructs an {@link ImageSpan} from a drawable with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. + * + * @param drawable drawable to be rendered + */ + public ImageSpan(@NonNull Drawable drawable) { + this(drawable, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a drawable and a vertical alignment. + * + * @param drawable drawable to be rendered * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Drawable d, int verticalAlignment) { + public ImageSpan(@NonNull Drawable drawable, int verticalAlignment) { super(verticalAlignment); - mDrawable = d; + mDrawable = drawable; } - public ImageSpan(Drawable d, String source) { - this(d, source, ALIGN_BOTTOM); + /** + * Constructs an {@link ImageSpan} from a drawable and a source with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * + * @param drawable drawable to be rendered + * @param source drawable's Uri source + */ + public ImageSpan(@NonNull Drawable drawable, @NonNull String source) { + this(drawable, source, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a drawable, a source and a vertical alignment. + * + * @param drawable drawable to be rendered + * @param source drawable's uri source * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Drawable d, String source, int verticalAlignment) { + public ImageSpan(@NonNull Drawable drawable, @NonNull String source, int verticalAlignment) { super(verticalAlignment); - mDrawable = d; + mDrawable = drawable; mSource = source; } - public ImageSpan(Context context, Uri uri) { + /** + * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Uri} with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. The Uri source can be retrieved via + * {@link #getSource()} + * + * @param context context used to create a drawable from {@param bitmap} based on the display + * metrics of the resources + * @param uri {@link Uri} used to construct the drawable that will be rendered + */ + public ImageSpan(@NonNull Context context, @NonNull Uri uri) { this(context, uri, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Uri} and a vertical + * alignment. The Uri source can be retrieved via {@link #getSource()} + * + * @param context context used to create a drawable from {@param bitmap} based on + * the display + * metrics of the resources + * @param uri {@link Uri} used to construct the drawable that will be rendered. * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Context context, Uri uri, int verticalAlignment) { + public ImageSpan(@NonNull Context context, @NonNull Uri uri, int verticalAlignment) { super(verticalAlignment); mContext = context; mContentUri = uri; mSource = uri.toString(); } - public ImageSpan(Context context, @DrawableRes int resourceId) { + /** + * Constructs an {@link ImageSpan} from a {@link Context} and a resource id with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * + * @param context context used to retrieve the drawable from resources + * @param resourceId drawable resource id based on which the drawable is retrieved + */ + public ImageSpan(@NonNull Context context, @DrawableRes int resourceId) { this(context, resourceId, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a {@link Context}, a resource id and a vertical + * alignment. + * + * @param context context used to retrieve the drawable from resources + * @param resourceId drawable resource id based on which the drawable is retrieved. * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Context context, @DrawableRes int resourceId, int verticalAlignment) { + public ImageSpan(@NonNull Context context, @DrawableRes int resourceId, + int verticalAlignment) { super(verticalAlignment); mContext = context; mResourceId = resourceId; @@ -128,10 +224,10 @@ public class ImageSpan extends DynamicDrawableSpan { @Override public Drawable getDrawable() { Drawable drawable = null; - + if (mDrawable != null) { drawable = mDrawable; - } else if (mContentUri != null) { + } else if (mContentUri != null) { Bitmap bitmap = null; try { InputStream is = mContext.getContentResolver().openInputStream( @@ -142,7 +238,7 @@ public class ImageSpan extends DynamicDrawableSpan { drawable.getIntrinsicHeight()); is.close(); } catch (Exception e) { - Log.e("sms", "Failed to loaded content " + mContentUri, e); + Log.e("ImageSpan", "Failed to loaded content " + mContentUri, e); } } else { try { @@ -150,8 +246,8 @@ public class ImageSpan extends DynamicDrawableSpan { drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); } catch (Exception e) { - Log.e("sms", "Unable to find resource: " + mResourceId); - } + Log.e("ImageSpan", "Unable to find resource: " + mResourceId); + } } return drawable; @@ -159,9 +255,12 @@ public class ImageSpan extends DynamicDrawableSpan { /** * Returns the source string that was saved during construction. + * + * @return the source string that was saved during construction + * @see #ImageSpan(Drawable, String) and this{@link #ImageSpan(Context, Uri)} */ + @Nullable public String getSource() { return mSource; } - } diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java index 1ebee82c18a82b1982ac3dfe6cdda283486259f2..50ee5f3875955168b15ac938f185fe59fd8cf896 100644 --- a/core/java/android/text/style/LineHeightSpan.java +++ b/core/java/android/text/style/LineHeightSpan.java @@ -19,16 +19,42 @@ package android.text.style; import android.graphics.Paint; import android.text.TextPaint; -public interface LineHeightSpan -extends ParagraphStyle, WrapTogetherSpan -{ +/** + * The classes that affect the height of the line should implement this interface. + */ +public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan { + /** + * Classes that implement this should define how the height is being calculated. + * + * @param text the text + * @param start the start of the line + * @param end the end of the line + * @param spanstartv the start of the span + * @param lineHeight the line height + * @param fm font metrics of the paint, in integers + */ public void chooseHeight(CharSequence text, int start, int end, - int spanstartv, int v, - Paint.FontMetricsInt fm); + int spanstartv, int lineHeight, + Paint.FontMetricsInt fm); + /** + * The classes that affect the height of the line with respect to density, should implement this + * interface. + */ public interface WithDensity extends LineHeightSpan { + + /** + * Classes that implement this should define how the height is being calculated. + * + * @param text the text + * @param start the start of the line + * @param end the end of the line + * @param spanstartv the start of the span + * @param lineHeight the line height + * @param paint the paint + */ public void chooseHeight(CharSequence text, int start, int end, - int spanstartv, int v, - Paint.FontMetricsInt fm, TextPaint paint); + int spanstartv, int lineHeight, + Paint.FontMetricsInt fm, TextPaint paint); } } diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java index 2ff52a8f70e8b9241191a67d17b81c4347554bf3..d76ef941d42edf54b38f8a2107e3c4514517c042 100644 --- a/core/java/android/text/style/MaskFilterSpan.java +++ b/core/java/android/text/style/MaskFilterSpan.java @@ -18,15 +18,36 @@ package android.text.style; import android.graphics.MaskFilter; import android.text.TextPaint; - +/** + * Span that allows setting a {@link MaskFilter} to the text it's attached to. + *

    + * For example, to blur a text, a {@link android.graphics.BlurMaskFilter} can be used: + *

    + * MaskFilter blurMask = new BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL);
    + * SpannableString string = new SpannableString("Text with blur mask");
    + * string.setSpan(new MaskFilterSpan(blurMask), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * 
    + * + *
    Text blurred with the MaskFilterSpan.
    + */ public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance { private MaskFilter mFilter; + /** + * Creates a {@link MaskFilterSpan} from a {@link MaskFilter}. + * + * @param filter the filter to be applied to the TextPaint + */ public MaskFilterSpan(MaskFilter filter) { mFilter = filter; } + /** + * Return the mask filter for this span. + * + * @return the mask filter for this span + */ public MaskFilter getMaskFilter() { return mFilter; } diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java index f900db502d0d00a6856280a4824ff2cadb3542b8..bdfa700215f8aa1837b6499116fcbc543450e90a 100644 --- a/core/java/android/text/style/StyleSpan.java +++ b/core/java/android/text/style/StyleSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.annotation.NonNull; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Parcel; @@ -24,55 +25,76 @@ import android.text.TextPaint; import android.text.TextUtils; /** - * - * Describes a style in a span. + * Span that allows setting the style of the text it's attached to. + * Possible styles are: {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC} and + * {@link Typeface#BOLD_ITALIC}. + *

    * Note that styles are cumulative -- if both bold and italic are set in * separate spans, or if the base style is bold and a span calls for italic, * you get bold italic. You can't turn off a style from the base style. - * + *

    + * For example, the StyleSpan can be used like this: + *

    + * SpannableString string = new SpannableString("Bold and italic text");
    + * string.setSpan(new StyleSpan(Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * string.setSpan(new StyleSpan(Typeface.ITALIC), 9, 15, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * 
    + * + *
    Text styled bold and italic with the StyleSpan.
    */ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan { private final int mStyle; /** - * + * Creates a {@link StyleSpan} from a style. + * * @param style An integer constant describing the style for this span. Examples - * include bold, italic, and normal. Values are constants defined - * in {@link android.graphics.Typeface}. + * include bold, italic, and normal. Values are constants defined + * in {@link Typeface}. */ public StyleSpan(int style) { mStyle = style; } - public StyleSpan(Parcel src) { + /** + * Creates a {@link StyleSpan} from a parcel. + * + * @param src the parcel + */ + public StyleSpan(@NonNull Parcel src) { mStyle = src.readInt(); } - + + @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } /** @hide */ + @Override public int getSpanTypeIdInternal() { return TextUtils.STYLE_SPAN; } - + + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeInt(mStyle); } /** - * Returns the style constant defined in {@link android.graphics.Typeface}. + * Returns the style constant defined in {@link Typeface}. */ public int getStyle() { return mStyle; diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java index 056642841815052b47e579c91dc9b0ee8f7dc093..2cceb2c8ced9daf3343449b1dd50139e0ae0a1e1 100644 --- a/core/java/android/text/style/TabStopSpan.java +++ b/core/java/android/text/style/TabStopSpan.java @@ -16,39 +16,54 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.Px; + /** - * Represents a single tab stop on a line. + * Paragraph affecting span that changes the position of the tab with respect to + * the leading margin of the line. TabStopSpan will only affect the first tab + * encountered on the first line of the text. */ -public interface TabStopSpan -extends ParagraphStyle -{ +public interface TabStopSpan extends ParagraphStyle { + /** - * Returns the offset of the tab stop from the leading margin of the - * line. - * @return the offset + * Returns the offset of the tab stop from the leading margin of the line, in pixels. + * + * @return the offset, in pixels */ - public int getTabStop(); + int getTabStop(); /** - * The default implementation of TabStopSpan. + * The default implementation of TabStopSpan that allows setting the offset of the tab stop + * from the leading margin of the first line of text. + *

    + * Let's consider that we have the following text: "\tParagraph text beginning with tab." + * and we want to move the tab stop with 100px. This can be achieved like this: + *

    +     * SpannableString string = new SpannableString("\tParagraph text beginning with tab.");
    +     * string.setSpan(new TabStopSpan.Standard(100), 0, string.length(),
    +     * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * + *
    Text with a tab stop and a TabStopSpan
    */ - public static class Standard - implements TabStopSpan - { + class Standard implements TabStopSpan { + + @Px + private int mTabOffset; + /** - * Constructor. + * Constructs a {@link TabStopSpan.Standard} based on an offset. * - * @param where the offset of the tab stop from the leading margin of - * the line + * @param offset the offset of the tab stop from the leading margin of + * the line, in pixels */ - public Standard(int where) { - mTab = where; + public Standard(@IntRange(from = 0) int offset) { + mTabOffset = offset; } + @Override public int getTabStop() { - return mTab; + return mTabOffset; } - - private int mTab; } } diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java index aa622d87c74e7f6fd825e4ec820d52819a6e2d1b..1622812502087ad929f7a70a69da92993a9ac7e0 100644 --- a/core/java/android/text/style/TypefaceSpan.java +++ b/core/java/android/text/style/TypefaceSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.annotation.NonNull; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Parcel; @@ -24,42 +25,59 @@ import android.text.TextPaint; import android.text.TextUtils; /** - * Changes the typeface family of the text to which the span is attached. + * Changes the typeface family of the text to which the span is attached. Examples of typeface + * family include "monospace", "serif", and "sans-serif". + *

    + * For example, change the typeface of a text to "monospace" like this: + *

    + * SpannableString string = new SpannableString("Text with typeface span");
    + * string.setSpan(new TypefaceSpan("monospace"), 10, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * 
    + * + *
    Text with "monospace" typeface family.
    */ public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan { + private final String mFamily; /** - * @param family The font family for this typeface. Examples include - * "monospace", "serif", and "sans-serif". + * Constructs a {@link TypefaceSpan} based on a font family. + * + * @param family The font family for this typeface. Examples include + * "monospace", "serif", and "sans-serif". */ public TypefaceSpan(String family) { mFamily = family; } - public TypefaceSpan(Parcel src) { + public TypefaceSpan(@NonNull Parcel src) { mFamily = src.readString(); } - + + @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } /** @hide */ + @Override public int getSpanTypeIdInternal() { return TextUtils.TYPEFACE_SPAN; } - + + @Override public int describeContents() { return 0; } - public void writeToParcel(Parcel dest, int flags) { + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeString(mFamily); } @@ -71,16 +89,16 @@ public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan } @Override - public void updateDrawState(TextPaint ds) { - apply(ds, mFamily); + public void updateDrawState(@NonNull TextPaint textPaint) { + apply(textPaint, mFamily); } @Override - public void updateMeasureState(TextPaint paint) { - apply(paint, mFamily); + public void updateMeasureState(@NonNull TextPaint textPaint) { + apply(textPaint, mFamily); } - private static void apply(Paint paint, String family) { + private static void apply(@NonNull Paint paint, String family) { int oldStyle; Typeface old = paint.getTypeface(); diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java index 58239efe5c5f61e75165a7a5f1a50ff8b57c7b40..eab1ef4f6afd5e430ec541218fed18746ad73d80 100644 --- a/core/java/android/text/style/URLSpan.java +++ b/core/java/android/text/style/URLSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.annotation.NonNull; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -27,40 +28,71 @@ import android.text.TextUtils; import android.util.Log; import android.view.View; +/** + * Implementation of the {@link ClickableSpan} that allows setting a url string. When + * selecting and clicking on the text to which the span is attached, the URLSpan + * will try to open the url, by launching an an Activity with an {@link Intent#ACTION_VIEW} intent. + *

    + * For example, a URLSpan can be used like this: + *

    + * SpannableString string = new SpannableString("Text with a url span");
    + * string.setSpan(new URLSpan("http://www.developer.android.com"), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    + * 
    + * + *
    Text with URLSpan.
    + */ public class URLSpan extends ClickableSpan implements ParcelableSpan { private final String mURL; + /** + * Constructs a {@link URLSpan} from a url string. + * + * @param url the url string + */ public URLSpan(String url) { mURL = url; } - public URLSpan(Parcel src) { + /** + * Constructs a {@link URLSpan} from a parcel. + */ + public URLSpan(@NonNull Parcel src) { mURL = src.readString(); } - + + @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } /** @hide */ + @Override public int getSpanTypeIdInternal() { return TextUtils.URL_SPAN; } - + + @Override public int describeContents() { return 0; } - public void writeToParcel(Parcel dest, int flags) { + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeString(mURL); } + /** + * Get the url string for this span. + * + * @return the url string. + */ public String getURL() { return mURL; } diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java index 768aee91e5b3e0e532dcf973669099ff3a749105..d973d4ac076c021076aead232eb52b7c3b91406a 100644 --- a/core/java/android/text/util/Linkify.java +++ b/core/java/android/text/util/Linkify.java @@ -19,6 +19,7 @@ package android.text.util; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UiThread; import android.content.Context; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; @@ -29,12 +30,16 @@ import android.text.method.LinkMovementMethod; import android.text.method.MovementMethod; import android.text.style.URLSpan; import android.util.Patterns; +import android.view.textclassifier.TextClassifier; +import android.view.textclassifier.TextLinks; +import android.view.textclassifier.TextLinks.TextLinkSpan; import android.webkit.WebView; import android.widget.TextView; import com.android.i18n.phonenumbers.PhoneNumberMatch; import com.android.i18n.phonenumbers.PhoneNumberUtil; import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency; +import com.android.internal.util.Preconditions; import libcore.util.EmptyArray; @@ -46,6 +51,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Future; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -479,6 +490,195 @@ public class Linkify { return hasMatches; } + /** + * Scans the text of the provided TextView and turns all occurrences of the entity types + * specified by {@code options} into clickable links. If links are found, this method + * removes any pre-existing {@link TextLinkSpan} attached to the text (to avoid + * problems if you call it repeatedly on the same text) and sets the movement method for the + * TextView to LinkMovementMethod. + * + *

    Note: This method returns immediately but generates the links with + * the specified classifier on a background thread. The generated links are applied on the + * calling thread. + * + * @param textView TextView whose text is to be marked-up with links + * @param options optional parameters to specify how to generate the links + * + * @return a future that may be used to interrupt or query the background task + */ + @UiThread + public static Future addLinksAsync( + @NonNull TextView textView, + @Nullable TextLinks.Options options) { + return addLinksAsync(textView, options, null /* executor */, null /* callback */); + } + + /** + * Scans the text of the provided TextView and turns all occurrences of the entity types + * specified by {@code options} into clickable links. If links are found, this method + * removes any pre-existing {@link TextLinkSpan} attached to the text (to avoid + * problems if you call it repeatedly on the same text) and sets the movement method for the + * TextView to LinkMovementMethod. + * + *

    Note: This method returns immediately but generates the links with + * the specified classifier on a background thread. The generated links are applied on the + * calling thread. + * + * @param textView TextView whose text is to be marked-up with links + * @param options optional parameters to specify how to generate the links + * @param executor Executor that runs the background task + * @param callback Callback that receives the final status of the background task execution + * + * @return a future that may be used to interrupt or query the background task + */ + @UiThread + public static Future addLinksAsync( + @NonNull TextView textView, + @Nullable TextLinks.Options options, + @Nullable Executor executor, + @Nullable Consumer callback) { + Preconditions.checkNotNull(textView); + final CharSequence text = textView.getText(); + final Spannable spannable = (text instanceof Spannable) + ? (Spannable) text : SpannableString.valueOf(text); + final Runnable modifyTextView = () -> { + addLinkMovementMethod(textView); + if (spannable != text) { + textView.setText(spannable); + } + }; + return addLinksAsync(spannable, textView.getTextClassifier(), + options, executor, callback, modifyTextView); + } + + /** + * Scans the text of the provided TextView and turns all occurrences of the entity types + * specified by {@code options} into clickable links. If links are found, this method + * removes any pre-existing {@link TextLinkSpan} attached to the text to avoid + * problems if you call it repeatedly on the same text. + * + *

    Note: This method returns immediately but generates the links with + * the specified classifier on a background thread. The generated links are applied on the + * calling thread. + * + *

    Note: If the text is currently attached to a TextView, this method + * should be called on the UI thread. + * + * @param text Spannable whose text is to be marked-up with links + * @param classifier the TextClassifier to use to generate the links + * @param options optional parameters to specify how to generate the links + * + * @return a future that may be used to interrupt or query the background task + */ + public static Future addLinksAsync( + @NonNull Spannable text, + @NonNull TextClassifier classifier, + @Nullable TextLinks.Options options) { + return addLinksAsync(text, classifier, options, null /* executor */, null /* callback */); + } + + /** + * Scans the text of the provided TextView and turns all occurrences of the entity types + * specified by the link {@code mask} into clickable links. If links are found, this method + * removes any pre-existing {@link TextLinkSpan} attached to the text to avoid + * problems if you call it repeatedly on the same text. + * + *

    Note: This method returns immediately but generates the links with + * the specified classifier on a background thread. The generated links are applied on the + * calling thread. + * + *

    Note: If the text is currently attached to a TextView, this method + * should be called on the UI thread. + * + * @param text Spannable whose text is to be marked-up with links + * @param classifier the TextClassifier to use to generate the links + * @param mask mask to define which kinds of links will be generated + * + * @return a future that may be used to interrupt or query the background task + */ + public static Future addLinksAsync( + @NonNull Spannable text, + @NonNull TextClassifier classifier, + @LinkifyMask int mask) { + return addLinksAsync(text, classifier, TextLinks.Options.fromLinkMask(mask), + null /* executor */, null /* callback */); + } + + /** + * Scans the text of the provided TextView and turns all occurrences of the entity types + * specified by {@code options} into clickable links. If links are found, this method + * removes any pre-existing {@link TextLinkSpan} attached to the text to avoid + * problems if you call it repeatedly on the same text. + * + *

    Note: This method returns immediately but generates the links with + * the specified classifier on a background thread. The generated links are applied on the + * calling thread. + * + *

    Note: If the text is currently attached to a TextView, this method + * should be called on the UI thread. + * + * @param text Spannable whose text is to be marked-up with links + * @param classifier the TextClassifier to use to generate the links + * @param options optional parameters to specify how to generate the links + * @param executor Executor that runs the background task + * @param callback Callback that receives the final status of the background task execution + * + * @return a future that may be used to interrupt or query the background task + */ + public static Future addLinksAsync( + @NonNull Spannable text, + @NonNull TextClassifier classifier, + @Nullable TextLinks.Options options, + @Nullable Executor executor, + @Nullable Consumer callback) { + return addLinksAsync(text, classifier, options, executor, callback, + null /* modifyTextView */); + } + + private static Future addLinksAsync( + @NonNull Spannable text, + @NonNull TextClassifier classifier, + @Nullable TextLinks.Options options, + @Nullable Executor executor, + @Nullable Consumer callback, + @Nullable Runnable modifyTextView) { + Preconditions.checkNotNull(text); + Preconditions.checkNotNull(classifier); + final Supplier supplier = () -> classifier.generateLinks(text, options); + final Consumer consumer = links -> { + if (links.getLinks().isEmpty()) { + if (callback != null) { + callback.accept(TextLinks.STATUS_NO_LINKS_FOUND); + } + return; + } + + final TextLinkSpan[] old = text.getSpans(0, text.length(), TextLinkSpan.class); + for (int i = old.length - 1; i >= 0; i--) { + text.removeSpan(old[i]); + } + + final Function spanFactory = (options == null) + ? null : options.getSpanFactory(); + final @TextLinks.ApplyStrategy int applyStrategy = (options == null) + ? TextLinks.APPLY_STRATEGY_IGNORE : options.getApplyStrategy(); + final @TextLinks.Status int result = links.apply(text, applyStrategy, spanFactory); + if (result == TextLinks.STATUS_LINKS_APPLIED) { + if (modifyTextView != null) { + modifyTextView.run(); + } + } + if (callback != null) { + callback.accept(result); + } + }; + if (executor == null) { + return CompletableFuture.supplyAsync(supplier).thenAccept(consumer); + } else { + return CompletableFuture.supplyAsync(supplier, executor).thenAccept(consumer); + } + } + private static final void applyLink(String url, int start, int end, Spannable text) { URLSpan span = new URLSpan(url); diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java index 084b79d5830185c53952eb365d32c15e21af7756..60b77bc8d4260d0528c29947a582aeed103da8b3 100644 --- a/core/java/android/transition/TransitionUtils.java +++ b/core/java/android/transition/TransitionUtils.java @@ -163,10 +163,14 @@ public class TransitionUtils { public static Bitmap createViewBitmap(View view, Matrix matrix, RectF bounds, ViewGroup sceneRoot) { final boolean addToOverlay = !view.isAttachedToWindow(); + ViewGroup parent = null; + int indexInParent = 0; if (addToOverlay) { if (sceneRoot == null || !sceneRoot.isAttachedToWindow()) { return null; } + parent = (ViewGroup) view.getParent(); + indexInParent = parent.indexOfChild(view); sceneRoot.getOverlay().add(view); } Bitmap bitmap = null; @@ -190,6 +194,7 @@ public class TransitionUtils { } if (addToOverlay) { sceneRoot.getOverlay().remove(view); + parent.addView(view, indexInParent); } return bitmap; } diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index f0838a169a4557eb2c08035928cd116c1f02126e..77c652ecf5f9a1403e4297e6780efb65f585f982 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -402,8 +402,11 @@ public abstract class Visibility extends Transition { // Becoming GONE if (startView == endView) { viewToKeep = endView; - } else { + } else if (mCanRemoveViews) { overlayView = startView; + } else { + overlayView = TransitionUtils.copyViewImage(sceneRoot, startView, + (View) startView.getParent()); } } } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index b7099b642e98a38c28b2c292e84033e413afcfe5..13de172c811c9efe9908e3708d649f82df0feba8 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -119,6 +119,14 @@ public class DisplayMetrics { */ public static final int DENSITY_420 = 420; + /** + * Intermediate density for screens that sit somewhere between + * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi). + * This is not a density that applications should target, instead relying + * on the system to scale their {@link #DENSITY_XXHIGH} assets for them. + */ + public static final int DENSITY_440 = 440; + /** * Standard quantized DPI for extra-extra-high-density screens. */ diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index 8af4b7150a31ebb48723ea0a8da8fde396eb025b..410cdc6a9bf17e5542d0cc87d56a146fa05a980b 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -38,12 +38,10 @@ public class FeatureFlagUtils { static { DEFAULT_FLAGS = new HashMap<>(); DEFAULT_FLAGS.put("device_info_v2", "true"); - DEFAULT_FLAGS.put("settings_app_info_v2", "true"); DEFAULT_FLAGS.put("settings_connected_device_v2", "true"); DEFAULT_FLAGS.put("settings_battery_v2", "true"); DEFAULT_FLAGS.put("settings_battery_display_app_list", "false"); DEFAULT_FLAGS.put("settings_zone_picker_v2", "true"); - DEFAULT_FLAGS.put("settings_suggestion_ui_v2", "false"); DEFAULT_FLAGS.put("settings_about_phone_v2", "false"); DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false"); } diff --git a/core/java/android/util/StatsManager.java b/core/java/android/util/StatsManager.java index 687aa8375e016d9530a636c551013ac279fae891..51fb18a95c4cbbeede243b2b6d54a6bf77e7153f 100644 --- a/core/java/android/util/StatsManager.java +++ b/core/java/android/util/StatsManager.java @@ -60,9 +60,19 @@ public class StatsManager { */ @RequiresPermission(Manifest.permission.DUMP) public boolean addConfiguration(String configKey, byte[] config, String pkg, String cls) { - // To prevent breakages of dependencies on old API. - - return false; + synchronized (this) { + try { + IStatsManager service = getIStatsManagerLocked(); + if (service == null) { + Slog.d(TAG, "Failed to find statsd when adding configuration"); + return false; + } + return service.addConfiguration(Long.parseLong(configKey), config, pkg, cls); + } catch (RemoteException e) { + Slog.d(TAG, "Failed to connect to statsd when adding configuration"); + return false; + } + } } /** @@ -99,7 +109,19 @@ public class StatsManager { @RequiresPermission(Manifest.permission.DUMP) public boolean removeConfiguration(String configKey) { // To prevent breakages of old dependencies. - return false; + synchronized (this) { + try { + IStatsManager service = getIStatsManagerLocked(); + if (service == null) { + Slog.d(TAG, "Failed to find statsd when removing configuration"); + return false; + } + return service.removeConfiguration(Long.parseLong(configKey)); + } catch (RemoteException e) { + Slog.d(TAG, "Failed to connect to statsd when removing configuration"); + return false; + } + } } /** @@ -132,7 +154,19 @@ public class StatsManager { public byte[] getData(String configKey) { // TODO: remove this and all other methods with String-based config keys. // To prevent build breakages of dependencies. - return null; + synchronized (this) { + try { + IStatsManager service = getIStatsManagerLocked(); + if (service == null) { + Slog.d(TAG, "Failed to find statsd when getting data"); + return null; + } + return service.getData(Long.parseLong(configKey)); + } catch (RemoteException e) { + Slog.d(TAG, "Failed to connecto statsd when getting data"); + return null; + } + } } /** diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java index a4c590f1b459f9f7005795190743e727320aec68..9436b296e9e24a3f1a3f83774c913f16045bd6b4 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java @@ -438,8 +438,8 @@ public class ApkSignatureSchemeV3Verifier { List flagsList = new ArrayList<>(); // Proof-of-rotation struct: - // is basically a singly linked list of nodes, called levels here, each of which have the - // following structure: + // A uint32 version code followed by basically a singly linked list of nodes, called levels + // here, each of which have the following structure: // * length-prefix for the entire level // - length-prefixed signed data (if previous level exists) // * length-prefixed X509 Certificate @@ -450,9 +450,13 @@ public class ApkSignatureSchemeV3Verifier { // - length-prefixed signature over the signed data in this level. The signature here // is verified using the certificate from the previous level. // The linking is provided by the certificate of each level signing the one of the next. - while (porBuf.hasRemaining()) { - levelCount++; - try { + + try { + + // get the version code, but don't do anything with it: creator knew about all our flags + porBuf.getInt(); + while (porBuf.hasRemaining()) { + levelCount++; ByteBuffer level = getLengthPrefixedSlice(porBuf); ByteBuffer signedData = getLengthPrefixedSlice(level); int flags = level.getInt(); @@ -491,17 +495,17 @@ public class ApkSignatureSchemeV3Verifier { lastSigAlgorithm = sigAlgorithm; certs.add(lastCert); flagsList.add(flags); - } catch (IOException | BufferUnderflowException e) { - throw new IOException("Failed to parse Proof-of-rotation record", e); - } catch (NoSuchAlgorithmException | InvalidKeyException - | InvalidAlgorithmParameterException | SignatureException e) { - throw new SecurityException( - "Failed to verify signature over signed data for certificate #" - + levelCount + " when verifying Proof-of-rotation record", e); - } catch (CertificateException e) { - throw new SecurityException("Failed to decode certificate #" + levelCount - + " when verifying Proof-of-rotation record", e); } + } catch (IOException | BufferUnderflowException e) { + throw new IOException("Failed to parse Proof-of-rotation record", e); + } catch (NoSuchAlgorithmException | InvalidKeyException + | InvalidAlgorithmParameterException | SignatureException e) { + throw new SecurityException( + "Failed to verify signature over signed data for certificate #" + + levelCount + " when verifying Proof-of-rotation record", e); + } catch (CertificateException e) { + throw new SecurityException("Failed to decode certificate #" + levelCount + + " when verifying Proof-of-rotation record", e); } return new VerifiedProofOfRotation(certs, flagsList); } diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java index 4c6e511ede46f938e96b3b55910fff0960f6fcd4..a3eeb275064a0c9fb87f976288a41ab23eca2620 100644 --- a/core/java/android/util/apk/ApkVerityBuilder.java +++ b/core/java/android/util/apk/ApkVerityBuilder.java @@ -106,18 +106,22 @@ abstract class ApkVerityBuilder { calculateFsveritySignatureInternal(apk, signatureInfo, null, null, header, extensions); MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM); - md.update(DEFAULT_SALT); - md.update(verityBlock); + md.update(header); + md.update(extensions); md.update(apkDigest); return md.digest(); } + /** + * Internal method to generate various parts of FSVerity constructs, including the header, + * extensions, Merkle tree, and the tree's root hash. The output buffer is flipped to the + * generated data size and is readey for consuming. + */ private static void calculateFsveritySignatureInternal( RandomAccessFile apk, SignatureInfo signatureInfo, ByteBuffer treeOutput, ByteBuffer rootHashOutput, ByteBuffer headerOutput, ByteBuffer extensionsOutput) throws IOException, NoSuchAlgorithmException, DigestException { assertSigningBlockAlignedAndHasFullPages(signatureInfo); - long signingBlockSize = signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset; long dataSize = apk.length() - signingBlockSize - ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE; @@ -128,6 +132,7 @@ abstract class ApkVerityBuilder { levelOffset, treeOutput); if (rootHashOutput != null) { rootHashOutput.put(apkRootHash); + rootHashOutput.flip(); } } @@ -333,9 +338,9 @@ abstract class ApkVerityBuilder { buffer.put((byte) 0); // auth block offset, disabled here buffer.put((byte) 2); // extension count buffer.put(salt); // salt (8 bytes) - // skip(buffer, 22); // reserved + skip(buffer, 22); // reserved - buffer.rewind(); + buffer.flip(); return buffer; } @@ -396,12 +401,10 @@ abstract class ApkVerityBuilder { buffer.put((byte) ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE); // length skip(buffer, 7); // reserved buffer.putInt(Math.toIntExact(signingBlockOffset)); // databytes - - // There are extra kPadding bytes of 0s here, included in the total size field of the - // extension header. The output ByteBuffer is assumed to be initialized to 0. + skip(buffer, kPadding); // padding } - buffer.rewind(); + buffer.flip(); return buffer; } diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index 3fd469630db0c266e01ef39e089aee2be5798306..8cb46b704c18cf41759f52d494a8979de4422cc6 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -23,6 +23,10 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -396,6 +400,33 @@ public final class PointerIcon implements Parcelable { return true; } + /** + * Get the Bitmap from the Drawable. + * + * If the Bitmap needed to be scaled up to account for density, BitmapDrawable + * handles this at draw time. But this class doesn't actually draw the Bitmap; + * it is just a holder for native code to access its SkBitmap. So this needs to + * get a version that is scaled to account for density. + */ + private Bitmap getBitmapFromDrawable(BitmapDrawable bitmapDrawable) { + Bitmap bitmap = bitmapDrawable.getBitmap(); + final int scaledWidth = bitmapDrawable.getIntrinsicWidth(); + final int scaledHeight = bitmapDrawable.getIntrinsicHeight(); + if (scaledWidth == bitmap.getWidth() && scaledHeight == bitmap.getHeight()) { + return bitmap; + } + + Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + RectF dst = new RectF(0, 0, scaledWidth, scaledHeight); + + Bitmap scaled = Bitmap.createBitmap(scaledWidth, scaledHeight, bitmap.getConfig()); + Canvas canvas = new Canvas(scaled); + Paint paint = new Paint(); + paint.setFilterBitmap(true); + canvas.drawBitmap(bitmap, src, dst, paint); + return scaled; + } + private void loadResource(Context context, Resources resources, @XmlRes int resourceId) { final XmlResourceParser parser = resources.getXml(resourceId); final int bitmapRes; @@ -452,7 +483,8 @@ public final class PointerIcon implements Parcelable { + "is different. All frames should have the exact same size and " + "share the same hotspot."); } - mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap(); + BitmapDrawable bitmapDrawableFrame = (BitmapDrawable) drawableFrame; + mBitmapFrames[i - 1] = getBitmapFromDrawable(bitmapDrawableFrame); } } } @@ -461,7 +493,8 @@ public final class PointerIcon implements Parcelable { + "refer to a bitmap drawable."); } - final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable); validateHotSpot(bitmap, hotSpotX, hotSpotY); // Set the properties now that we have successfully loaded the icon. mBitmap = bitmap; diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 5070151815f50281a7fbfba64864277804c7def3..ce7e8f3b55b55308f68fbc1e4141e0128d1be33e 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -353,9 +353,24 @@ public class RenderNode { return nHasShadow(mNativeRenderNode); } - /** setShadowColor */ - public boolean setShadowColor(int color) { - return nSetShadowColor(mNativeRenderNode, color); + /** setSpotShadowColor */ + public boolean setSpotShadowColor(int color) { + return nSetSpotShadowColor(mNativeRenderNode, color); + } + + /** setAmbientShadowColor */ + public boolean setAmbientShadowColor(int color) { + return nSetAmbientShadowColor(mNativeRenderNode, color); + } + + /** getSpotShadowColor */ + public int getSpotShadowColor() { + return nGetSpotShadowColor(mNativeRenderNode); + } + + /** getAmbientShadowColor */ + public int getAmbientShadowColor() { + return nGetAmbientShadowColor(mNativeRenderNode); } /** @@ -915,7 +930,13 @@ public class RenderNode { @CriticalNative private static native boolean nHasShadow(long renderNode); @CriticalNative - private static native boolean nSetShadowColor(long renderNode, int color); + private static native boolean nSetSpotShadowColor(long renderNode, int color); + @CriticalNative + private static native boolean nSetAmbientShadowColor(long renderNode, int color); + @CriticalNative + private static native int nGetSpotShadowColor(long renderNode); + @CriticalNative + private static native int nGetAmbientShadowColor(long renderNode); @CriticalNative private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); @CriticalNative diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 5150c1fec8a3126c15fb9f072a7fd6f55c16a4d3..79fc13424bee0e884be4ed8655c703767d2d6678 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -17,7 +17,6 @@ package android.view; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; - import static java.lang.Math.max; import android.animation.AnimatorInflater; @@ -75,6 +74,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; +import android.text.InputType; import android.text.TextUtils; import android.util.AttributeSet; import android.util.FloatProperty; @@ -726,6 +726,8 @@ import java.util.function.Predicate; * @attr ref android.R.styleable#View_nextFocusRight * @attr ref android.R.styleable#View_nextFocusUp * @attr ref android.R.styleable#View_onClick + * @attr ref android.R.styleable#View_outlineSpotShadowColor + * @attr ref android.R.styleable#View_outlineAmbientShadowColor * @attr ref android.R.styleable#View_padding * @attr ref android.R.styleable#View_paddingHorizontal * @attr ref android.R.styleable#View_paddingVertical @@ -3975,6 +3977,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Current clip bounds. to which all drawing of this view are constrained. */ + @ViewDebug.ExportedProperty(category = "drawing") Rect mClipBounds = null; private boolean mLastIsOpaque; @@ -5446,6 +5449,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setAccessibilityPaneTitle(a.getString(attr)); } break; + case R.styleable.View_outlineSpotShadowColor: + setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK)); + break; + case R.styleable.View_outlineAmbientShadowColor: + setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK)); + break; } } @@ -7932,12 +7941,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * optimal implementation providing this data. */ public void onProvideVirtualStructure(ViewStructure structure) { - AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); + onProvideVirtualStructureCompat(structure, false); + } + + /** + * Fallback implementation to populate a ViewStructure from accessibility state. + * + * @param structure The structure to populate. + * @param forAutofill Whether the structure is needed for autofill. + */ + private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) { + final AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); if (provider != null) { - AccessibilityNodeInfo info = createAccessibilityNodeInfo(); + final AccessibilityNodeInfo info = createAccessibilityNodeInfo(); structure.setChildCount(1); - ViewStructure root = structure.newChild(0); - populateVirtualStructure(root, provider, info); + final ViewStructure root = structure.newChild(0); + populateVirtualStructure(root, provider, info, forAutofill); info.recycle(); } } @@ -7966,6 +7985,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, *

  • Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)} * and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)} * when the focused virtual child changed. + *
  • Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query + * whether a given virtual view is visible to the user in order to support triggering + * save when all views of interest go away. *
  • Call * {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)} * when the value of a virtual child changed. @@ -8001,6 +8023,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS */ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { + if (mContext.isAutofillCompatibilityEnabled()) { + onProvideVirtualStructureCompat(structure, true); + } } /** @@ -8078,6 +8103,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#Theme_autofilledHighlight */ public void autofill(@NonNull @SuppressWarnings("unused") SparseArray values) { + if (!mContext.isAutofillCompatibilityEnabled()) { + return; + } + final AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); + if (provider == null) { + return; + } + final int valueCount = values.size(); + for (int i = 0; i < valueCount; i++) { + final AutofillValue value = values.valueAt(i); + if (value.isText()) { + final int virtualId = values.keyAt(i); + final CharSequence text = value.getTextValue(); + final Bundle arguments = new Bundle(); + arguments.putCharSequence( + AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text); + provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments); + } + } } /** @@ -8331,7 +8375,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void populateVirtualStructure(ViewStructure structure, - AccessibilityNodeProvider provider, AccessibilityNodeInfo info) { + AccessibilityNodeProvider provider, AccessibilityNodeInfo info, + boolean forAutofill) { structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), null, null, null); Rect rect = structure.getTempRect(); @@ -8366,21 +8411,43 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (info.isContextClickable()) { structure.setContextClickable(true); } + if (forAutofill) { + structure.setAutofillId(new AutofillId(getAutofillId(), + AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()))); + } CharSequence cname = info.getClassName(); structure.setClassName(cname != null ? cname.toString() : null); structure.setContentDescription(info.getContentDescription()); if ((info.getText() != null || info.getError() != null)) { structure.setText(info.getText(), info.getTextSelectionStart(), info.getTextSelectionEnd()); + if (forAutofill) { + if (info.isEditable()) { + structure.setDataIsSensitive(true); + structure.setAutofillType(AUTOFILL_TYPE_TEXT); + final AutofillValue autofillValue = AutofillValue.forText(structure.getText()); + structure.setAutofillValue(autofillValue); + if (info.isPassword()) { + structure.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + } + } else { + structure.setDataIsSensitive(false); + } + } } final int NCHILDREN = info.getChildCount(); if (NCHILDREN > 0) { structure.setChildCount(NCHILDREN); for (int i=0; i + * By default the shadow color is black. Generally, this color will be opaque so the intensity + * of the shadow is consistent between different views with different colors. + *

    + * The opacity of the final spot shadow is a function of the shadow caster height, the + * alpha channel of the outlineSpotShadowColor (typically opaque), and the + * {@link android.R.attr#spotShadowAlpha} theme attribute. + * + * @attr ref android.R.styleable#View_outlineSpotShadowColor + * @param color The color this View will cast for its elevation spot shadow. + */ + public void setOutlineSpotShadowColor(@ColorInt int color) { + if (mRenderNode.setSpotShadowColor(color)) { + invalidateViewProperty(true, true); + } + } + + /** + * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing + * was set + */ + public @ColorInt int getOutlineSpotShadowColor() { + return mRenderNode.getSpotShadowColor(); + } + + /** + * Sets the color of the ambient shadow that is drawn when the view has a positive Z or + * elevation value. + *

    + * By default the shadow color is black. Generally, this color will be opaque so the intensity + * of the shadow is consistent between different views with different colors. + *

    + * The opacity of the final ambient shadow is a function of the shadow caster height, the + * alpha channel of the outlineAmbientShadowColor (typically opaque), and the + * {@link android.R.attr#ambientShadowAlpha} theme attribute. + * + * @attr ref android.R.styleable#View_outlineAmbientShadowColor + * @param color The color this View will cast for its elevation shadow. */ - public void setShadowColor(@ColorInt int color) { - if (mRenderNode.setShadowColor(color)) { + public void setOutlineAmbientShadowColor(@ColorInt int color) { + if (mRenderNode.setAmbientShadowColor(color)) { invalidateViewProperty(true, true); } } + /** + * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if + * nothing was set + */ + public @ColorInt int getOutlineAmbientShadowColor() { + return mRenderNode.getAmbientShadowColor(); + } + /** @hide */ public void setRevealClip(boolean shouldClip, float x, float y, float radius) { @@ -23634,9 +23766,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Point shadowTouchPoint = new Point(); shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); - if ((shadowSize.x <= 0) || (shadowSize.y <= 0) + if ((shadowSize.x < 0) || (shadowSize.y < 0) || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { - throw new IllegalStateException("Drag shadow dimensions must be positive"); + throw new IllegalStateException("Drag shadow dimensions must not be negative"); + } + + // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder + // does not accept zero size surface. + if (shadowSize.x == 0 || shadowSize.y == 0) { + shadowSize.x = 1; + shadowSize.y = 1; } if (ViewDebug.DEBUG_DRAG) { @@ -26979,6 +27118,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, stream.addProperty("drawing:scaleY", getScaleY()); stream.addProperty("drawing:pivotX", getPivotX()); stream.addProperty("drawing:pivotY", getPivotY()); + stream.addProperty("drawing:clipBounds", + mClipBounds == null ? null : mClipBounds.toString()); stream.addProperty("drawing:opaque", isOpaque()); stream.addProperty("drawing:alpha", getAlpha()); stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); @@ -26990,6 +27131,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); + stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor()); + stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor()); // focus stream.addProperty("focus:hasFocus", hasFocus()); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index a8bdb85660d05240b7d681fcfc714406826334f4..273f097edc633e1d3a7b8875da89f81a719b0da8 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3555,13 +3555,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public void dispatchProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) { super.dispatchProvideAutofillStructure(structure, flags); + if (structure.getChildCount() != 0) { return; } if (!isLaidOut()) { - Log.v(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring " - + mChildrenCount + " children of " + getAutofillId()); + if (Helper.sVerbose) { + Log.v(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring " + + mChildrenCount + " children of " + getAutofillId()); + } return; } @@ -5120,6 +5123,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // manually assembling the hierarchy, update the ancestor default-focus chain. setDefaultFocus(child); } + + touchAccessibilityNodeProviderIfNeeded(child); + } + + /** + * We may need to touch the provider to bring up the a11y layer. In a11y mode + * clients inspect the screen or the user touches it which triggers bringing up + * of the a11y infrastructure while in autofill mode we want the infra up and + * running from the beginning since we watch for a11y events to drive autofill. + */ + private void touchAccessibilityNodeProviderIfNeeded(View child) { + if (mContext.isAutofillCompatibilityEnabled()) { + child.getAccessibilityNodeProvider(); + } } private void addInArray(View child, int index) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 0af12544294c4de1602db9c35e4e70f34ef05df2..810864eaac3ccf273b85f4ae2f2c0bec0e7fb739 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -71,6 +71,7 @@ import android.os.Trace; import android.util.AndroidRuntimeException; import android.util.DisplayMetrics; import android.util.Log; +import android.util.LongArray; import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; @@ -114,6 +115,8 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; import java.util.concurrent.CountDownLatch; /** @@ -1995,6 +1998,7 @@ public final class ViewRootImpl implements ViewParent, final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets); final boolean surfaceSizeChanged = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0; + surfaceChanged |= surfaceSizeChanged; final boolean alwaysConsumeNavBarChanged = mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar; if (contentInsetsChanged) { @@ -2568,6 +2572,10 @@ public final class ViewRootImpl implements ViewParent, ~WindowManager.LayoutParams .SOFT_INPUT_IS_FORWARD_NAVIGATION; mHasHadWindowFocus = true; + + // Refocusing a window that has a focused view should fire a + // focus event for the view since the global focused view changed. + fireAccessibilityFocusEventIfHasFocusedNode(); } else { if (mPointerCapture) { handlePointerCaptureChanged(false); @@ -2577,6 +2585,86 @@ public final class ViewRootImpl implements ViewParent, mFirstInputStage.onWindowFocusChanged(hasWindowFocus); } + private void fireAccessibilityFocusEventIfHasFocusedNode() { + if (!AccessibilityManager.getInstance(mContext).isEnabled()) { + return; + } + final View focusedView = mView.findFocus(); + if (focusedView == null) { + return; + } + final AccessibilityNodeProvider provider = focusedView.getAccessibilityNodeProvider(); + if (provider == null) { + focusedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } else { + final AccessibilityNodeInfo focusedNode = findFocusedVirtualNode(provider); + if (focusedNode != null) { + final int virtualId = AccessibilityNodeInfo.getVirtualDescendantId( + focusedNode.getSourceNodeId()); + // This is a best effort since clearing and setting the focus via the + // provider APIs could have side effects. We don't have a provider API + // similar to that on View to ask a given event to be fired. + final AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_VIEW_FOCUSED); + event.setSource(focusedView, virtualId); + event.setPackageName(focusedNode.getPackageName()); + event.setChecked(focusedNode.isChecked()); + event.setContentDescription(focusedNode.getContentDescription()); + event.setPassword(focusedNode.isPassword()); + event.getText().add(focusedNode.getText()); + event.setEnabled(focusedNode.isEnabled()); + focusedView.getParent().requestSendAccessibilityEvent(focusedView, event); + focusedNode.recycle(); + } + } + } + + private AccessibilityNodeInfo findFocusedVirtualNode(AccessibilityNodeProvider provider) { + AccessibilityNodeInfo focusedNode = provider.findFocus( + AccessibilityNodeInfo.FOCUS_INPUT); + if (focusedNode != null) { + return focusedNode; + } + + if (!mContext.isAutofillCompatibilityEnabled()) { + return null; + } + + // Unfortunately some provider implementations don't properly + // implement AccessibilityNodeProvider#findFocus + AccessibilityNodeInfo current = provider.createAccessibilityNodeInfo( + AccessibilityNodeProvider.HOST_VIEW_ID); + if (current.isFocused()) { + return current; + } + + final Queue fringe = new LinkedList<>(); + fringe.offer(current); + + while (!fringe.isEmpty()) { + current = fringe.poll(); + final LongArray childNodeIds = current.getChildNodeIds(); + if (childNodeIds== null || childNodeIds.size() <= 0) { + continue; + } + final int childCount = childNodeIds.size(); + for (int i = 0; i < childCount; i++) { + final int virtualId = AccessibilityNodeInfo.getVirtualDescendantId( + childNodeIds.get(i)); + final AccessibilityNodeInfo child = provider.createAccessibilityNodeInfo(virtualId); + if (child != null) { + if (child.isFocused()) { + return child; + } + fringe.offer(child); + } + } + current.recycle(); + } + + return null; + } + private void handleOutOfResourcesException(Surface.OutOfResourcesException e) { Log.e(mTag, "OutOfResourcesException initializing HW surface", e); try { diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index b4499d1acac3d208b9f6f478afe87d4a65254a8a..191c27073782ed5d085095fcc9ab8169f494b271 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -16,10 +16,9 @@ package android.view.accessibility; -import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_ENABLE_ACCESSIBILITY_VOLUME; - import android.Manifest; import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; @@ -44,7 +43,7 @@ import android.util.Log; import android.util.SparseArray; import android.view.IWindow; import android.view.View; - +import android.view.accessibility.AccessibilityEvent.EventType; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IntPair; @@ -52,6 +51,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_ENABLE_ACCESSIBILITY_VOLUME; + /** * System level service that serves as an event dispatch for {@link AccessibilityEvent}s, * and provides facilities for querying the accessibility state of the system. @@ -132,6 +133,8 @@ public final class AccessibilityManager { boolean mIsHighTextContrastEnabled; + AccessibilityPolicy mAccessibilityPolicy; + private final ArrayMap mAccessibilityStateChangeListeners = new ArrayMap<>(); @@ -215,6 +218,60 @@ public final class AccessibilityManager { void onHighTextContrastStateChanged(boolean enabled); } + /** + * Policy to inject behavior into the accessibility manager. + * + * @hide + */ + public interface AccessibilityPolicy { + /** + * Checks whether accessibility is enabled. + * + * @param accessibilityEnabled Whether the accessibility layer is enabled. + * @return whether accessibility is enabled. + */ + boolean isEnabled(boolean accessibilityEnabled); + + /** + * Notifies the policy for an accessibility event. + * + * @param event The event. + * @param accessibilityEnabled Whether the accessibility layer is enabled. + * @param relevantEventTypes The events relevant events. + * @return The event to dispatch or null. + */ + @Nullable AccessibilityEvent onAccessibilityEvent(@NonNull AccessibilityEvent event, + boolean accessibilityEnabled, @EventType int relevantEventTypes); + + /** + * Gets the list of relevant events. + * + * @param relevantEventTypes The relevant events. + * @return The relevant events to report. + */ + @EventType int getRelevantEventTypes(@EventType int relevantEventTypes); + + /** + * Gets the list of installed services to report. + * + * @param installedService The installed services. + * @return The services to report. + */ + @NonNull List getInstalledAccessibilityServiceList( + @Nullable List installedService); + + /** + * Gets the list of enabled accessibility services. + * + * @param feedbackTypeFlags The feedback type to query for. + * @param enabledService The enabled services. + * @return The services to report. + */ + @Nullable List getEnabledAccessibilityServiceList( + @FeedbackType int feedbackTypeFlags, + @Nullable List enabledService); + } + private final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { @Override @@ -273,7 +330,7 @@ public final class AccessibilityManager { == PackageManager.PERMISSION_GRANTED) { userId = UserHandle.USER_CURRENT; } else { - userId = UserHandle.myUserId(); + userId = context.getUserId(); } sInstance = new AccessibilityManager(context, null, userId); } @@ -341,11 +398,8 @@ public final class AccessibilityManager { */ public boolean isEnabled() { synchronized (mLock) { - IAccessibilityManager service = getServiceLocked(); - if (service == null) { - return false; - } - return mIsEnabled; + return mIsEnabled || (mAccessibilityPolicy != null + && mAccessibilityPolicy.isEnabled(mIsEnabled)); } } @@ -401,12 +455,23 @@ public final class AccessibilityManager { public void sendAccessibilityEvent(AccessibilityEvent event) { final IAccessibilityManager service; final int userId; + final AccessibilityEvent dispatchedEvent; synchronized (mLock) { service = getServiceLocked(); if (service == null) { return; } - if (!mIsEnabled) { + event.setEventTime(SystemClock.uptimeMillis()); + if (mAccessibilityPolicy != null) { + dispatchedEvent = mAccessibilityPolicy.onAccessibilityEvent(event, + mIsEnabled, mRelevantEventTypes); + if (dispatchedEvent == null) { + return; + } + } else { + dispatchedEvent = event; + } + if (!isEnabled()) { Looper myLooper = Looper.myLooper(); if (myLooper == Looper.getMainLooper()) { throw new IllegalStateException( @@ -420,9 +485,9 @@ public final class AccessibilityManager { return; } } - if ((event.getEventType() & mRelevantEventTypes) == 0) { + if ((dispatchedEvent.getEventType() & mRelevantEventTypes) == 0) { if (DEBUG) { - Log.i(LOG_TAG, "Not dispatching irrelevant event: " + event + Log.i(LOG_TAG, "Not dispatching irrelevant event: " + dispatchedEvent + " that is not among " + AccessibilityEvent.eventTypeToString(mRelevantEventTypes)); } @@ -431,23 +496,25 @@ public final class AccessibilityManager { userId = mUserId; } try { - event.setEventTime(SystemClock.uptimeMillis()); // it is possible that this manager is in the same process as the service but // client using it is called through Binder from another process. Example: MMS // app adds a SMS notification and the NotificationManagerService calls this method long identityToken = Binder.clearCallingIdentity(); try { - service.sendAccessibilityEvent(event, userId); + service.sendAccessibilityEvent(dispatchedEvent, userId); } finally { Binder.restoreCallingIdentity(identityToken); } if (DEBUG) { - Log.i(LOG_TAG, event + " sent"); + Log.i(LOG_TAG, dispatchedEvent + " sent"); } } catch (RemoteException re) { - Log.e(LOG_TAG, "Error during sending " + event + " ", re); + Log.e(LOG_TAG, "Error during sending " + dispatchedEvent + " ", re); } finally { - event.recycle(); + if (event != dispatchedEvent) { + event.recycle(); + } + dispatchedEvent.recycle(); } } @@ -462,7 +529,7 @@ public final class AccessibilityManager { if (service == null) { return; } - if (!mIsEnabled) { + if (!isEnabled()) { Looper myLooper = Looper.myLooper(); if (myLooper == Looper.getMainLooper()) { throw new IllegalStateException( @@ -532,6 +599,9 @@ public final class AccessibilityManager { } catch (RemoteException re) { Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re); } + if (mAccessibilityPolicy != null) { + services = mAccessibilityPolicy.getInstalledAccessibilityServiceList(services); + } if (services != null) { return Collections.unmodifiableList(services); } else { @@ -574,6 +644,10 @@ public final class AccessibilityManager { } catch (RemoteException re) { Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re); } + if (mAccessibilityPolicy != null) { + services = mAccessibilityPolicy.getEnabledAccessibilityServiceList( + feedbackTypeFlags, services); + } if (services != null) { return Collections.unmodifiableList(services); } else { @@ -782,6 +856,19 @@ public final class AccessibilityManager { } } + /** + * Sets the {@link AccessibilityPolicy} controlling this manager. + * + * @param policy The policy. + * + * @hide + */ + public void setAccessibilityPolicy(@Nullable AccessibilityPolicy policy) { + synchronized (mLock) { + mAccessibilityPolicy = policy; + } + } + /** * Check if the accessibility volume stream is active. * @@ -834,7 +921,7 @@ public final class AccessibilityManager { final boolean highTextContrastEnabled = (stateFlags & STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED) != 0; - final boolean wasEnabled = mIsEnabled; + final boolean wasEnabled = isEnabled(); final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled; final boolean wasHighTextContrastEnabled = mIsHighTextContrastEnabled; @@ -843,7 +930,7 @@ public final class AccessibilityManager { mIsTouchExplorationEnabled = touchExplorationEnabled; mIsHighTextContrastEnabled = highTextContrastEnabled; - if (wasEnabled != enabled) { + if (wasEnabled != isEnabled()) { notifyAccessibilityStateChanged(); } @@ -1052,16 +1139,15 @@ public final class AccessibilityManager { if (mAccessibilityStateChangeListeners.isEmpty()) { return; } - isEnabled = mIsEnabled; + isEnabled = isEnabled(); listeners = new ArrayMap<>(mAccessibilityStateChangeListeners); } - int numListeners = listeners.size(); + final int numListeners = listeners.size(); for (int i = 0; i < numListeners; i++) { - final AccessibilityStateChangeListener listener = - mAccessibilityStateChangeListeners.keyAt(i); - mAccessibilityStateChangeListeners.valueAt(i) - .post(() -> listener.onAccessibilityStateChanged(isEnabled)); + final AccessibilityStateChangeListener listener = listeners.keyAt(i); + listeners.valueAt(i).post(() -> + listener.onAccessibilityStateChanged(isEnabled)); } } @@ -1079,12 +1165,11 @@ public final class AccessibilityManager { listeners = new ArrayMap<>(mTouchExplorationStateChangeListeners); } - int numListeners = listeners.size(); + final int numListeners = listeners.size(); for (int i = 0; i < numListeners; i++) { - final TouchExplorationStateChangeListener listener = - mTouchExplorationStateChangeListeners.keyAt(i); - mTouchExplorationStateChangeListeners.valueAt(i) - .post(() -> listener.onTouchExplorationStateChanged(isTouchExplorationEnabled)); + final TouchExplorationStateChangeListener listener = listeners.keyAt(i); + listeners.valueAt(i).post(() -> + listener.onTouchExplorationStateChanged(isTouchExplorationEnabled)); } } @@ -1102,12 +1187,11 @@ public final class AccessibilityManager { listeners = new ArrayMap<>(mHighTextContrastStateChangeListeners); } - int numListeners = listeners.size(); + final int numListeners = listeners.size(); for (int i = 0; i < numListeners; i++) { - final HighTextContrastChangeListener listener = - mHighTextContrastStateChangeListeners.keyAt(i); - mHighTextContrastStateChangeListeners.valueAt(i) - .post(() -> listener.onHighTextContrastStateChanged(isHighTextContrastEnabled)); + final HighTextContrastChangeListener listener = listeners.keyAt(i); + listeners.valueAt(i).post(() -> + listener.onHighTextContrastStateChanged(isHighTextContrastEnabled)); } } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 4b24a71c8bfb5760a1c5e5caee75d8b13d295309..63a9990cf83910b227219b4249d3cf95c23ed89a 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -16,10 +16,7 @@ package android.view.autofill; -import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; -import static android.view.autofill.Helper.sDebug; -import static android.view.autofill.Helper.sVerbose; - +import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -28,6 +25,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Rect; import android.metrics.LogMaker; import android.os.Bundle; @@ -41,13 +40,22 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; +import android.view.Choreographer; import android.view.View; - +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; +import android.view.accessibility.AccessibilityWindowInfo; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; +import org.xmlpull.v1.XmlPullParserException; +import sun.misc.Cleaner; +import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -58,8 +66,11 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; +import static android.view.autofill.Helper.sDebug; +import static android.view.autofill.Helper.sVerbose; + // TODO: use java.lang.ref.Cleaner once Android supports Java 9 -import sun.misc.Cleaner; /** * The {@link AutofillManager} provides ways for apps and custom views to integrate with the @@ -178,7 +189,6 @@ public final class AutofillManager { private static final String STATE_TAG = "android:state"; private static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData"; - /** @hide */ public static final int ACTION_START_SESSION = 1; /** @hide */ public static final int ACTION_VIEW_ENTERED = 2; /** @hide */ public static final int ACTION_VIEW_EXITED = 3; @@ -355,6 +365,10 @@ public final class AutofillManager { @GuardedBy("mLock") private boolean mSaveOnFinish; + /** If compatibility mode is enabled - this is a bridge to interact with a11y */ + @GuardedBy("mLock") + private CompatibilityBridge mCompatibilityBridge; + /** @hide */ public interface AutofillClient { /** @@ -364,13 +378,13 @@ public final class AutofillManager { * @param intent The authentication intent. * @param fillInIntent The authentication fill-in intent. */ - void autofillCallbackAuthenticate(int authenticationId, IntentSender intent, + void autofillClientAuthenticate(int authenticationId, IntentSender intent, Intent fillInIntent); /** * Tells the client this manager has state to be reset. */ - void autofillCallbackResetableStateAvailable(); + void autofillClientResetableStateAvailable(); /** * Request showing the autofill UI. @@ -382,7 +396,7 @@ public final class AutofillManager { * @param presenter The presenter that controls the fill UI window. * @return Whether the UI was shown. */ - boolean autofillCallbackRequestShowFillUi(@NonNull View anchor, int width, int height, + boolean autofillClientRequestShowFillUi(@NonNull View anchor, int width, int height, @Nullable Rect virtualBounds, IAutofillWindowPresenter presenter); /** @@ -390,21 +404,28 @@ public final class AutofillManager { * * @return Whether the UI was hidden. */ - boolean autofillCallbackRequestHideFillUi(); + boolean autofillClientRequestHideFillUi(); + + /** + * Gets whether the fill UI is currenlty being shown. + * + * @return Whether the fill UI is currently being shown + */ + boolean autofillClientIsFillUiShowing(); /** * Checks if views are currently attached and visible. * * @return And array with {@code true} iff the view is attached or visible */ - @NonNull boolean[] getViewVisibility(@NonNull int[] viewId); + @NonNull boolean[] autofillClientGetViewVisibility(@NonNull AutofillId[] autofillIds); /** * Checks is the client is currently visible as understood by autofill. * * @return {@code true} if the client is currently visible */ - boolean isVisibleForAutofill(); + boolean autofillClientIsVisibleForAutofill(); /** * Client might disable enter/exit event e.g. when activity is paused. @@ -414,30 +435,51 @@ public final class AutofillManager { /** * Finds views by traversing the hierarchies of the client. * - * @param viewIds The autofill ids of the views to find + * @param autofillIds The autofill ids of the views to find * * @return And array containing the views (empty if no views found). */ - @NonNull View[] findViewsByAutofillIdTraversal(@NonNull int[] viewIds); + @NonNull View[] autofillClientFindViewsByAutofillIdTraversal( + @NonNull AutofillId[] autofillIds); /** * Finds a view by traversing the hierarchies of the client. * - * @param viewId The autofill id of the views to find + * @param autofillId The autofill id of the views to find + * + * @return The view, or {@code null} if not found + */ + @Nullable View autofillClientFindViewByAutofillIdTraversal(@NonNull AutofillId autofillId); + + /** + * Finds a view by a11y id in a given client window. + * + * @param viewId The accessibility id of the views to find + * @param windowId The accessibility window id where to search * * @return The view, or {@code null} if not found */ - @Nullable View findViewByAutofillIdTraversal(int viewId); + @Nullable View autofillClientFindViewByAccessibilityIdTraversal(int viewId, int windowId); /** * Runs the specified action on the UI thread. */ - void runOnUiThread(Runnable action); + void autofillClientRunOnUiThread(Runnable action); /** * Gets the complete component name of this client. */ - ComponentName getComponentName(); + ComponentName autofillClientGetComponentName(); + + /** + * Gets the activity token + */ + @Nullable IBinder autofillClientGetActivityToken(); + + /** + * @return Whether compatibility mode is enabled. + */ + boolean autofillIsCompatibilityModeEnabled(); } /** @@ -448,6 +490,19 @@ public final class AutofillManager { mService = service; } + /** + * @hide + */ + public void enableCompatibilityMode() { + synchronized (mLock) { + // The accessibility manager is a singleton so we may need to plug + // different bridge based on which activity is currently focused + // in the current process. Since compat would be rarely used, just + // create and register a new instance every time. + mCompatibilityBridge = new CompatibilityBridge(); + } + } + /** * Restore state after activity lifecycle * @@ -477,7 +532,8 @@ public final class AutofillManager { if (client != null) { try { final boolean sessionWasRestored = mService.restoreSession(mSessionId, - mContext.getActivityToken(), mServiceClient.asBinder()); + client.autofillClientGetActivityToken(), + mServiceClient.asBinder()); if (!sessionWasRestored) { Log.w(TAG, "Session " + mSessionId + " could not be restored"); @@ -488,7 +544,7 @@ public final class AutofillManager { Log.d(TAG, "session " + mSessionId + " was restored"); } - client.autofillCallbackResetableStateAvailable(); + client.autofillClientResetableStateAvailable(); } } catch (RemoteException e) { Log.e(TAG, "Could not figure out if there was an autofill session", e); @@ -501,22 +557,29 @@ public final class AutofillManager { /** * Called once the client becomes visible. * - * @see AutofillClient#isVisibleForAutofill() + * @see AutofillClient#autofillClientIsVisibleForAutofill() * * {@hide} */ public void onVisibleForAutofill() { - synchronized (mLock) { - if (mEnabled && isActiveLocked() && mTrackedViews != null) { - mTrackedViews.onVisibleForAutofillLocked(); + // This gets called when the client just got visible at which point the visibility + // of the tracked views may not have been computed (due to a pending layout, etc). + // While generally we have no way to know when the UI has settled. We will evaluate + // the tracked views state at the end of next frame to guarantee that everything + // that may need to be laid out is laid out. + Choreographer.getInstance().postCallback(Choreographer.CALLBACK_COMMIT, () -> { + synchronized (mLock) { + if (mEnabled && isActiveLocked() && mTrackedViews != null) { + mTrackedViews.onVisibleForAutofillChangedLocked(); + } } - } + }, null); } /** * Called once the client becomes invisible. * - * @see AutofillClient#isVisibleForAutofill() + * @see AutofillClient#autofillClientIsVisibleForAutofill() * * {@hide} */ @@ -550,6 +613,15 @@ public final class AutofillManager { } } + /** + * @hide + */ + public boolean isCompatibilityModeEnabled() { + synchronized (mLock) { + return mCompatibilityBridge != null; + } + } + /** * Checks whether autofill is enabled for the current user. * @@ -653,7 +725,7 @@ public final class AutofillManager { private boolean isClientVisibleForAutofillLocked() { final AutofillClient client = getClient(); - return client != null && client.isVisibleForAutofill(); + return client != null && client.autofillClientIsVisibleForAutofill(); } private boolean isClientDisablingEnterExitEvent() { @@ -1098,6 +1170,30 @@ public final class AutofillManager { } } + /** + * Gets the id of the {@link UserData} used for + * field classification. + * + *

    This method is useful when the service must check the status of the {@link UserData} in + * the device without fetching the whole object. + * + *

    Note: This method should only be called by an app providing an autofill service, + * and it's ignored if the caller currently doesn't have an enabled autofill service for + * the user. + * + * @return id of the {@link UserData} previously set by {@link #setUserData(UserData)} + * or {@code null} if it was reset or if the caller currently does not have an enabled autofill + * service for the user. + */ + @Nullable public String getUserDataId() { + try { + return mService.getUserDataId(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return null; + } + } + /** * Gets the user data used for * field classification. @@ -1119,7 +1215,7 @@ public final class AutofillManager { } /** - * Sets the user data used for + * Sets the {@link UserData} used for * field classification * *

    Note: This method should only be called by an app providing an autofill service, @@ -1298,13 +1394,13 @@ public final class AutofillManager { final AutofillClient client = getClient(); if (client == null) return; // NOTE: getClient() already logd it.. - mSessionId = mService.startSession(mContext.getActivityToken(), + mSessionId = mService.startSession(client.autofillClientGetActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), - mCallback != null, flags, client.getComponentName()); + mCallback != null, flags, client.autofillClientGetComponentName()); if (mSessionId != NO_SESSION) { mState = STATE_ACTIVE; } - client.autofillCallbackResetableStateAvailable(); + client.autofillClientResetableStateAvailable(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1359,14 +1455,16 @@ public final class AutofillManager { final AutofillClient client = getClient(); if (client == null) return; // NOTE: getClient() already logd it.. - final int newId = mService.updateOrRestartSession(mContext.getActivityToken(), + final int newId = mService.updateOrRestartSession( + client.autofillClientGetActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), - mCallback != null, flags, client.getComponentName(), mSessionId, action); + mCallback != null, flags, client.autofillClientGetComponentName(), + mSessionId, action); if (newId != mSessionId) { if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId); mSessionId = newId; mState = (mSessionId == NO_SESSION) ? STATE_UNKNOWN : STATE_ACTIVE; - client.autofillCallbackResetableStateAvailable(); + client.autofillClientResetableStateAvailable(); } } else { mService.updateSession(mSessionId, id, bounds, value, action, flags, @@ -1465,7 +1563,7 @@ public final class AutofillManager { AutofillClient client = getClient(); if (client != null) { - if (client.autofillCallbackRequestShowFillUi(anchor, width, height, + if (client.autofillClientRequestShowFillUi(anchor, width, height, anchorBounds, presenter) && mCallback != null) { callback = mCallback; } @@ -1492,7 +1590,7 @@ public final class AutofillManager { // clear mOnInvisibleCalled and we will see if receive onInvisibleForAutofill() // before onAuthenticationResult() mOnInvisibleCalled = false; - client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent); + client.autofillClientAuthenticate(authenticationId, intent, fillInIntent); } } } @@ -1563,7 +1661,8 @@ public final class AutofillManager { final int itemCount = ids.size(); int numApplied = 0; ArrayMap> virtualValues = null; - final View[] views = client.findViewsByAutofillIdTraversal(getViewIds(ids)); + final View[] views = client.autofillClientFindViewsByAutofillIdTraversal( + Helper.toArray(ids)); for (int i = 0; i < itemCount; i++) { final AutofillId id = ids.get(i); @@ -1734,7 +1833,7 @@ public final class AutofillManager { // service being uninstalled and the UI being dismissed. AutofillClient client = getClient(); if (client != null) { - if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { + if (client.autofillClientRequestHideFillUi() && mCallback != null) { callback = mCallback; } } @@ -1782,35 +1881,6 @@ public final class AutofillManager { } } - /** - * Get an array of viewIds from a List of {@link AutofillId}. - * - * @param autofillIds The autofill ids to convert - * - * @return The array of viewIds. - */ - // TODO: move to Helper as static method - @NonNull private int[] getViewIds(@NonNull AutofillId[] autofillIds) { - final int numIds = autofillIds.length; - final int[] viewIds = new int[numIds]; - for (int i = 0; i < numIds; i++) { - viewIds[i] = autofillIds[i].getViewId(); - } - - return viewIds; - } - - // TODO: move to Helper as static method - @NonNull private int[] getViewIds(@NonNull List autofillIds) { - final int numIds = autofillIds.size(); - final int[] viewIds = new int[numIds]; - for (int i = 0; i < numIds; i++) { - viewIds[i] = autofillIds.get(i).getViewId(); - } - - return viewIds; - } - /** * Find a single view by its id. * @@ -1820,12 +1890,10 @@ public final class AutofillManager { */ private View findView(@NonNull AutofillId autofillId) { final AutofillClient client = getClient(); - - if (client == null) { - return null; + if (client != null) { + return client.autofillClientFindViewByAutofillIdTraversal(autofillId); } - - return client.findViewByAutofillIdTraversal(autofillId.getViewId()); + return null; } /** @hide */ @@ -1871,6 +1939,7 @@ public final class AutofillManager { pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds); pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId); pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish); + pw.print(pfx); pw.print("compat mode enabled: "); pw.println(isCompatibilityModeEnabled()); pw.print(pfx); pw.print("debug: "); pw.print(sDebug); pw.print(" verbose: "); pw.println(sVerbose); } @@ -1910,7 +1979,218 @@ public final class AutofillManager { if (sVerbose) Log.v(TAG, "ignoring post() because client is null"); return; } - client.runOnUiThread(runnable); + client.autofillClientRunOnUiThread(runnable); + } + + /** + * Implementation of the accessibility based compatibility. + */ + private final class CompatibilityBridge implements AccessibilityManager.AccessibilityPolicy { + @GuardedBy("mLock") + private final Rect mFocusedBounds = new Rect(); + @GuardedBy("mLock") + private final Rect mTempBounds = new Rect(); + + @GuardedBy("mLock") + private int mFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; + @GuardedBy("mLock") + private long mFocusedNodeId = AccessibilityNodeInfo.UNDEFINED_NODE_ID; + + // Need to report a fake service in case a11y clients check the service list + @NonNull + @GuardedBy("mLock") + AccessibilityServiceInfo mCompatServiceInfo; + + CompatibilityBridge() { + final AccessibilityManager am = AccessibilityManager.getInstance(mContext); + am.setAccessibilityPolicy(this); + } + + private AccessibilityServiceInfo getCompatServiceInfo() { + synchronized (mLock) { + if (mCompatServiceInfo != null) { + return mCompatServiceInfo; + } + final Intent intent = new Intent(); + intent.setComponent(new ComponentName("android", + "com.android.server.autofill.AutofillCompatAccessibilityService")); + final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService( + intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA); + try { + mCompatServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); + } catch (XmlPullParserException | IOException e) { + Log.e(TAG, "Cannot find compat autofill service:" + intent); + throw new IllegalStateException("Cannot find compat autofill service"); + } + return mCompatServiceInfo; + } + } + + @Override + public boolean isEnabled(boolean accessibilityEnabled) { + return true; + } + + @Override + public int getRelevantEventTypes(int relevantEventTypes) { + return relevantEventTypes | AccessibilityEvent.TYPE_VIEW_FOCUSED + | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED + | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED; + } + + @Override + public List getInstalledAccessibilityServiceList( + List installedServices) { + if (installedServices == null) { + installedServices = new ArrayList<>(); + } + installedServices.add(getCompatServiceInfo()); + return installedServices; + } + + @Override + public List getEnabledAccessibilityServiceList( + int feedbackTypeFlags, List enabledService) { + if (enabledService == null) { + enabledService = new ArrayList<>(); + } + enabledService.add(getCompatServiceInfo()); + return enabledService; + } + + @Override + public AccessibilityEvent onAccessibilityEvent(AccessibilityEvent event, + boolean accessibilityEnabled, int relevantEventTypes) { + switch (event.getEventType()) { + case AccessibilityEvent.TYPE_VIEW_FOCUSED: { + synchronized (mLock) { + if (mFocusedWindowId == event.getWindowId() + && mFocusedNodeId == event.getSourceNodeId()) { + return event; + } + if (mFocusedWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID + && mFocusedNodeId != AccessibilityNodeInfo.UNDEFINED_NODE_ID) { + notifyViewExited(mFocusedWindowId, mFocusedNodeId); + mFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; + mFocusedNodeId = AccessibilityNodeInfo.UNDEFINED_NODE_ID; + mFocusedBounds.set(0, 0, 0, 0); + } + final int windowId = event.getWindowId(); + final long nodeId = event.getSourceNodeId(); + if (notifyViewEntered(windowId, nodeId, mFocusedBounds)) { + mFocusedWindowId = windowId; + mFocusedNodeId = nodeId; + } + } + } break; + + case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED: { + synchronized (mLock) { + if (mFocusedWindowId == event.getWindowId() + && mFocusedNodeId == event.getSourceNodeId()) { + notifyValueChanged(event.getWindowId(), event.getSourceNodeId()); + } + } + } break; + + case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: { + final AutofillClient client = getClient(); + if (client != null) { + synchronized (mLock) { + if (client.autofillClientIsFillUiShowing()) { + notifyViewEntered(mFocusedWindowId, mFocusedNodeId, mFocusedBounds); + } + updateTrackedViewsLocked(); + } + } + } break; + } + + return accessibilityEnabled ? event : null; + } + + private boolean notifyViewEntered(int windowId, long nodeId, Rect focusedBounds) { + final int virtualId = AccessibilityNodeInfo.getVirtualDescendantId(nodeId); + if (!isVirtualNode(virtualId)) { + return false; + } + final View view = findViewByAccessibilityId(windowId, nodeId); + if (view == null) { + return false; + } + final AccessibilityNodeInfo node = findVirtualNodeByAccessibilityId(view, virtualId); + if (node == null) { + return false; + } + if (!node.isEditable()) { + return false; + } + final Rect newBounds = mTempBounds; + node.getBoundsInScreen(newBounds); + if (newBounds.equals(focusedBounds)) { + return false; + } + focusedBounds.set(newBounds); + AutofillManager.this.notifyViewEntered(view, virtualId, newBounds); + return true; + } + + private void notifyViewExited(int windowId, long nodeId) { + final int virtualId = AccessibilityNodeInfo.getVirtualDescendantId(nodeId); + if (!isVirtualNode(virtualId)) { + return; + } + final View view = findViewByAccessibilityId(windowId, nodeId); + if (view == null) { + return; + } + AutofillManager.this.notifyViewExited(view, virtualId); + } + + private void notifyValueChanged(int windowId, long nodeId) { + final int virtualId = AccessibilityNodeInfo.getVirtualDescendantId(nodeId); + if (!isVirtualNode(virtualId)) { + return; + } + final View view = findViewByAccessibilityId(windowId, nodeId); + if (view == null) { + return; + } + final AccessibilityNodeInfo node = findVirtualNodeByAccessibilityId(view, virtualId); + if (node == null) { + return; + } + AutofillManager.this.notifyValueChanged(view, virtualId, + AutofillValue.forText(node.getText())); + } + + private void updateTrackedViewsLocked() { + if (mTrackedViews != null) { + mTrackedViews.onVisibleForAutofillChangedLocked(); + } + } + + private View findViewByAccessibilityId(int windowId, long nodeId) { + final AutofillClient client = getClient(); + if (client == null) { + return null; + } + final int viewId = AccessibilityNodeInfo.getAccessibilityViewId(nodeId); + return client.autofillClientFindViewByAccessibilityIdTraversal(viewId, windowId); + } + + private AccessibilityNodeInfo findVirtualNodeByAccessibilityId(View view, int virtualId) { + final AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider(); + if (provider == null) { + return null; + } + return provider.createAccessibilityNodeInfo(virtualId); + } + + private boolean isVirtualNode(int nodeId) { + return nodeId != AccessibilityNodeProvider.HOST_VIEW_ID + && nodeId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID; + } } /** @@ -1989,11 +2269,11 @@ public final class AutofillManager { */ TrackedViews(@Nullable AutofillId[] trackedIds) { final AutofillClient client = getClient(); - if (trackedIds != null && client != null) { + if (!ArrayUtils.isEmpty(trackedIds) && client != null) { final boolean[] isVisible; - if (client.isVisibleForAutofill()) { - isVisible = client.getViewVisibility(getViewIds(trackedIds)); + if (client.autofillClientIsVisibleForAutofill()) { + isVisible = client.autofillClientGetViewVisibility(trackedIds); } else { // All false isVisible = new boolean[trackedIds.length]; @@ -2030,7 +2310,7 @@ public final class AutofillManager { */ void notifyViewVisibilityChangedLocked(@NonNull AutofillId id, boolean isVisible) { if (sDebug) { - Log.d(TAG, "notifyViewVisibilityChanged(): id=" + id + " isVisible=" + Log.d(TAG, "notifyViewVisibilityChangedLocked(): id=" + id + " isVisible=" + isVisible); } @@ -2059,9 +2339,9 @@ public final class AutofillManager { /** * Called once the client becomes visible. * - * @see AutofillClient#isVisibleForAutofill() + * @see AutofillClient#autofillClientIsVisibleForAutofill() */ - void onVisibleForAutofillLocked() { + void onVisibleForAutofillChangedLocked() { // The visibility of the views might have changed while the client was not be visible, // hence update the visibility state for all views. AutofillClient client = getClient(); @@ -2071,8 +2351,8 @@ public final class AutofillManager { if (mInvisibleTrackedIds != null) { final ArrayList orderedInvisibleIds = new ArrayList<>(mInvisibleTrackedIds); - final boolean[] isVisible = client.getViewVisibility( - getViewIds(orderedInvisibleIds)); + final boolean[] isVisible = client.autofillClientGetViewVisibility( + Helper.toArray(orderedInvisibleIds)); final int numInvisibleTrackedIds = orderedInvisibleIds.size(); for (int i = 0; i < numInvisibleTrackedIds; i++) { @@ -2092,8 +2372,8 @@ public final class AutofillManager { if (mVisibleTrackedIds != null) { final ArrayList orderedVisibleIds = new ArrayList<>(mVisibleTrackedIds); - final boolean[] isVisible = client.getViewVisibility( - getViewIds(orderedVisibleIds)); + final boolean[] isVisible = client.autofillClientGetViewVisibility( + Helper.toArray(orderedVisibleIds)); final int numVisibleTrackedIds = orderedVisibleIds.size(); for (int i = 0; i < numVisibleTrackedIds; i++) { diff --git a/core/java/android/view/autofill/AutofillManagerInternal.java b/core/java/android/view/autofill/AutofillManagerInternal.java index fc5d306ddcef5879f982d2d103143ab8e9a11264..155fe721311c36eec0e884ebffb6b5cefb43b333 100644 --- a/core/java/android/view/autofill/AutofillManagerInternal.java +++ b/core/java/android/view/autofill/AutofillManagerInternal.java @@ -15,6 +15,9 @@ */ package android.view.autofill; +import android.annotation.NonNull; +import android.annotation.UserIdInt; + /** * Autofill Manager local system service interface. * @@ -26,4 +29,14 @@ public abstract class AutofillManagerInternal { * Notifies the manager that the back key was pressed. */ public abstract void onBackKeyPressed(); + + /** + * Gets whether compatibility mode is enabled for a package + * + * @param packageName The package for which to query. + * @param versionCode The package version code. + * @param userId The user id for which to query. + */ + public abstract boolean isCompatibilityModeRequested(@NonNull String packageName, + long versionCode, @UserIdInt int userId); } diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java index 4b2c53c7eb844b76c41552ebc67dfbefe4cc2f54..48d0dbb3e02bee2766031b295f3d3f964ffc6b68 100644 --- a/core/java/android/view/autofill/Helper.java +++ b/core/java/android/view/autofill/Helper.java @@ -19,6 +19,8 @@ package android.view.autofill; import android.annotation.NonNull; import android.annotation.Nullable; +import java.util.Collection; + /** @hide */ public final class Helper { @@ -59,6 +61,20 @@ public final class Helper { builder.append(" ]"); } + /** + * Convers a collaction of {@link AutofillId AutofillIds} to an array. + * @param collection The collection. + * @return The array. + */ + public static @NonNull AutofillId[] toArray(Collection collection) { + if (collection == null) { + return new AutofillId[0]; + } + final AutofillId[] array = new AutofillId[collection.size()]; + collection.toArray(array); + return array; + } + private Helper() { throw new UnsupportedOperationException("contains static members only"); } diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 1a11fbba00116b08474a5be1061397a7605f53ae..001854716715ec845f2b6a9e24241205001f05ab 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -56,6 +56,7 @@ interface IAutoFillManager { boolean isServiceEnabled(int userId, String packageName); void onPendingSaveUi(int operation, IBinder token); UserData getUserData(); + String getUserDataId(); void setUserData(in UserData userData); boolean isFieldClassificationEnabled(); ComponentName getAutofillServiceComponentName(); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 7db5c32072967ad4c6569a6d67b3ea25c5d37e80..9de26a86f20fd5f8d4cc7e91ae4cd6bcb92ece86 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemService; +import android.annotation.TestApi; import android.content.Context; import android.graphics.Rect; import android.inputmethodservice.InputMethodService; @@ -1178,8 +1179,9 @@ public final class InputMethodManager { } } - /* + /** * This method toggles the input method window display. + * * If the input window is already displayed, it gets hidden. * If not the input window will be displayed. * @param showFlags Provides additional operating flags. May be @@ -1188,7 +1190,6 @@ public final class InputMethodManager { * @param hideFlags Provides additional operating flags. May be * 0 or have the {@link #HIDE_IMPLICIT_ONLY}, * {@link #HIDE_NOT_ALWAYS} bit set. - * @hide */ public void toggleSoftInput(int showFlags, int hideFlags) { if (mCurMethod != null) { @@ -2136,6 +2137,26 @@ public final class InputMethodManager { } } + /** + * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected. + * + *

    When customizing the implementation of {@link #showInputMethodPicker()} API, make sure + * that this test API returns when and only while and only while + * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not + * pass CTS.

    + * + * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI. + * @hide + */ + @TestApi + public boolean isInputMethodPickerShown() { + try { + return mService.isInputMethodPickerShownForTest(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Show the settings for enabling subtypes of the specified input method. * @param imiId An input method, whose subtypes settings will be shown. If imiId is null, diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java new file mode 100644 index 0000000000000000000000000000000000000000..af55dcd0ed7251fb8fad6bcc06ff7a226255e9a8 --- /dev/null +++ b/core/java/android/view/textclassifier/SystemTextClassifier.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textclassifier; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.WorkerThread; +import android.content.Context; +import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.service.textclassifier.ITextClassificationCallback; +import android.service.textclassifier.ITextClassifierService; +import android.service.textclassifier.ITextLinksCallback; +import android.service.textclassifier.ITextSelectionCallback; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Proxy to the system's default TextClassifier. + */ +final class SystemTextClassifier implements TextClassifier { + + private static final String LOG_TAG = "SystemTextClassifier"; + + private final ITextClassifierService mManagerService; + private final TextClassifier mFallback; + + SystemTextClassifier(Context context) throws ServiceManager.ServiceNotFoundException { + mManagerService = ITextClassifierService.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE)); + mFallback = new TextClassifierImpl(context); + } + + /** + * @inheritDoc + */ + @WorkerThread + public TextSelection suggestSelection( + @NonNull CharSequence text, + @IntRange(from = 0) int selectionStartIndex, + @IntRange(from = 0) int selectionEndIndex, + @Nullable TextSelection.Options options) { + Utils.validate(text, selectionStartIndex, selectionEndIndex, false /* allowInMainThread */); + try { + final TextSelectionCallback callback = new TextSelectionCallback(); + mManagerService.onSuggestSelection( + text, selectionStartIndex, selectionEndIndex, options, callback); + final TextSelection selection = callback.mReceiver.get(); + if (selection != null) { + return selection; + } + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } catch (InterruptedException e) { + Log.d(LOG_TAG, e.getMessage()); + } + return mFallback.suggestSelection(text, selectionStartIndex, selectionEndIndex, options); + } + + /** + * @inheritDoc + */ + @WorkerThread + public TextClassification classifyText( + @NonNull CharSequence text, + @IntRange(from = 0) int startIndex, + @IntRange(from = 0) int endIndex, + @Nullable TextClassification.Options options) { + Utils.validate(text, startIndex, endIndex, false /* allowInMainThread */); + try { + final TextClassificationCallback callback = new TextClassificationCallback(); + mManagerService.onClassifyText(text, startIndex, endIndex, options, callback); + final TextClassification classification = callback.mReceiver.get(); + if (classification != null) { + return classification; + } + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } catch (InterruptedException e) { + Log.d(LOG_TAG, e.getMessage()); + } + return mFallback.classifyText(text, startIndex, endIndex, options); + } + + /** + * @inheritDoc + */ + @WorkerThread + public TextLinks generateLinks( + @NonNull CharSequence text, @Nullable TextLinks.Options options) { + Utils.validate(text, false /* allowInMainThread */); + try { + final TextLinksCallback callback = new TextLinksCallback(); + mManagerService.onGenerateLinks(text, options, callback); + final TextLinks links = callback.mReceiver.get(); + if (links != null) { + return links; + } + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } catch (InterruptedException e) { + Log.d(LOG_TAG, e.getMessage()); + } + return mFallback.generateLinks(text, options); + } + + private static final class TextSelectionCallback extends ITextSelectionCallback.Stub { + + final ResponseReceiver mReceiver = new ResponseReceiver<>(); + + @Override + public void onSuccess(TextSelection selection) { + mReceiver.onSuccess(selection); + } + + @Override + public void onFailure() { + mReceiver.onFailure(); + } + } + + private static final class TextClassificationCallback extends ITextClassificationCallback.Stub { + + final ResponseReceiver mReceiver = new ResponseReceiver<>(); + + @Override + public void onSuccess(TextClassification classification) { + mReceiver.onSuccess(classification); + } + + @Override + public void onFailure() { + mReceiver.onFailure(); + } + } + + private static final class TextLinksCallback extends ITextLinksCallback.Stub { + + final ResponseReceiver mReceiver = new ResponseReceiver<>(); + + @Override + public void onSuccess(TextLinks links) { + mReceiver.onSuccess(links); + } + + @Override + public void onFailure() { + mReceiver.onFailure(); + } + } + + private static final class ResponseReceiver { + + private final CountDownLatch mLatch = new CountDownLatch(1); + + private T mResponse; + + public void onSuccess(T response) { + mResponse = response; + mLatch.countDown(); + } + + public void onFailure() { + Log.e(LOG_TAG, "Request failed.", null); + mLatch.countDown(); + } + + @Nullable + public T get() throws InterruptedException { + // If this is running on the main thread, do not block for a response. + // The response will unfortunately be null and the TextClassifier should depend on its + // fallback. + // NOTE that TextClassifier calls should preferably always be called on a worker thread. + if (Looper.myLooper() != Looper.getMainLooper()) { + mLatch.await(2, TimeUnit.SECONDS); + } + return mResponse; + } + } +} diff --git a/core/java/android/view/textclassifier/TextClassification.aidl b/core/java/android/view/textclassifier/TextClassification.aidl new file mode 100644 index 0000000000000000000000000000000000000000..9fefe5d4176a3d2c378cfaa6e2e577cecb2bc2ad --- /dev/null +++ b/core/java/android/view/textclassifier/TextClassification.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textclassifier; + +parcelable TextClassification; +parcelable TextClassification.Options; \ No newline at end of file diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java index 54e93d5afd880e273a8d65e2881b0f8181b5719a..a6a2a945e774359c1d6c51c9eea19a59cc8c2cb2 100644 --- a/core/java/android/view/textclassifier/TextClassification.java +++ b/core/java/android/view/textclassifier/TextClassification.java @@ -97,7 +97,7 @@ import java.util.Map; * }); * } */ -public final class TextClassification { +public final class TextClassification implements Parcelable { /** * @hide @@ -310,42 +310,6 @@ public final class TextClassification { mSignature); } - /** Helper for parceling via #ParcelableWrapper. */ - private void writeToParcel(Parcel dest, int flags) { - dest.writeString(mText); - final Bitmap primaryIconBitmap = drawableToBitmap(mPrimaryIcon, MAX_PRIMARY_ICON_SIZE); - dest.writeInt(primaryIconBitmap != null ? 1 : 0); - if (primaryIconBitmap != null) { - primaryIconBitmap.writeToParcel(dest, flags); - } - dest.writeString(mPrimaryLabel); - dest.writeInt(mPrimaryIntent != null ? 1 : 0); - if (mPrimaryIntent != null) { - mPrimaryIntent.writeToParcel(dest, flags); - } - // mPrimaryOnClickListener is not parcelable. - dest.writeTypedList(drawablesToBitmaps(mSecondaryIcons, MAX_SECONDARY_ICON_SIZE)); - dest.writeStringList(mSecondaryLabels); - dest.writeTypedList(mSecondaryIntents); - mEntityConfidence.writeToParcel(dest, flags); - dest.writeString(mSignature); - } - - /** Helper for unparceling via #ParcelableWrapper. */ - private TextClassification(Parcel in) { - mText = in.readString(); - mPrimaryIcon = in.readInt() == 0 - ? null : new BitmapDrawable(null, Bitmap.CREATOR.createFromParcel(in)); - mPrimaryLabel = in.readString(); - mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in); - mPrimaryOnClickListener = null; // not parcelable - mSecondaryIcons = bitmapsToDrawables(in.createTypedArrayList(Bitmap.CREATOR)); - mSecondaryLabels = in.createStringArrayList(); - mSecondaryIntents = in.createTypedArrayList(Intent.CREATOR); - mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in); - mSignature = in.readString(); - } - /** * Creates an OnClickListener that starts an activity with the specified intent. * @@ -675,46 +639,56 @@ public final class TextClassification { } } - /** - * Parcelable wrapper for TextClassification objects. - * @hide - */ - public static final class ParcelableWrapper implements Parcelable { - - @NonNull private TextClassification mTextClassification; - - public ParcelableWrapper(@NonNull TextClassification textClassification) { - Preconditions.checkNotNull(textClassification); - mTextClassification = textClassification; - } - - @NonNull - public TextClassification getTextClassification() { - return mTextClassification; - } + @Override + public int describeContents() { + return 0; + } - @Override - public int describeContents() { - return 0; + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mText); + final Bitmap primaryIconBitmap = drawableToBitmap(mPrimaryIcon, MAX_PRIMARY_ICON_SIZE); + dest.writeInt(primaryIconBitmap != null ? 1 : 0); + if (primaryIconBitmap != null) { + primaryIconBitmap.writeToParcel(dest, flags); } - - @Override - public void writeToParcel(Parcel dest, int flags) { - mTextClassification.writeToParcel(dest, flags); + dest.writeString(mPrimaryLabel); + dest.writeInt(mPrimaryIntent != null ? 1 : 0); + if (mPrimaryIntent != null) { + mPrimaryIntent.writeToParcel(dest, flags); } + // mPrimaryOnClickListener is not parcelable. + dest.writeTypedList(drawablesToBitmaps(mSecondaryIcons, MAX_SECONDARY_ICON_SIZE)); + dest.writeStringList(mSecondaryLabels); + dest.writeTypedList(mSecondaryIntents); + mEntityConfidence.writeToParcel(dest, flags); + dest.writeString(mSignature); + } - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public ParcelableWrapper createFromParcel(Parcel in) { - return new ParcelableWrapper(new TextClassification(in)); - } + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public TextClassification createFromParcel(Parcel in) { + return new TextClassification(in); + } - @Override - public ParcelableWrapper[] newArray(int size) { - return new ParcelableWrapper[size]; - } - }; + @Override + public TextClassification[] newArray(int size) { + return new TextClassification[size]; + } + }; + private TextClassification(Parcel in) { + mText = in.readString(); + mPrimaryIcon = in.readInt() == 0 + ? null : new BitmapDrawable(null, Bitmap.CREATOR.createFromParcel(in)); + mPrimaryLabel = in.readString(); + mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in); + mPrimaryOnClickListener = null; // not parcelable + mSecondaryIcons = bitmapsToDrawables(in.createTypedArrayList(Bitmap.CREATOR)); + mSecondaryLabels = in.createStringArrayList(); + mSecondaryIntents = in.createTypedArrayList(Intent.CREATOR); + mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in); + mSignature = in.readString(); } } diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java index d7b07761a65359b3822efbe9f38e775c1b1ec3dc..300aef2d172e46c1137948aa6d7006502a2ee5f7 100644 --- a/core/java/android/view/textclassifier/TextClassificationManager.java +++ b/core/java/android/view/textclassifier/TextClassificationManager.java @@ -19,6 +19,8 @@ package android.view.textclassifier; import android.annotation.Nullable; import android.annotation.SystemService; import android.content.Context; +import android.os.ServiceManager; +import android.service.textclassifier.TextClassifierService; import com.android.internal.util.Preconditions; @@ -28,23 +30,56 @@ import com.android.internal.util.Preconditions; @SystemService(Context.TEXT_CLASSIFICATION_SERVICE) public final class TextClassificationManager { - private final Object mTextClassifierLock = new Object(); + // TODO: Make this a configurable flag. + private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED = true; + + private static final String LOG_TAG = "TextClassificationManager"; + + private final Object mLock = new Object(); private final Context mContext; private TextClassifier mTextClassifier; + private TextClassifier mSystemTextClassifier; /** @hide */ public TextClassificationManager(Context context) { mContext = Preconditions.checkNotNull(context); } + /** + * Returns the system's default TextClassifier. + * @hide + */ + // TODO: Unhide when this is ready. + public TextClassifier getSystemDefaultTextClassifier() { + synchronized (mLock) { + if (mSystemTextClassifier == null && isSystemTextClassifierEnabled()) { + try { + Log.d(LOG_TAG, "Initialized SystemTextClassifier"); + mSystemTextClassifier = new SystemTextClassifier(mContext); + } catch (ServiceManager.ServiceNotFoundException e) { + Log.e(LOG_TAG, "Could not initialize SystemTextClassifier", e); + } + } + if (mSystemTextClassifier == null) { + Log.d(LOG_TAG, "Using an in-process TextClassifier as the system default"); + mSystemTextClassifier = new TextClassifierImpl(mContext); + } + } + return mSystemTextClassifier; + } + /** * Returns the text classifier. */ public TextClassifier getTextClassifier() { - synchronized (mTextClassifierLock) { + synchronized (mLock) { if (mTextClassifier == null) { - mTextClassifier = new TextClassifierImpl(mContext); + if (isSystemTextClassifierEnabled()) { + mTextClassifier = getSystemDefaultTextClassifier(); + } else { + mTextClassifier = new TextClassifierImpl(mContext); + } } return mTextClassifier; } @@ -56,8 +91,13 @@ public final class TextClassificationManager { * Set to {@link TextClassifier#NO_OP} to disable text classifier features. */ public void setTextClassifier(@Nullable TextClassifier textClassifier) { - synchronized (mTextClassifierLock) { + synchronized (mLock) { mTextClassifier = textClassifier; } } + + private boolean isSystemTextClassifierEnabled() { + return SYSTEM_TEXT_CLASSIFIER_ENABLED + && TextClassifierService.getServiceComponentName(mContext) != null; + } } diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index 04ab4474a40cc629219ee26eaeb8de2ff76faea3..9f75c4a80ca2c6bbe9dc1a7c7c2690a01557c0aa 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -23,9 +23,12 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.WorkerThread; import android.os.LocaleList; +import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; +import android.util.Slog; +import android.view.textclassifier.logging.Logger; import com.android.internal.util.Preconditions; @@ -39,8 +42,8 @@ import java.util.List; /** * Interface for providing text classification related features. * - *

    Unless otherwise stated, methods of this interface are blocking operations. - * Avoid calling them on the UI thread. + *

    NOTE: Unless otherwise stated, methods of this interface are blocking + * operations. Call on a worker thread. */ public interface TextClassifier { @@ -107,6 +110,8 @@ public interface TextClassifier { * Returns suggested text selection start and end indices, recognized entity types, and their * associated confidence scores. The entity types are ordered from highest to lowest scoring. * + *

    NOTE: Call on a worker thread. + * * @param text text providing context for the selected text (which is specified * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex) * @param selectionStartIndex start index of the selected part of text @@ -125,7 +130,7 @@ public interface TextClassifier { @IntRange(from = 0) int selectionStartIndex, @IntRange(from = 0) int selectionEndIndex, @Nullable TextSelection.Options options) { - Utils.validateInput(text, selectionStartIndex, selectionEndIndex); + Utils.validate(text, selectionStartIndex, selectionEndIndex, false); return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build(); } @@ -137,6 +142,8 @@ public interface TextClassifier { * {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. If that method * calls this method, a stack overflow error will happen. * + *

    NOTE: Call on a worker thread. + * * @param text text providing context for the selected text (which is specified * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex) * @param selectionStartIndex start index of the selected part of text @@ -161,6 +168,8 @@ public interface TextClassifier { * See {@link #suggestSelection(CharSequence, int, int)} or * {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. * + *

    NOTE: Call on a worker thread. + * *

    NOTE: Do not implement. The default implementation of this method calls * {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. If that method * calls this method, a stack overflow error will happen. @@ -182,6 +191,8 @@ public interface TextClassifier { * Classifies the specified text and returns a {@link TextClassification} object that can be * used to generate a widget for handling the classified text. * + *

    NOTE: Call on a worker thread. + * * @param text text providing context for the text to classify (which is specified * by the sub sequence starting at startIndex and ending at endIndex) * @param startIndex start index of the text to classify @@ -200,7 +211,7 @@ public interface TextClassifier { @IntRange(from = 0) int startIndex, @IntRange(from = 0) int endIndex, @Nullable TextClassification.Options options) { - Utils.validateInput(text, startIndex, endIndex); + Utils.validate(text, startIndex, endIndex, false); return TextClassification.EMPTY; } @@ -208,6 +219,8 @@ public interface TextClassifier { * Classifies the specified text and returns a {@link TextClassification} object that can be * used to generate a widget for handling the classified text. * + *

    NOTE: Call on a worker thread. + * *

    NOTE: Do not implement. The default implementation of this method calls * {@link #classifyText(CharSequence, int, int, TextClassification.Options)}. If that method * calls this method, a stack overflow error will happen. @@ -235,6 +248,8 @@ public interface TextClassifier { * See {@link #classifyText(CharSequence, int, int, TextClassification.Options)} or * {@link #classifyText(CharSequence, int, int)}. * + *

    NOTE: Call on a worker thread. + * *

    NOTE: Do not implement. The default implementation of this method calls * {@link #classifyText(CharSequence, int, int, TextClassification.Options)}. If that method * calls this method, a stack overflow error will happen. @@ -253,10 +268,10 @@ public interface TextClassifier { } /** - * Returns a {@link TextLinks} that may be applied to the text to annotate it with links - * information. + * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with + * links information. * - * If no options are supplied, default values will be used, determined by the TextClassifier. + *

    NOTE: Call on a worker thread. * * @param text the text to generate annotations for * @param options configuration for link generation @@ -268,13 +283,15 @@ public interface TextClassifier { @WorkerThread default TextLinks generateLinks( @NonNull CharSequence text, @Nullable TextLinks.Options options) { - Utils.validateInput(text); + Utils.validate(text, false); return new TextLinks.Builder(text.toString()).build(); } /** - * Returns a {@link TextLinks} that may be applied to the text to annotate it with links - * information. + * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with + * links information. + * + *

    NOTE: Call on a worker thread. * *

    NOTE: Do not implement. The default implementation of this method calls * {@link #generateLinks(CharSequence, TextLinks.Options)}. If that method calls this method, @@ -296,20 +313,22 @@ public interface TextClassifier { * * @see #ENTITY_PRESET_ALL * @see #ENTITY_PRESET_NONE + * @see #ENTITY_PRESET_BASE */ default Collection getEntitiesForPreset(@EntityPreset int entityPreset) { return Collections.EMPTY_LIST; } /** - * Logs a TextClassifier event. + * Returns a helper for logging TextClassifier related events. * - * @param source the text classifier used to generate this event - * @param event the text classifier related event - * @hide + * @param config logger configuration */ @WorkerThread - default void logEvent(String source, String event) {} + default Logger getLogger(@NonNull Logger.Config config) { + Preconditions.checkNotNull(config); + return Logger.DISABLED; + } /** * Returns this TextClassifier's settings. @@ -424,19 +443,28 @@ public interface TextClassifier { * endIndex is greater than text.length() or is not greater than startIndex; * options is null */ - static void validateInput( - @NonNull CharSequence text, int startIndex, int endIndex) { + public static void validate( + @NonNull CharSequence text, int startIndex, int endIndex, + boolean allowInMainThread) { Preconditions.checkArgument(text != null); Preconditions.checkArgument(startIndex >= 0); Preconditions.checkArgument(endIndex <= text.length()); Preconditions.checkArgument(endIndex > startIndex); + checkMainThread(allowInMainThread); } /** * @throws IllegalArgumentException if text is null or options is null */ - static void validateInput(@NonNull CharSequence text) { + public static void validate(@NonNull CharSequence text, boolean allowInMainThread) { Preconditions.checkArgument(text != null); + checkMainThread(allowInMainThread); + } + + private static void checkMainThread(boolean allowInMainThread) { + if (!allowInMainThread && Looper.myLooper() == Looper.getMainLooper()) { + Slog.w(DEFAULT_LOG_TAG, "TextClassifier called on main thread"); + } } } } diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 6a44fb38ee13cbca937fba35b1c56f1a26f0274b..9f389ba0c1402f228b4990a07ceb9dca0fd27e88 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -35,6 +35,8 @@ import android.provider.ContactsContract; import android.provider.Settings; import android.text.util.Linkify; import android.util.Patterns; +import android.view.textclassifier.logging.DefaultLogger; +import android.view.textclassifier.logging.Logger; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; @@ -43,6 +45,7 @@ import com.android.internal.util.Preconditions; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -66,13 +69,13 @@ import java.util.regex.Pattern; * * @hide */ -final class TextClassifierImpl implements TextClassifier { +public final class TextClassifierImpl implements TextClassifier { private static final String LOG_TAG = DEFAULT_LOG_TAG; private static final String MODEL_DIR = "/etc/textclassifier/"; - private static final String MODEL_FILE_REGEX = "textclassifier\\.smartselection\\.(.*)\\.model"; + private static final String MODEL_FILE_REGEX = "textclassifier\\.(.*)\\.model"; private static final String UPDATED_MODEL_FILE_PATH = - "/data/misc/textclassifier/textclassifier.smartselection.model"; + "/data/misc/textclassifier/textclassifier.model"; private static final List ENTITY_TYPES_ALL = Collections.unmodifiableList(Arrays.asList( TextClassifier.TYPE_ADDRESS, @@ -90,30 +93,39 @@ final class TextClassifierImpl implements TextClassifier { TextClassifier.TYPE_URL)); private final Context mContext; + private final TextClassifier mFallback; private final MetricsLogger mMetricsLogger = new MetricsLogger(); - private final Object mSmartSelectionLock = new Object(); - @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. + private final Object mLock = new Object(); + @GuardedBy("mLock") // Do not access outside this lock. private Map mModelFilePaths; - @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. + @GuardedBy("mLock") // Do not access outside this lock. private Locale mLocale; - @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. + @GuardedBy("mLock") // Do not access outside this lock. private int mVersion; - @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. + @GuardedBy("mLock") // Do not access outside this lock. private SmartSelection mSmartSelection; + private final Object mLoggerLock = new Object(); + @GuardedBy("mLoggerLock") // Do not access outside this lock. + private WeakReference mLoggerConfig = new WeakReference<>(null); + @GuardedBy("mLoggerLock") // Do not access outside this lock. + private Logger mLogger; // Should never be null if mLoggerConfig.get() is not null. + private TextClassifierConstants mSettings; - TextClassifierImpl(Context context) { + public TextClassifierImpl(Context context) { mContext = Preconditions.checkNotNull(context); + mFallback = TextClassifier.NO_OP; } + /** @inheritDoc */ @Override public TextSelection suggestSelection( @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex, @Nullable TextSelection.Options options) { - Utils.validateInput(text, selectionStartIndex, selectionEndIndex); + Utils.validate(text, selectionStartIndex, selectionEndIndex, false /* allowInMainThread */); try { if (text.length() > 0) { final LocaleList locales = (options == null) ? null : options.getDefaultLocales(); @@ -159,15 +171,16 @@ final class TextClassifierImpl implements TextClassifier { t); } // Getting here means something went wrong, return a NO_OP result. - return TextClassifier.NO_OP.suggestSelection( + return mFallback.suggestSelection( text, selectionStartIndex, selectionEndIndex, options); } + /** @inheritDoc */ @Override public TextClassification classifyText( @NonNull CharSequence text, int startIndex, int endIndex, @Nullable TextClassification.Options options) { - Utils.validateInput(text, startIndex, endIndex); + Utils.validate(text, startIndex, endIndex, false /* allowInMainThread */); try { if (text.length() > 0) { final String string = text.toString(); @@ -186,13 +199,14 @@ final class TextClassifierImpl implements TextClassifier { Log.e(LOG_TAG, "Error getting text classification info.", t); } // Getting here means something went wrong, return a NO_OP result. - return TextClassifier.NO_OP.classifyText(text, startIndex, endIndex, options); + return mFallback.classifyText(text, startIndex, endIndex, options); } + /** @inheritDoc */ @Override public TextLinks generateLinks( @NonNull CharSequence text, @Nullable TextLinks.Options options) { - Utils.validateInput(text); + Utils.validate(text, false /* allowInMainThread */); final String textString = text.toString(); final TextLinks.Builder builder = new TextLinks.Builder(textString); @@ -216,14 +230,14 @@ final class TextClassifierImpl implements TextClassifier { for (int i = 0; i < results.length; i++) { entityScores.put(results[i].mCollection, results[i].mScore); } - builder.addLink(new TextLinks.TextLink( - textString, span.getStartIndex(), span.getEndIndex(), entityScores)); + builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores); } + return builder.build(); } catch (Throwable t) { // Avoid throwing from this method. Log the error. Log.e(LOG_TAG, "Error getting links info.", t); } - return builder.build(); + return mFallback.generateLinks(text, options); } @Override @@ -241,12 +255,18 @@ final class TextClassifierImpl implements TextClassifier { } @Override - public void logEvent(String source, String event) { - if (LOG_TAG.equals(source)) { - mMetricsLogger.count(event, 1); + public Logger getLogger(@NonNull Logger.Config config) { + Preconditions.checkNotNull(config); + synchronized (mLoggerLock) { + if (mLoggerConfig.get() == null || !mLoggerConfig.get().equals(config)) { + mLoggerConfig = new WeakReference<>(config); + mLogger = new DefaultLogger(config); + } + return mLogger; } } + /** @hide */ @Override public TextClassifierConstants getSettings() { if (mSettings == null) { @@ -257,7 +277,7 @@ final class TextClassifierImpl implements TextClassifier { } private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException { - synchronized (mSmartSelectionLock) { + synchronized (mLock) { localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList; final Locale locale = findBestSupportedLocaleLocked(localeList); if (locale == null) { @@ -277,16 +297,12 @@ final class TextClassifierImpl implements TextClassifier { } private String getSignature(String text, int start, int end) { - synchronized (mSmartSelectionLock) { - final String versionInfo = (mLocale != null) - ? String.format(Locale.US, "%s_v%d", mLocale.toLanguageTag(), mVersion) - : ""; - final int hash = Objects.hash(text, start, end, mContext.getPackageName()); - return String.format(Locale.US, "%s|%s|%d", LOG_TAG, versionInfo, hash); + synchronized (mLock) { + return DefaultLogger.createSignature(text, start, end, mContext, mVersion, mLocale); } } - @GuardedBy("mSmartSelectionLock") // Do not call outside this lock. + @GuardedBy("mLock") // Do not call outside this lock. private ParcelFileDescriptor getFdLocked(Locale locale) throws FileNotFoundException { ParcelFileDescriptor updateFd; int updateVersion = -1; @@ -321,7 +337,7 @@ final class TextClassifierImpl implements TextClassifier { return factoryFd; } else { throw new FileNotFoundException( - String.format("No model file found for %s", locale)); + String.format(Locale.US, "No model file found for %s", locale)); } } @@ -335,7 +351,7 @@ final class TextClassifierImpl implements TextClassifier { } else { closeAndLogError(updateFd); throw new FileNotFoundException( - String.format("No model file found for %s", locale)); + String.format(Locale.US, "No model file found for %s", locale)); } } @@ -353,7 +369,7 @@ final class TextClassifierImpl implements TextClassifier { } } - @GuardedBy("mSmartSelectionLock") // Do not call outside this lock. + @GuardedBy("mLock") // Do not call outside this lock. private void destroySmartSelectionIfExistsLocked() { if (mSmartSelection != null) { mSmartSelection.close(); @@ -361,7 +377,7 @@ final class TextClassifierImpl implements TextClassifier { } } - @GuardedBy("mSmartSelectionLock") // Do not call outside this lock. + @GuardedBy("mLock") // Do not call outside this lock. @Nullable private Locale findBestSupportedLocaleLocked(LocaleList localeList) { // Specified localeList takes priority over the system default, so it is listed first. @@ -379,7 +395,7 @@ final class TextClassifierImpl implements TextClassifier { return Locale.lookup(languageRangeList, supportedLocales); } - @GuardedBy("mSmartSelectionLock") // Do not call outside this lock. + @GuardedBy("mLock") // Do not call outside this lock. private Map getFactoryModelFilePathsLocked() { if (mModelFilePaths == null) { final Map modelFilePaths = new HashMap<>(); diff --git a/core/java/android/view/textclassifier/TextLinks.aidl b/core/java/android/view/textclassifier/TextLinks.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1bbb79845528b2c48544766199730c98aa5f4217 --- /dev/null +++ b/core/java/android/view/textclassifier/TextLinks.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textclassifier; + +parcelable TextLinks; +parcelable TextLinks.Options; \ No newline at end of file diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java index ba854e040460facfd46b08b647bc7308c72b8bff..d866d1305172aa71541fb57ca54a4e25d711daca 100644 --- a/core/java/android/view/textclassifier/TextLinks.java +++ b/core/java/android/view/textclassifier/TextLinks.java @@ -17,18 +17,24 @@ package android.view.textclassifier; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; -import android.text.SpannableString; +import android.text.Spannable; import android.text.style.ClickableSpan; +import android.text.util.Linkify; +import android.text.util.Linkify.LinkifyMask; import android.view.View; +import android.view.textclassifier.TextClassifier.EntityType; import android.widget.TextView; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -41,12 +47,51 @@ import java.util.function.Function; * address, url, etc) they may be. */ public final class TextLinks implements Parcelable { + + /** + * Return status of an attempt to apply TextLinks to text. + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({STATUS_LINKS_APPLIED, STATUS_NO_LINKS_FOUND, STATUS_NO_LINKS_APPLIED, + STATUS_DIFFERENT_TEXT}) + public @interface Status {} + + /** Links were successfully applied to the text. */ + public static final int STATUS_LINKS_APPLIED = 0; + + /** No links exist to apply to text. Links count is zero. */ + public static final int STATUS_NO_LINKS_FOUND = 1; + + /** No links applied to text. The links were filtered out. */ + public static final int STATUS_NO_LINKS_APPLIED = 2; + + /** The specified text does not match the text used to generate the links. */ + public static final int STATUS_DIFFERENT_TEXT = 3; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({APPLY_STRATEGY_IGNORE, APPLY_STRATEGY_REPLACE}) + public @interface ApplyStrategy {} + + /** + * Do not replace {@link ClickableSpan}s that exist where the {@link TextLinkSpan} needs to + * be applied to. Do not apply the TextLinkSpan. + */ + public static final int APPLY_STRATEGY_IGNORE = 0; + + /** + * Replace any {@link ClickableSpan}s that exist where the {@link TextLinkSpan} needs to be + * applied to. + */ + public static final int APPLY_STRATEGY_REPLACE = 1; + private final String mFullText; private final List mLinks; - private TextLinks(String fullText, Collection links) { + private TextLinks(String fullText, ArrayList links) { mFullText = fullText; - mLinks = Collections.unmodifiableList(new ArrayList<>(links)); + mLinks = Collections.unmodifiableList(links); } /** @@ -60,29 +105,57 @@ public final class TextLinks implements Parcelable { * Annotates the given text with the generated links. It will fail if the provided text doesn't * match the original text used to crete the TextLinks. * - * @param text the text to apply the links to. Must match the original text. - * @param spanFactory a factory to generate spans from TextLinks. Will use a default if null. + * @param text the text to apply the links to. Must match the original text + * @param applyStrategy strategy for resolving link conflicts + * @param spanFactory a factory to generate spans from TextLinks. Will use a default if null * - * @return Success or failure. + * @return a status code indicating whether or not the links were successfully applied + * + * @hide */ - public boolean apply( - @NonNull SpannableString text, - @Nullable Function spanFactory) { + @Status + public int apply( + @NonNull Spannable text, + @ApplyStrategy int applyStrategy, + @Nullable Function spanFactory) { Preconditions.checkNotNull(text); + checkValidApplyStrategy(applyStrategy); if (!mFullText.equals(text.toString())) { - return false; + return STATUS_DIFFERENT_TEXT; + } + if (mLinks.isEmpty()) { + return STATUS_NO_LINKS_FOUND; } if (spanFactory == null) { spanFactory = DEFAULT_SPAN_FACTORY; } + int applyCount = 0; for (TextLink link : mLinks) { - final ClickableSpan span = spanFactory.apply(link); + final TextLinkSpan span = spanFactory.apply(link); if (span != null) { - text.setSpan(span, link.getStart(), link.getEnd(), 0); + final ClickableSpan[] existingSpans = text.getSpans( + link.getStart(), link.getEnd(), ClickableSpan.class); + if (existingSpans.length > 0) { + if (applyStrategy == APPLY_STRATEGY_REPLACE) { + for (ClickableSpan existingSpan : existingSpans) { + text.removeSpan(existingSpan); + } + text.setSpan(span, link.getStart(), link.getEnd(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + applyCount++; + } + } else { + text.setSpan(span, link.getStart(), link.getEnd(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + applyCount++; + } } } - return true; + if (applyCount == 0) { + return STATUS_NO_LINKS_APPLIED; + } + return STATUS_LINKS_APPLIED; } @Override @@ -119,21 +192,22 @@ public final class TextLinks implements Parcelable { */ public static final class TextLink implements Parcelable { private final EntityConfidence mEntityScores; - private final String mOriginalText; private final int mStart; private final int mEnd; /** * Create a new TextLink. * - * @throws IllegalArgumentException if entityScores is null or empty. + * @param start The start index of the identified subsequence + * @param end The end index of the identified subsequence + * @param entityScores A mapping of entity type to confidence score + * + * @throws IllegalArgumentException if entityScores is null or empty */ - public TextLink(String originalText, int start, int end, Map entityScores) { - Preconditions.checkNotNull(originalText); + TextLink(int start, int end, Map entityScores) { Preconditions.checkNotNull(entityScores); Preconditions.checkArgument(!entityScores.isEmpty()); Preconditions.checkArgument(start <= end); - mOriginalText = originalText; mStart = start; mEnd = end; mEntityScores = new EntityConfidence(entityScores); @@ -142,7 +216,7 @@ public final class TextLinks implements Parcelable { /** * Returns the start index of this link in the original text. * - * @return the start index. + * @return the start index */ public int getStart() { return mStart; @@ -151,7 +225,7 @@ public final class TextLinks implements Parcelable { /** * Returns the end index of this link in the original text. * - * @return the end index. + * @return the end index */ public int getEnd() { return mEnd; @@ -160,7 +234,7 @@ public final class TextLinks implements Parcelable { /** * Returns the number of entity types that have confidence scores. * - * @return the entity count. + * @return the entity count */ public int getEntityCount() { return mEntityScores.getEntities().size(); @@ -169,19 +243,19 @@ public final class TextLinks implements Parcelable { /** * Returns the entity type at a given index. Entity types are sorted by confidence. * - * @return the entity type at the provided index. + * @return the entity type at the provided index */ - @NonNull public @TextClassifier.EntityType String getEntity(int index) { + @NonNull public @EntityType String getEntity(int index) { return mEntityScores.getEntities().get(index); } /** * Returns the confidence score for a particular entity type. * - * @param entityType the entity type. + * @param entityType the entity type */ public @FloatRange(from = 0.0, to = 1.0) float getConfidenceScore( - @TextClassifier.EntityType String entityType) { + @EntityType String entityType) { return mEntityScores.getConfidenceScore(entityType); } @@ -193,7 +267,6 @@ public final class TextLinks implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { mEntityScores.writeToParcel(dest, flags); - dest.writeString(mOriginalText); dest.writeInt(mStart); dest.writeInt(mEnd); } @@ -213,7 +286,6 @@ public final class TextLinks implements Parcelable { private TextLink(Parcel in) { mEntityScores = EntityConfidence.CREATOR.createFromParcel(in); - mOriginalText = in.readString(); mStart = in.readInt(); mEnd = in.readInt(); } @@ -227,6 +299,32 @@ public final class TextLinks implements Parcelable { private LocaleList mDefaultLocales; private TextClassifier.EntityConfig mEntityConfig; + private @ApplyStrategy int mApplyStrategy; + private Function mSpanFactory; + + /** + * Returns a new options object based on the specified link mask. + */ + public static Options fromLinkMask(@LinkifyMask int mask) { + final TextClassifier.EntityConfig entityConfig = + new TextClassifier.EntityConfig(TextClassifier.ENTITY_PRESET_NONE); + + if ((mask & Linkify.WEB_URLS) != 0) { + entityConfig.includeEntities(TextClassifier.TYPE_URL); + } + if ((mask & Linkify.EMAIL_ADDRESSES) != 0) { + entityConfig.includeEntities(TextClassifier.TYPE_EMAIL); + } + if ((mask & Linkify.PHONE_NUMBERS) != 0) { + entityConfig.includeEntities(TextClassifier.TYPE_PHONE); + } + if ((mask & Linkify.MAP_ADDRESSES) != 0) { + entityConfig.includeEntities(TextClassifier.TYPE_ADDRESS); + } + + return new Options().setEntityConfig(entityConfig); + } + public Options() {} /** @@ -250,9 +348,34 @@ public final class TextLinks implements Parcelable { return this; } + /** + * Sets a strategy for resolving conflicts when applying generated links to text that + * already have links. + * + * @throws IllegalArgumentException if applyStrategy is not valid + * + * @see #APPLY_STRATEGY_IGNORE + * @see #APPLY_STRATEGY_REPLACE + */ + public Options setApplyStrategy(@ApplyStrategy int applyStrategy) { + checkValidApplyStrategy(applyStrategy); + mApplyStrategy = applyStrategy; + return this; + } + + /** + * Sets a factory for converting a TextLink to a TextLinkSpan. + * + *

    Note: This is not parceled over IPC. + */ + public Options setSpanFactory(@Nullable Function spanFactory) { + mSpanFactory = spanFactory; + return this; + } + /** * @return ordered list of locale preferences that can be used to disambiguate - * the provided text. + * the provided text */ @Nullable public LocaleList getDefaultLocales() { @@ -260,7 +383,7 @@ public final class TextLinks implements Parcelable { } /** - * @return The config representing the set of entities to look for. + * @return The config representing the set of entities to look for * @see #setEntityConfig(TextClassifier.EntityConfig) */ @Nullable @@ -268,6 +391,29 @@ public final class TextLinks implements Parcelable { return mEntityConfig; } + /** + * @return the strategy for resolving conflictswhen applying generated links to text that + * already have links + * + * @see #APPLY_STRATEGY_IGNORE + * @see #APPLY_STRATEGY_REPLACE + */ + @ApplyStrategy + public int getApplyStrategy() { + return mApplyStrategy; + } + + /** + * Returns a factory for converting a TextLink to a TextLinkSpan. + * + *

    Note: This is not parcelable and will always return null if read + * from a parcel + */ + @Nullable + public Function getSpanFactory() { + return mSpanFactory; + } + @Override public int describeContents() { return 0; @@ -283,6 +429,7 @@ public final class TextLinks implements Parcelable { if (mEntityConfig != null) { mEntityConfig.writeToParcel(dest, flags); } + dest.writeInt(mApplyStrategy); } public static final Parcelable.Creator CREATOR = @@ -305,39 +452,53 @@ public final class TextLinks implements Parcelable { if (in.readInt() > 0) { mEntityConfig = TextClassifier.EntityConfig.CREATOR.createFromParcel(in); } + mApplyStrategy = in.readInt(); } } /** * A function to create spans from TextLinks. + */ + private static final Function DEFAULT_SPAN_FACTORY = + textLink -> new TextLinkSpan(textLink); + + /** + * A ClickableSpan for a TextLink. * - * Applies only to TextViews. - * We can hide this until we are convinced we want it to be part of the public API. - * - * @hide + *

    Applies only to TextViews. */ - public static final Function DEFAULT_SPAN_FACTORY = - textLink -> new ClickableSpan() { - @Override - public void onClick(View widget) { - if (widget instanceof TextView) { - final TextView textView = (TextView) widget; - textView.requestActionMode(textLink); - } - } - }; + public static class TextLinkSpan extends ClickableSpan { + + private final TextLink mTextLink; + + public TextLinkSpan(@Nullable TextLink textLink) { + mTextLink = textLink; + } + + @Override + public void onClick(View widget) { + if (widget instanceof TextView) { + final TextView textView = (TextView) widget; + textView.requestActionMode(mTextLink); + } + } + + public final TextLink getTextLink() { + return mTextLink; + } + } /** * A builder to construct a TextLinks instance. */ public static final class Builder { private final String mFullText; - private final Collection mLinks; + private final ArrayList mLinks; /** * Create a new TextLinks.Builder. * - * @param fullText The full text that links will be added to. + * @param fullText The full text to annotate with links */ public Builder(@NonNull String fullText) { mFullText = Preconditions.checkNotNull(fullText); @@ -347,21 +508,40 @@ public final class TextLinks implements Parcelable { /** * Adds a TextLink. * - * @return this instance. + * @return this instance + * + * @throws IllegalArgumentException if entityScores is null or empty. + */ + public Builder addLink(int start, int end, Map entityScores) { + mLinks.add(new TextLink(start, end, entityScores)); + return this; + } + + /** + * Removes all {@link TextLink}s. */ - public Builder addLink(TextLink link) { - Preconditions.checkNotNull(link); - mLinks.add(link); + public Builder clearTextLinks() { + mLinks.clear(); return this; } /** * Constructs a TextLinks instance. * - * @return the constructed TextLinks. + * @return the constructed TextLinks */ public TextLinks build() { return new TextLinks(mFullText, mLinks); } } + + /** + * @throws IllegalArgumentException if the value is invalid + */ + private static void checkValidApplyStrategy(int applyStrategy) { + if (applyStrategy != APPLY_STRATEGY_IGNORE && applyStrategy != APPLY_STRATEGY_REPLACE) { + throw new IllegalArgumentException( + "Invalid apply strategy. See TextLinks.ApplyStrategy for options."); + } + } } diff --git a/core/java/android/view/textclassifier/TextSelection.aidl b/core/java/android/view/textclassifier/TextSelection.aidl new file mode 100644 index 0000000000000000000000000000000000000000..dab1aefa353278ddecab4f994d52be1f9cf8eacf --- /dev/null +++ b/core/java/android/view/textclassifier/TextSelection.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textclassifier; + +parcelable TextSelection; +parcelable TextSelection.Options; \ No newline at end of file diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java index 774d42db67a08c0a051a29027c56786eceb862e4..1c93be75a3a1c6af4bb30d568dbe91872e297c9c 100644 --- a/core/java/android/view/textclassifier/TextSelection.java +++ b/core/java/android/view/textclassifier/TextSelection.java @@ -34,7 +34,7 @@ import java.util.Map; /** * Information about where text selection should be. */ -public final class TextSelection { +public final class TextSelection implements Parcelable { private final int mStartIndex; private final int mEndIndex; @@ -112,22 +112,6 @@ public final class TextSelection { mStartIndex, mEndIndex, mEntityConfidence, mSignature); } - /** Helper for parceling via #ParcelableWrapper. */ - private void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mStartIndex); - dest.writeInt(mEndIndex); - mEntityConfidence.writeToParcel(dest, flags); - dest.writeString(mSignature); - } - - /** Helper for unparceling via #ParcelableWrapper. */ - private TextSelection(Parcel in) { - mStartIndex = in.readInt(); - mEndIndex = in.readInt(); - mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in); - mSignature = in.readString(); - } - /** * Builder used to build {@link TextSelection} objects. */ @@ -272,46 +256,36 @@ public final class TextSelection { } } - /** - * Parcelable wrapper for TextSelection objects. - * @hide - */ - public static final class ParcelableWrapper implements Parcelable { - - @NonNull private TextSelection mTextSelection; - - public ParcelableWrapper(@NonNull TextSelection textSelection) { - Preconditions.checkNotNull(textSelection); - mTextSelection = textSelection; - } - - @NonNull - public TextSelection getTextSelection() { - return mTextSelection; - } - - @Override - public int describeContents() { - return 0; - } + @Override + public int describeContents() { + return 0; + } - @Override - public void writeToParcel(Parcel dest, int flags) { - mTextSelection.writeToParcel(dest, flags); - } + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mStartIndex); + dest.writeInt(mEndIndex); + mEntityConfidence.writeToParcel(dest, flags); + dest.writeString(mSignature); + } - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public ParcelableWrapper createFromParcel(Parcel in) { - return new ParcelableWrapper(new TextSelection(in)); - } + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public TextSelection createFromParcel(Parcel in) { + return new TextSelection(in); + } - @Override - public ParcelableWrapper[] newArray(int size) { - return new ParcelableWrapper[size]; - } - }; + @Override + public TextSelection[] newArray(int size) { + return new TextSelection[size]; + } + }; + private TextSelection(Parcel in) { + mStartIndex = in.readInt(); + mEndIndex = in.readInt(); + mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in); + mSignature = in.readString(); } } diff --git a/core/java/android/view/textclassifier/logging/DefaultLogger.java b/core/java/android/view/textclassifier/logging/DefaultLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..6b848351cbf658fc21b6f038596c5d9a7428c74c --- /dev/null +++ b/core/java/android/view/textclassifier/logging/DefaultLogger.java @@ -0,0 +1,263 @@ +/* + * 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.view.textclassifier.logging; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.metrics.LogMaker; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.util.Preconditions; + +import java.util.Locale; +import java.util.Objects; + +/** + * Default Logger. + * Used internally by TextClassifierImpl. + * @hide + */ +public final class DefaultLogger extends Logger { + + private static final String LOG_TAG = "DefaultLogger"; + private static final String CLASSIFIER_ID = "androidtc"; + + private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START; + private static final int PREV_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_PREVIOUS; + private static final int INDEX = MetricsEvent.FIELD_SELECTION_SESSION_INDEX; + private static final int WIDGET_TYPE = MetricsEvent.FIELD_SELECTION_WIDGET_TYPE; + private static final int WIDGET_VERSION = MetricsEvent.FIELD_SELECTION_WIDGET_VERSION; + private static final int MODEL_NAME = MetricsEvent.FIELD_TEXTCLASSIFIER_MODEL; + private static final int ENTITY_TYPE = MetricsEvent.FIELD_SELECTION_ENTITY_TYPE; + private static final int SMART_START = MetricsEvent.FIELD_SELECTION_SMART_RANGE_START; + private static final int SMART_END = MetricsEvent.FIELD_SELECTION_SMART_RANGE_END; + private static final int EVENT_START = MetricsEvent.FIELD_SELECTION_RANGE_START; + private static final int EVENT_END = MetricsEvent.FIELD_SELECTION_RANGE_END; + private static final int SESSION_ID = MetricsEvent.FIELD_SELECTION_SESSION_ID; + + private static final String ZERO = "0"; + private static final String UNKNOWN = "unknown"; + + private final MetricsLogger mMetricsLogger; + + public DefaultLogger(@NonNull Config config) { + super(config); + mMetricsLogger = new MetricsLogger(); + } + + @VisibleForTesting + public DefaultLogger(@NonNull Config config, @NonNull MetricsLogger metricsLogger) { + super(config); + mMetricsLogger = Preconditions.checkNotNull(metricsLogger); + } + + @Override + public boolean isSmartSelection(@NonNull String signature) { + return CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature)); + } + + @Override + public void writeEvent(@NonNull SelectionEvent event) { + Preconditions.checkNotNull(event); + final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION) + .setType(getLogType(event)) + .setSubtype(MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL) + .setPackageName(event.getPackageName()) + .addTaggedData(START_EVENT_DELTA, event.getDurationSinceSessionStart()) + .addTaggedData(PREV_EVENT_DELTA, event.getDurationSincePreviousEvent()) + .addTaggedData(INDEX, event.getEventIndex()) + .addTaggedData(WIDGET_TYPE, event.getWidgetType()) + .addTaggedData(WIDGET_VERSION, event.getWidgetVersion()) + .addTaggedData(MODEL_NAME, SignatureParser.getModelName(event.getSignature())) + .addTaggedData(ENTITY_TYPE, event.getEntityType()) + .addTaggedData(SMART_START, event.getSmartStart()) + .addTaggedData(SMART_END, event.getSmartEnd()) + .addTaggedData(EVENT_START, event.getStart()) + .addTaggedData(EVENT_END, event.getEnd()) + .addTaggedData(SESSION_ID, event.getSessionId()); + mMetricsLogger.write(log); + debugLog(log); + } + + private static int getLogType(SelectionEvent event) { + switch (event.getEventType()) { + case SelectionEvent.ACTION_OVERTYPE: + return MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE; + case SelectionEvent.ACTION_COPY: + return MetricsEvent.ACTION_TEXT_SELECTION_COPY; + case SelectionEvent.ACTION_PASTE: + return MetricsEvent.ACTION_TEXT_SELECTION_PASTE; + case SelectionEvent.ACTION_CUT: + return MetricsEvent.ACTION_TEXT_SELECTION_CUT; + case SelectionEvent.ACTION_SHARE: + return MetricsEvent.ACTION_TEXT_SELECTION_SHARE; + case SelectionEvent.ACTION_SMART_SHARE: + return MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE; + case SelectionEvent.ACTION_DRAG: + return MetricsEvent.ACTION_TEXT_SELECTION_DRAG; + case SelectionEvent.ACTION_ABANDON: + return MetricsEvent.ACTION_TEXT_SELECTION_ABANDON; + case SelectionEvent.ACTION_OTHER: + return MetricsEvent.ACTION_TEXT_SELECTION_OTHER; + case SelectionEvent.ACTION_SELECT_ALL: + return MetricsEvent.ACTION_TEXT_SELECTION_SELECT_ALL; + case SelectionEvent.ACTION_RESET: + return MetricsEvent.ACTION_TEXT_SELECTION_RESET; + case SelectionEvent.EVENT_SELECTION_STARTED: + return MetricsEvent.ACTION_TEXT_SELECTION_START; + case SelectionEvent.EVENT_SELECTION_MODIFIED: + return MetricsEvent.ACTION_TEXT_SELECTION_MODIFY; + case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: + return MetricsEvent.ACTION_TEXT_SELECTION_SMART_SINGLE; + case SelectionEvent.EVENT_SMART_SELECTION_MULTI: + return MetricsEvent.ACTION_TEXT_SELECTION_SMART_MULTI; + case SelectionEvent.EVENT_AUTO_SELECTION: + return MetricsEvent.ACTION_TEXT_SELECTION_AUTO; + default: + return MetricsEvent.VIEW_UNKNOWN; + } + } + + private static String getLogTypeString(int logType) { + switch (logType) { + case MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE: + return "OVERTYPE"; + case MetricsEvent.ACTION_TEXT_SELECTION_COPY: + return "COPY"; + case MetricsEvent.ACTION_TEXT_SELECTION_PASTE: + return "PASTE"; + case MetricsEvent.ACTION_TEXT_SELECTION_CUT: + return "CUT"; + case MetricsEvent.ACTION_TEXT_SELECTION_SHARE: + return "SHARE"; + case MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE: + return "SMART_SHARE"; + case MetricsEvent.ACTION_TEXT_SELECTION_DRAG: + return "DRAG"; + case MetricsEvent.ACTION_TEXT_SELECTION_ABANDON: + return "ABANDON"; + case MetricsEvent.ACTION_TEXT_SELECTION_OTHER: + return "OTHER"; + case MetricsEvent.ACTION_TEXT_SELECTION_SELECT_ALL: + return "SELECT_ALL"; + case MetricsEvent.ACTION_TEXT_SELECTION_RESET: + return "RESET"; + case MetricsEvent.ACTION_TEXT_SELECTION_START: + return "SELECTION_STARTED"; + case MetricsEvent.ACTION_TEXT_SELECTION_MODIFY: + return "SELECTION_MODIFIED"; + case MetricsEvent.ACTION_TEXT_SELECTION_SMART_SINGLE: + return "SMART_SELECTION_SINGLE"; + case MetricsEvent.ACTION_TEXT_SELECTION_SMART_MULTI: + return "SMART_SELECTION_MULTI"; + case MetricsEvent.ACTION_TEXT_SELECTION_AUTO: + return "AUTO_SELECTION"; + default: + return UNKNOWN; + } + } + + private static void debugLog(LogMaker log) { + if (!DEBUG_LOG_ENABLED) return; + + final String widgetType = Objects.toString(log.getTaggedData(WIDGET_TYPE), UNKNOWN); + final String widgetVersion = Objects.toString(log.getTaggedData(WIDGET_VERSION), ""); + final String widget = widgetVersion.isEmpty() + ? widgetType : widgetType + "-" + widgetVersion; + final int index = Integer.parseInt(Objects.toString(log.getTaggedData(INDEX), ZERO)); + if (log.getType() == MetricsEvent.ACTION_TEXT_SELECTION_START) { + String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), ""); + sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1); + Log.d(LOG_TAG, String.format("New selection session: %s (%s)", widget, sessionId)); + } + + final String model = Objects.toString(log.getTaggedData(MODEL_NAME), UNKNOWN); + final String entity = Objects.toString(log.getTaggedData(ENTITY_TYPE), UNKNOWN); + final String type = getLogTypeString(log.getType()); + final int smartStart = Integer.parseInt( + Objects.toString(log.getTaggedData(SMART_START), ZERO)); + final int smartEnd = Integer.parseInt( + Objects.toString(log.getTaggedData(SMART_END), ZERO)); + final int eventStart = Integer.parseInt( + Objects.toString(log.getTaggedData(EVENT_START), ZERO)); + final int eventEnd = Integer.parseInt( + Objects.toString(log.getTaggedData(EVENT_END), ZERO)); + + Log.d(LOG_TAG, String.format("%2d: %s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", + index, type, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model)); + } + + /** + * Creates a signature string that may be used to tag TextClassifier results. + */ + public static String createSignature( + String text, int start, int end, Context context, int modelVersion, + @Nullable Locale locale) { + Preconditions.checkNotNull(text); + Preconditions.checkNotNull(context); + final String modelName = (locale != null) + ? String.format(Locale.US, "%s_v%d", locale.toLanguageTag(), modelVersion) + : ""; + final int hash = Objects.hash(text, start, end, context.getPackageName()); + return SignatureParser.createSignature(CLASSIFIER_ID, modelName, hash); + } + + /** + * Helper for creating and parsing signature strings for + * {@link android.view.textclassifier.TextClassifierImpl}. + */ + @VisibleForTesting + public static final class SignatureParser { + + static String createSignature(String classifierId, String modelName, int hash) { + return String.format(Locale.US, "%s|%s|%d", classifierId, modelName, hash); + } + + static String getClassifierId(String signature) { + Preconditions.checkNotNull(signature); + final int end = signature.indexOf("|"); + if (end >= 0) { + return signature.substring(0, end); + } + return ""; + } + + static String getModelName(String signature) { + Preconditions.checkNotNull(signature); + final int start = signature.indexOf("|"); + final int end = signature.indexOf("|", start); + if (start >= 0 && end >= start) { + return signature.substring(start, end); + } + return ""; + } + + static int getHash(String signature) { + Preconditions.checkNotNull(signature); + final int index1 = signature.indexOf("|"); + final int index2 = signature.indexOf("|", index1); + if (index2 > 0) { + return Integer.parseInt(signature.substring(index2)); + } + return 0; + } + } +} diff --git a/core/java/android/view/textclassifier/logging/Logger.java b/core/java/android/view/textclassifier/logging/Logger.java new file mode 100644 index 0000000000000000000000000000000000000000..40e4d8ce1a7726d96df20b75ead00c6ea85c7cce --- /dev/null +++ b/core/java/android/view/textclassifier/logging/Logger.java @@ -0,0 +1,429 @@ +/* + * 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.view.textclassifier.logging; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.StringDef; +import android.content.Context; +import android.util.Log; +import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextClassifier; +import android.view.textclassifier.TextSelection; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.text.BreakIterator; +import java.util.Locale; +import java.util.Objects; +import java.util.UUID; + +/** + * A helper for logging TextClassifier related events. + */ +public abstract class Logger { + + /** + * Use this to specify an indeterminate positive index. + */ + public static final int OUT_OF_BOUNDS = Integer.MAX_VALUE; + + /** + * Use this to specify an indeterminate negative index. + */ + public static final int OUT_OF_BOUNDS_NEGATIVE = Integer.MIN_VALUE; + + private static final String LOG_TAG = "Logger"; + /* package */ static final boolean DEBUG_LOG_ENABLED = true; + + private static final String NO_SIGNATURE = ""; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @StringDef({WIDGET_TEXTVIEW, WIDGET_WEBVIEW, WIDGET_EDITTEXT, + WIDGET_EDIT_WEBVIEW, WIDGET_CUSTOM_TEXTVIEW, WIDGET_CUSTOM_EDITTEXT, + WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW, WIDGET_UNKNOWN}) + public @interface WidgetType {} + + public static final String WIDGET_TEXTVIEW = "textview"; + public static final String WIDGET_EDITTEXT = "edittext"; + public static final String WIDGET_UNSELECTABLE_TEXTVIEW = "nosel-textview"; + public static final String WIDGET_WEBVIEW = "webview"; + public static final String WIDGET_EDIT_WEBVIEW = "edit-webview"; + public static final String WIDGET_CUSTOM_TEXTVIEW = "customview"; + public static final String WIDGET_CUSTOM_EDITTEXT = "customedit"; + public static final String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview"; + public static final String WIDGET_UNKNOWN = "unknown"; + + private SelectionEvent mPrevEvent; + private SelectionEvent mSmartEvent; + private SelectionEvent mStartEvent; + + /** + * Logger that does not log anything. + * @hide + */ + public static final Logger DISABLED = new Logger() { + @Override + public void writeEvent(SelectionEvent event) {} + }; + + @Nullable + private final Config mConfig; + + public Logger(Config config) { + mConfig = Preconditions.checkNotNull(config); + } + + private Logger() { + mConfig = null; + } + + /** + * Writes the selection event. + * + *

    NOTE: This method is designed for subclasses. + * Apps should not call it directly. + */ + public abstract void writeEvent(@NonNull SelectionEvent event); + + /** + * Returns true if the signature matches that of a smart selection event (i.e. + * {@link SelectionEvent#EVENT_SMART_SELECTION_SINGLE} or + * {@link SelectionEvent#EVENT_SMART_SELECTION_MULTI}). + * Returns false otherwise. + */ + public boolean isSmartSelection(@NonNull String signature) { + return false; + } + + + /** + * Returns a token iterator for tokenizing text for logging purposes. + */ + public BreakIterator getTokenIterator(@NonNull Locale locale) { + return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale)); + } + + /** + * Logs a "selection started" event. + * + * @param start the token index of the selected token + */ + public final void logSelectionStartedEvent(int start) { + if (mConfig == null) { + return; + } + + logEvent(new SelectionEvent( + start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED, + TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig)); + } + + /** + * Logs a "selection modified" event. + * Use when the user modifies the selection. + * + * @param start the start token (inclusive) index of the selection + * @param end the end token (exclusive) index of the selection + */ + public final void logSelectionModifiedEvent(int start, int end) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + + if (mConfig == null) { + return; + } + + logEvent(new SelectionEvent( + start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, + TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig)); + } + + /** + * Logs a "selection modified" event. + * Use when the user modifies the selection and the selection's entity type is known. + * + * @param start the start token (inclusive) index of the selection + * @param end the end token (exclusive) index of the selection + * @param classification the TextClassification object returned by the TextClassifier that + * classified the selected text + */ + public final void logSelectionModifiedEvent( + int start, int end, @NonNull TextClassification classification) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + Preconditions.checkNotNull(classification); + + if (mConfig == null) { + return; + } + + final String entityType = classification.getEntityCount() > 0 + ? classification.getEntity(0) + : TextClassifier.TYPE_UNKNOWN; + final String signature = classification.getSignature(); + logEvent(new SelectionEvent( + start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, + entityType, signature, mConfig)); + } + + /** + * Logs a "selection modified" event. + * Use when a TextClassifier modifies the selection. + * + * @param start the start token (inclusive) index of the selection + * @param end the end token (exclusive) index of the selection + * @param selection the TextSelection object returned by the TextClassifier for the + * specified selection + */ + public final void logSelectionModifiedEvent( + int start, int end, @NonNull TextSelection selection) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + Preconditions.checkNotNull(selection); + + if (mConfig == null) { + return; + } + + final int eventType; + if (isSmartSelection(selection.getSignature())) { + eventType = end - start > 1 + ? SelectionEvent.EVENT_SMART_SELECTION_MULTI + : SelectionEvent.EVENT_SMART_SELECTION_SINGLE; + + } else { + eventType = SelectionEvent.EVENT_AUTO_SELECTION; + } + final String entityType = selection.getEntityCount() > 0 + ? selection.getEntity(0) + : TextClassifier.TYPE_UNKNOWN; + final String signature = selection.getSignature(); + logEvent(new SelectionEvent(start, end, eventType, entityType, signature, mConfig)); + } + + /** + * Logs an event specifying an action taken on a selection. + * Use when the user clicks on an action to act on the selected text. + * + * @param start the start token (inclusive) index of the selection + * @param end the end token (exclusive) index of the selection + * @param actionType the action that was performed on the selection + */ + public final void logSelectionActionEvent( + int start, int end, @SelectionEvent.ActionType int actionType) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + checkActionType(actionType); + + if (mConfig == null) { + return; + } + + logEvent(new SelectionEvent( + start, end, actionType, TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig)); + } + + /** + * Logs an event specifying an action taken on a selection. + * Use when the user clicks on an action to act on the selected text and the selection's + * entity type is known. + * + * @param start the start token (inclusive) index of the selection + * @param end the end token (exclusive) index of the selection + * @param actionType the action that was performed on the selection + * @param classification the TextClassification object returned by the TextClassifier that + * classified the selected text + * + * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType + */ + public final void logSelectionActionEvent( + int start, int end, @SelectionEvent.ActionType int actionType, + @NonNull TextClassification classification) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + Preconditions.checkNotNull(classification); + checkActionType(actionType); + + if (mConfig == null) { + return; + } + + final String entityType = classification.getEntityCount() > 0 + ? classification.getEntity(0) + : TextClassifier.TYPE_UNKNOWN; + final String signature = classification.getSignature(); + logEvent(new SelectionEvent(start, end, actionType, entityType, signature, mConfig)); + } + + private void logEvent(@NonNull SelectionEvent event) { + Preconditions.checkNotNull(event); + + if (event.getEventType() != SelectionEvent.EVENT_SELECTION_STARTED + && mStartEvent == null) { + if (DEBUG_LOG_ENABLED) { + Log.d(LOG_TAG, "Selection session not yet started. Ignoring event"); + } + return; + } + + final long now = System.currentTimeMillis(); + switch (event.getEventType()) { + case SelectionEvent.EVENT_SELECTION_STARTED: + Preconditions.checkArgument(event.getAbsoluteEnd() == event.getAbsoluteStart() + 1); + event.setSessionId(startNewSession()); + mStartEvent = event; + break; + case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through + case SelectionEvent.EVENT_SMART_SELECTION_MULTI: + mSmartEvent = event; + break; + case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through + case SelectionEvent.EVENT_AUTO_SELECTION: + if (mPrevEvent != null + && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart() + && mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) { + // Selection did not change. Ignore event. + return; + } + } + + event.setEventTime(now); + if (mStartEvent != null) { + event.setSessionId(mStartEvent.getSessionId()) + .setDurationSinceSessionStart(now - mStartEvent.getEventTime()) + .setStart(event.getAbsoluteStart() - mStartEvent.getAbsoluteStart()) + .setEnd(event.getAbsoluteEnd() - mStartEvent.getAbsoluteStart()); + } + if (mSmartEvent != null) { + event.setSignature(mSmartEvent.getSignature()) + .setSmartStart(mSmartEvent.getAbsoluteStart() - mStartEvent.getAbsoluteStart()) + .setSmartEnd(mSmartEvent.getAbsoluteEnd() - mStartEvent.getAbsoluteStart()); + } + if (mPrevEvent != null) { + event.setDurationSincePreviousEvent(now - mPrevEvent.getEventTime()) + .setEventIndex(mPrevEvent.getEventIndex() + 1); + } + writeEvent(event); + mPrevEvent = event; + + if (event.isTerminal()) { + endSession(); + } + } + + private String startNewSession() { + endSession(); + return UUID.randomUUID().toString(); + } + + private void endSession() { + mPrevEvent = null; + mSmartEvent = null; + mStartEvent = null; + } + + /** + * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType} + */ + private static void checkActionType(@SelectionEvent.EventType int eventType) + throws IllegalArgumentException { + switch (eventType) { + case SelectionEvent.ACTION_OVERTYPE: // fall through + case SelectionEvent.ACTION_COPY: // fall through + case SelectionEvent.ACTION_PASTE: // fall through + case SelectionEvent.ACTION_CUT: // fall through + case SelectionEvent.ACTION_SHARE: // fall through + case SelectionEvent.ACTION_SMART_SHARE: // fall through + case SelectionEvent.ACTION_DRAG: // fall through + case SelectionEvent.ACTION_ABANDON: // fall through + case SelectionEvent.ACTION_SELECT_ALL: // fall through + case SelectionEvent.ACTION_RESET: // fall through + return; + default: + throw new IllegalArgumentException( + String.format(Locale.US, "%d is not an eventType", eventType)); + } + } + + + /** + * A Logger config. + */ + public static final class Config { + + private final String mPackageName; + private final String mWidgetType; + @Nullable private final String mWidgetVersion; + + /** + * @param context Context of the widget the logger logs for + * @param widgetType a name for the widget being logged for. e.g. + * {@link #WIDGET_TEXTVIEW} + * @param widgetVersion a string version info for the widget the logger logs for + */ + public Config( + @NonNull Context context, + @WidgetType String widgetType, + @Nullable String widgetVersion) { + mPackageName = Preconditions.checkNotNull(context).getPackageName(); + mWidgetType = widgetType; + mWidgetVersion = widgetVersion; + } + + /** + * Returns the package name of the application the logger logs for. + */ + public String getPackageName() { + return mPackageName; + } + + /** + * Returns the name for the widget being logged for. e.g. {@link #WIDGET_TEXTVIEW}. + */ + public String getWidgetType() { + return mWidgetType; + } + + /** + * Returns string version info for the logger. This is specific to the text classifier. + */ + @Nullable + public String getWidgetVersion() { + return mWidgetVersion; + } + + @Override + public int hashCode() { + return Objects.hash(mPackageName, mWidgetType, mWidgetVersion); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof Config)) { + return false; + } + + final Config other = (Config) obj; + return Objects.equals(mPackageName, other.mPackageName) + && Objects.equals(mWidgetType, other.mWidgetType) + && Objects.equals(mWidgetVersion, other.mWidgetType); + } + } +} diff --git a/core/java/android/view/textclassifier/logging/SelectionEvent.java b/core/java/android/view/textclassifier/logging/SelectionEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..f40b65571142f7127e4cbafce76c440e0d85c902 --- /dev/null +++ b/core/java/android/view/textclassifier/logging/SelectionEvent.java @@ -0,0 +1,337 @@ +/* + * 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.view.textclassifier.logging; + +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.view.textclassifier.TextClassifier.EntityType; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Locale; + +/** + * A selection event. + * Specify index parameters as word token indices. + */ +public final class SelectionEvent { + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT, + ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON, + ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET}) + // NOTE: ActionType values should not be lower than 100 to avoid colliding with the other + // EventTypes declared below. + public @interface ActionType { + /* + * Terminal event types range: [100,200). + * Non-terminal event types range: [200,300). + */ + } + + /** User typed over the selection. */ + public static final int ACTION_OVERTYPE = 100; + /** User copied the selection. */ + public static final int ACTION_COPY = 101; + /** User pasted over the selection. */ + public static final int ACTION_PASTE = 102; + /** User cut the selection. */ + public static final int ACTION_CUT = 103; + /** User shared the selection. */ + public static final int ACTION_SHARE = 104; + /** User clicked the textAssist menu item. */ + public static final int ACTION_SMART_SHARE = 105; + /** User dragged+dropped the selection. */ + public static final int ACTION_DRAG = 106; + /** User abandoned the selection. */ + public static final int ACTION_ABANDON = 107; + /** User performed an action on the selection. */ + public static final int ACTION_OTHER = 108; + + // Non-terminal actions. + /** User activated Select All */ + public static final int ACTION_SELECT_ALL = 200; + /** User reset the smart selection. */ + public static final int ACTION_RESET = 201; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT, + ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON, + ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET, + EVENT_SELECTION_STARTED, EVENT_SELECTION_MODIFIED, + EVENT_SMART_SELECTION_SINGLE, EVENT_SMART_SELECTION_MULTI, + EVENT_AUTO_SELECTION}) + // NOTE: EventTypes declared here must be less than 100 to avoid colliding with the + // ActionTypes declared above. + public @interface EventType { + /* + * Range: 1 -> 99. + */ + } + + /** User started a new selection. */ + public static final int EVENT_SELECTION_STARTED = 1; + /** User modified an existing selection. */ + public static final int EVENT_SELECTION_MODIFIED = 2; + /** Smart selection triggered for a single token (word). */ + public static final int EVENT_SMART_SELECTION_SINGLE = 3; + /** Smart selection triggered spanning multiple tokens (words). */ + public static final int EVENT_SMART_SELECTION_MULTI = 4; + /** Something else other than User or the default TextClassifier triggered a selection. */ + public static final int EVENT_AUTO_SELECTION = 5; + + private final int mAbsoluteStart; + private final int mAbsoluteEnd; + private final @EventType int mEventType; + private final @EntityType String mEntityType; + @Nullable private final String mWidgetVersion; + private final String mPackageName; + private final String mWidgetType; + + // These fields should only be set by creator of a SelectionEvent. + private String mSignature; + private long mEventTime; + private long mDurationSinceSessionStart; + private long mDurationSinceLastEvent; + private int mEventIndex; + private String mSessionId; + private int mStart; + private int mEnd; + private int mSmartStart; + private int mSmartEnd; + + SelectionEvent( + int start, int end, + @EventType int eventType, @EntityType String entityType, + String signature, Logger.Config config) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + mAbsoluteStart = start; + mAbsoluteEnd = end; + mEventType = eventType; + mEntityType = Preconditions.checkNotNull(entityType); + mSignature = Preconditions.checkNotNull(signature); + Preconditions.checkNotNull(config); + mWidgetVersion = config.getWidgetVersion(); + mPackageName = Preconditions.checkNotNull(config.getPackageName()); + mWidgetType = Preconditions.checkNotNull(config.getWidgetType()); + } + + int getAbsoluteStart() { + return mAbsoluteStart; + } + + int getAbsoluteEnd() { + return mAbsoluteEnd; + } + + /** + * Returns the type of event that was triggered. e.g. {@link #ACTION_COPY}. + */ + public int getEventType() { + return mEventType; + } + + /** + * Returns the type of entity that is associated with this event. e.g. + * {@link android.view.textclassifier.TextClassifier#TYPE_EMAIL}. + */ + @EntityType + public String getEntityType() { + return mEntityType; + } + + /** + * Returns the package name of the app that this event originated in. + */ + public String getPackageName() { + return mPackageName; + } + + /** + * Returns the type of widget that was involved in triggering this event. + */ + public String getWidgetType() { + return mWidgetType; + } + + /** + * Returns a string version info for the widget this event was triggered in. + */ + public String getWidgetVersion() { + return mWidgetVersion; + } + + /** + * Returns the signature of the text classifier result associated with this event. + */ + public String getSignature() { + return mSignature; + } + + SelectionEvent setSignature(String signature) { + mSignature = Preconditions.checkNotNull(signature); + return this; + } + + /** + * Returns the time this event was triggered. + */ + public long getEventTime() { + return mEventTime; + } + + SelectionEvent setEventTime(long timeMs) { + mEventTime = timeMs; + return this; + } + + /** + * Returns the duration in ms between when this event was triggered and when the first event in + * the selection session was triggered. + */ + public long getDurationSinceSessionStart() { + return mDurationSinceSessionStart; + } + + SelectionEvent setDurationSinceSessionStart(long durationMs) { + mDurationSinceSessionStart = durationMs; + return this; + } + + /** + * Returns the duration in ms between when this event was triggered and when the previous event + * in the selection session was triggered. + */ + public long getDurationSincePreviousEvent() { + return mDurationSinceLastEvent; + } + + SelectionEvent setDurationSincePreviousEvent(long durationMs) { + this.mDurationSinceLastEvent = durationMs; + return this; + } + + /** + * Returns the index (e.g. 1st event, 2nd event, etc.) of this event in the selection session. + */ + public int getEventIndex() { + return mEventIndex; + } + + SelectionEvent setEventIndex(int index) { + mEventIndex = index; + return this; + } + + /** + * Returns the selection session id. + */ + public String getSessionId() { + return mSessionId; + } + + SelectionEvent setSessionId(String id) { + mSessionId = id; + return this; + } + + /** + * Returns the start index of this events token relative to the index of the start selection + * event in the selection session. + */ + public int getStart() { + return mStart; + } + + SelectionEvent setStart(int start) { + mStart = start; + return this; + } + + /** + * Returns the end index of this events token relative to the index of the start selection + * event in the selection session. + */ + public int getEnd() { + return mEnd; + } + + SelectionEvent setEnd(int end) { + mEnd = end; + return this; + } + + /** + * Returns the start index of this events token relative to the index of the smart selection + * event in the selection session. + */ + public int getSmartStart() { + return mSmartStart; + } + + SelectionEvent setSmartStart(int start) { + this.mSmartStart = start; + return this; + } + + /** + * Returns the end index of this events token relative to the index of the smart selection + * event in the selection session. + */ + public int getSmartEnd() { + return mSmartEnd; + } + + SelectionEvent setSmartEnd(int end) { + mSmartEnd = end; + return this; + } + + boolean isTerminal() { + switch (mEventType) { + case ACTION_OVERTYPE: // fall through + case ACTION_COPY: // fall through + case ACTION_PASTE: // fall through + case ACTION_CUT: // fall through + case ACTION_SHARE: // fall through + case ACTION_SMART_SHARE: // fall through + case ACTION_DRAG: // fall through + case ACTION_ABANDON: // fall through + case ACTION_OTHER: // fall through + return true; + default: + return false; + } + } + + @Override + public String toString() { + return String.format(Locale.US, + "SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, " + + "widgetVersion=%s, packageName=%s, widgetType=%s, signature=%s, " + + "eventTime=%d, durationSinceSessionStart=%d, durationSinceLastEvent=%d, " + + "eventIndex=%d, sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}", + mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType, + mWidgetVersion, mPackageName, mWidgetType, mSignature, + mEventTime, mDurationSinceSessionStart, mDurationSinceLastEvent, + mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd); + } +} diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index d2cb70e027c1fc920dc16a2c220cc42648b31cf0..65deb3b8557278f1284fae356ca761c68db4c482 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2106,6 +2106,18 @@ public class WebView extends AbsoluteLayout * the default directory, and other processes must call this API to define * a unique suffix. *

    + * This means that different processes in the same application cannot directly + * share WebView-related data, since the data directories must be distinct. + * Applications that use this API may have to explicitly pass data between + * processes. For example, login cookies may have to be copied from one + * process's cookie jar to the other using {@link CookieManager} if both + * processes' WebViews are intended to be logged in. + *

    + * Most applications should simply ensure that all components of the app + * that rely on WebView are in the same process, to avoid needing multiple + * data directories. The {@link #disableWebView} method can be used to ensure + * that the other processes do not use WebView by accident in this case. + *

    * This API must be called before any instances of WebView are created in * this process and before any other methods in the android.webkit package * are called by this process. @@ -2126,10 +2138,14 @@ public class WebView extends AbsoluteLayout * methods in the android.webkit package are used. *

    * Applications with multiple processes may wish to call this in processes - * which are not intended to use WebView to prevent potential data directory - * conflicts (see {@link #setDataDirectorySuffix}) and to avoid accidentally - * incurring the memory usage of initializing WebView in long-lived - * processes which have no need for it. + * that are not intended to use WebView to avoid accidentally incurring + * the memory usage of initializing WebView in long-lived processes that + * have no need for it, and to prevent potential data directory conflicts + * (see {@link #setDataDirectorySuffix}). + *

    + * For example, an audio player application with one process for its + * activities and another process for its playback service may wish to call + * this method in the playback service's {@link android.app.Service#onCreate}. * * @throws IllegalStateException if WebView has already been initialized * in the current process. diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 7bb0db1cf9109f610f81ad9792714a24b37c404e..5ab579df5ed6e9af9a9846f947d82e4c788cf7e4 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1745,16 +1745,19 @@ public class Editor { highlight = null; } + if (mSelectionActionModeHelper != null) { + mSelectionActionModeHelper.onDraw(canvas); + if (mSelectionActionModeHelper.isDrawingHighlight()) { + highlight = null; + } + } + if (mTextView.canHaveDisplayList() && canvas.isHardwareAccelerated()) { drawHardwareAccelerated(canvas, layout, highlight, highlightPaint, cursorOffsetVertical); } else { layout.draw(canvas, highlight, highlightPaint, cursorOffsetVertical); } - - if (mSelectionActionModeHelper != null) { - mSelectionActionModeHelper.onDraw(canvas); - } } private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highlight, diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 1dc5b44bed4fe7dfe2857d442e0241ec0ed5d5ae..4b951fa1824e7e8e36b8850dc14e092f588c1923 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -23,10 +23,12 @@ import android.annotation.TestApi; import android.content.ContentResolver; import android.content.Context; import android.content.res.ColorStateList; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.ImageDecoder; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.PorterDuff; @@ -53,7 +55,6 @@ import android.widget.RemoteViews.RemoteView; import com.android.internal.R; import java.io.IOException; -import java.io.InputStream; /** * Displays image resources, for example {@link android.graphics.Bitmap} @@ -946,21 +947,15 @@ public class ImageView extends View { } } else if (ContentResolver.SCHEME_CONTENT.equals(scheme) || ContentResolver.SCHEME_FILE.equals(scheme)) { - InputStream stream = null; try { - stream = mContext.getContentResolver().openInputStream(uri); - return Drawable.createFromResourceStream(sCompatUseCorrectStreamDensity - ? getResources() : null, null, stream, null); - } catch (Exception e) { + Resources res = sCompatUseCorrectStreamDensity ? getResources() : null; + ImageDecoder.Source src = ImageDecoder.createSource(mContext.getContentResolver(), + uri, res); + return ImageDecoder.decodeDrawable(src, (decoder, info, s) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); + } catch (IOException e) { Log.w(LOG_TAG, "Unable to open content: " + uri, e); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - Log.w(LOG_TAG, "Unable to close content: " + uri, e); - } - } } } else { return Drawable.createFromPath(uri.toString()); diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index e42217f710c4126a6818870d73535303a9d9af04..7a4c800ba15edde7ce133742fbbc8bbeff6a6001 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -182,8 +182,6 @@ public final class Magnifier { /** * Forces the magnifier to update its content. It uses the previous coordinates passed to * {@link #show(float, float)}. This only happens if the magnifier is currently showing. - * - * @hide */ public void update() { if (mWindow.isShowing()) { diff --git a/core/java/android/widget/MediaControlView2.java b/core/java/android/widget/MediaControlView2.java index a4da05f8b982837b03f1459d1f11de4099ddb633..7d556bf450b4350be1934a90882e12d4b6f441b5 100644 --- a/core/java/android/widget/MediaControlView2.java +++ b/core/java/android/widget/MediaControlView2.java @@ -23,12 +23,12 @@ import android.content.Context; import android.media.session.MediaController; import android.media.update.ApiLoader; import android.media.update.MediaControlView2Provider; -import android.media.update.ViewProvider; +import android.media.update.ViewGroupHelper; import android.util.AttributeSet; -import android.view.MotionEvent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; + /** * A View that contains the controls for MediaPlayer2. * It provides a wide range of UI including buttons such as "Play/Pause", "Rewind", "Fast Forward", @@ -45,10 +45,22 @@ import java.lang.annotation.RetentionPolicy; * developer needs to manually retrieve a MediaController instance and set it to MediaControlView2 * by calling setController(MediaController controller). * + *

    + * There is no separate method that handles the show/hide behavior for MediaControlView2. Instead, + * one can directly change the visibility of this view by calling View.setVisibility(int). The + * values supported are View.VISIBLE and View.GONE. + * In addition, the following customization is supported: + * Set focus to the play/pause button by calling requestPlayButtonFocus(). + * + *

    + * It is also possible to add custom buttons with custom icons and actions inside MediaControlView2. + * Those buttons will be shown when the overflow button is clicked. + * See {@link VideoView2#setCustomActions} for more details on how to add. + * * TODO PUBLIC API * @hide */ -public class MediaControlView2 extends FrameLayout { +public class MediaControlView2 extends ViewGroupHelper { /** @hide */ @IntDef({ BUTTON_PLAY_PAUSE, @@ -127,8 +139,6 @@ public class MediaControlView2 extends FrameLayout { */ public static final String COMMAND_SET_FULLSCREEN = "setFullscreen"; - private final MediaControlView2Provider mProvider; - public MediaControlView2(@NonNull Context context) { this(context, null); } @@ -144,17 +154,12 @@ public class MediaControlView2 extends FrameLayout { public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - - mProvider = ApiLoader.getProvider(context) - .createMediaControlView2(this, new SuperProvider()); - } - - /** - * @hide - */ - public MediaControlView2Provider getProvider() { - return mProvider; + super((instance, superProvider, privateProvider) -> + ApiLoader.getProvider(context).createMediaControlView2( + (MediaControlView2) instance, superProvider, privateProvider, + attrs, defStyleAttr, defStyleRes), + context, attrs, defStyleAttr, defStyleRes); + mProvider.initialize(attrs, defStyleAttr, defStyleRes); } /** @@ -164,36 +169,6 @@ public class MediaControlView2 extends FrameLayout { mProvider.setController_impl(controller); } - /** - * Shows the control view on screen. It will disappear automatically after 3 seconds of - * inactivity. - */ - public void show() { - mProvider.show_impl(); - } - - /** - * Shows the control view on screen. It will disappear automatically after {@code timeout} - * milliseconds of inactivity. - */ - public void show(long timeout) { - mProvider.show_impl(timeout); - } - - /** - * Returns whether the control view is currently shown or hidden. - */ - public boolean isShowing() { - return mProvider.isShowing_impl(); - } - - /** - * Hide the control view from the screen. - */ - public void hide() { - mProvider.hide_impl(); - } - /** * Changes the visibility state of an individual button. Default value is View.Visible. * @@ -217,75 +192,15 @@ public class MediaControlView2 extends FrameLayout { mProvider.setButtonVisibility_impl(button, visibility); } - @Override - protected void onAttachedToWindow() { - mProvider.onAttachedToWindow_impl(); - } - - @Override - protected void onDetachedFromWindow() { - mProvider.onDetachedFromWindow_impl(); - } - - @Override - public CharSequence getAccessibilityClassName() { - return mProvider.getAccessibilityClassName_impl(); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - return mProvider.onTouchEvent_impl(ev); - } - - @Override - public boolean onTrackballEvent(MotionEvent ev) { - return mProvider.onTrackballEvent_impl(ev); - } - - @Override - public void onFinishInflate() { - mProvider.onFinishInflate_impl(); + /** + * Requests focus for the play/pause button. + */ + public void requestPlayButtonFocus() { + mProvider.requestPlayButtonFocus_impl(); } @Override - public void setEnabled(boolean enabled) { - mProvider.setEnabled_impl(enabled); - } - - private class SuperProvider implements ViewProvider { - @Override - public void onAttachedToWindow_impl() { - MediaControlView2.super.onAttachedToWindow(); - } - - @Override - public void onDetachedFromWindow_impl() { - MediaControlView2.super.onDetachedFromWindow(); - } - - @Override - public CharSequence getAccessibilityClassName_impl() { - return MediaControlView2.super.getAccessibilityClassName(); - } - - @Override - public boolean onTouchEvent_impl(MotionEvent ev) { - return MediaControlView2.super.onTouchEvent(ev); - } - - @Override - public boolean onTrackballEvent_impl(MotionEvent ev) { - return MediaControlView2.super.onTrackballEvent(ev); - } - - @Override - public void onFinishInflate_impl() { - MediaControlView2.super.onFinishInflate(); - } - - @Override - public void setEnabled_impl(boolean enabled) { - MediaControlView2.super.setEnabled(enabled); - } + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mProvider.onLayout_impl(changed, l, t, r, b); } } diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 3bfa520cd9425318cfc77206893233531c0b7cc7..e7a4c0246e1f7fef9c277a83f858c0ad19c2b2d2 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -37,8 +37,8 @@ import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import android.view.textclassifier.TextSelection; -import android.view.textclassifier.logging.SmartSelectionEventTracker; -import android.view.textclassifier.logging.SmartSelectionEventTracker.SelectionEvent; +import android.view.textclassifier.logging.Logger; +import android.view.textclassifier.logging.SelectionEvent; import android.widget.Editor.SelectionModifierCursorController; import com.android.internal.annotations.VisibleForTesting; @@ -65,6 +65,7 @@ public final class SelectionActionModeHelper { private static final String LOG_TAG = "SelectActionModeHelper"; + // TODO: Make this a configurable flag. private static final boolean SMART_SELECT_ANIMATION_ENABLED = true; private final Editor mEditor; @@ -92,7 +93,7 @@ public final class SelectionActionModeHelper { if (SMART_SELECT_ANIMATION_ENABLED) { mSmartSelectSprite = new SmartSelectSprite(mTextView.getContext(), - mTextView::invalidate); + editor.getTextView().mHighlightColor, mTextView::invalidate); } else { mSmartSelectSprite = null; } @@ -172,7 +173,7 @@ public final class SelectionActionModeHelper { public void onSelectionDrag() { mSelectionTracker.onSelectionAction( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), - SelectionEvent.ActionType.DRAG, mTextClassification); + SelectionEvent.ACTION_DRAG, mTextClassification); } public void onTextChanged(int start, int end) { @@ -199,11 +200,15 @@ public final class SelectionActionModeHelper { } public void onDraw(final Canvas canvas) { - if (mSmartSelectSprite != null) { + if (isDrawingHighlight() && mSmartSelectSprite != null) { mSmartSelectSprite.draw(canvas); } } + public boolean isDrawingHighlight() { + return mSmartSelectSprite != null && mSmartSelectSprite.isAnimationActive(); + } + private void cancelAsyncTask() { if (mTextClassificationAsyncTask != null) { mTextClassificationAsyncTask.cancel(true); @@ -574,7 +579,7 @@ public final class SelectionActionModeHelper { mSelectionEnd = editor.getTextView().getSelectionEnd(); mLogger.logSelectionAction( textView.getSelectionStart(), textView.getSelectionEnd(), - SelectionEvent.ActionType.RESET, null /* classification */); + SelectionEvent.ACTION_RESET, null /* classification */); } return selected; } @@ -583,7 +588,7 @@ public final class SelectionActionModeHelper { public void onTextChanged(int start, int end, TextClassification classification) { if (isSelectionStarted() && start == mSelectionStart && end == mSelectionEnd) { - onSelectionAction(start, end, SelectionEvent.ActionType.OVERTYPE, classification); + onSelectionAction(start, end, SelectionEvent.ACTION_OVERTYPE, classification); } } @@ -622,7 +627,7 @@ public final class SelectionActionModeHelper { if (mIsPending) { mLogger.logSelectionAction( mSelectionStart, mSelectionEnd, - SelectionEvent.ActionType.ABANDON, null /* classification */); + SelectionEvent.ACTION_ABANDON, null /* classification */); mSelectionStart = mSelectionEnd = -1; mIsPending = false; } @@ -649,22 +654,29 @@ public final class SelectionActionModeHelper { private static final String LOG_TAG = "SelectionMetricsLogger"; private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+"); - private final SmartSelectionEventTracker mDelegate; + private final Logger mLogger; private final boolean mEditTextLogger; - private final BreakIterator mWordIterator; + private final BreakIterator mTokenIterator; private int mStartIndex; private String mText; SelectionMetricsLogger(TextView textView) { Preconditions.checkNotNull(textView); - final @SmartSelectionEventTracker.WidgetType int widgetType = textView.isTextEditable() - ? SmartSelectionEventTracker.WidgetType.EDITTEXT - : (textView.isTextSelectable() - ? SmartSelectionEventTracker.WidgetType.TEXTVIEW - : SmartSelectionEventTracker.WidgetType.UNSELECTABLE_TEXTVIEW); - mDelegate = new SmartSelectionEventTracker(textView.getContext(), widgetType); + mLogger = textView.getTextClassifier().getLogger( + new Logger.Config(textView.getContext(), getWidetType(textView), null)); mEditTextLogger = textView.isTextEditable(); - mWordIterator = BreakIterator.getWordInstance(textView.getTextLocale()); + mTokenIterator = mLogger.getTokenIterator(textView.getTextLocale()); + } + + @Logger.WidgetType + private static String getWidetType(TextView textView) { + if (textView.isTextEditable()) { + return Logger.WIDGET_EDITTEXT; + } + if (textView.isTextSelectable()) { + return Logger.WIDGET_TEXTVIEW; + } + return Logger.WIDGET_UNSELECTABLE_TEXTVIEW; } public void logSelectionStarted(CharSequence text, int index) { @@ -674,9 +686,9 @@ public final class SelectionActionModeHelper { if (mText == null || !mText.contentEquals(text)) { mText = text.toString(); } - mWordIterator.setText(mText); + mTokenIterator.setText(mText); mStartIndex = index; - mDelegate.logEvent(SelectionEvent.selectionStarted(0)); + mLogger.logSelectionStartedEvent(0); } catch (Exception e) { // Avoid crashes due to logging. Log.d(LOG_TAG, e.getMessage()); @@ -690,14 +702,14 @@ public final class SelectionActionModeHelper { Preconditions.checkArgumentInRange(end, start, mText.length(), "end"); int[] wordIndices = getWordDelta(start, end); if (selection != null) { - mDelegate.logEvent(SelectionEvent.selectionModified( - wordIndices[0], wordIndices[1], selection)); + mLogger.logSelectionModifiedEvent( + wordIndices[0], wordIndices[1], selection); } else if (classification != null) { - mDelegate.logEvent(SelectionEvent.selectionModified( - wordIndices[0], wordIndices[1], classification)); + mLogger.logSelectionModifiedEvent( + wordIndices[0], wordIndices[1], classification); } else { - mDelegate.logEvent(SelectionEvent.selectionModified( - wordIndices[0], wordIndices[1])); + mLogger.logSelectionModifiedEvent( + wordIndices[0], wordIndices[1]); } } catch (Exception e) { // Avoid crashes due to logging. @@ -714,11 +726,11 @@ public final class SelectionActionModeHelper { Preconditions.checkArgumentInRange(end, start, mText.length(), "end"); int[] wordIndices = getWordDelta(start, end); if (classification != null) { - mDelegate.logEvent(SelectionEvent.selectionAction( - wordIndices[0], wordIndices[1], action, classification)); + mLogger.logSelectionActionEvent( + wordIndices[0], wordIndices[1], action, classification); } else { - mDelegate.logEvent(SelectionEvent.selectionAction( - wordIndices[0], wordIndices[1], action)); + mLogger.logSelectionActionEvent( + wordIndices[0], wordIndices[1], action); } } catch (Exception e) { // Avoid crashes due to logging. @@ -741,10 +753,10 @@ public final class SelectionActionModeHelper { wordIndices[0] = countWordsBackward(start); // For the selection start index, avoid counting a partial word backwards. - if (!mWordIterator.isBoundary(start) + if (!mTokenIterator.isBoundary(start) && !isWhitespace( - mWordIterator.preceding(start), - mWordIterator.following(start))) { + mTokenIterator.preceding(start), + mTokenIterator.following(start))) { // We counted a partial word. Remove it. wordIndices[0]--; } @@ -766,7 +778,7 @@ public final class SelectionActionModeHelper { int wordCount = 0; int offset = from; while (offset > mStartIndex) { - int start = mWordIterator.preceding(offset); + int start = mTokenIterator.preceding(offset); if (!isWhitespace(start, offset)) { wordCount++; } @@ -780,7 +792,7 @@ public final class SelectionActionModeHelper { int wordCount = 0; int offset = from; while (offset < mStartIndex) { - int end = mWordIterator.following(offset); + int end = mTokenIterator.following(offset); if (!isWhitespace(offset, end)) { wordCount++; } @@ -1021,20 +1033,20 @@ public final class SelectionActionModeHelper { private static int getActionType(int menuItemId) { switch (menuItemId) { case TextView.ID_SELECT_ALL: - return SelectionEvent.ActionType.SELECT_ALL; + return SelectionEvent.ACTION_SELECT_ALL; case TextView.ID_CUT: - return SelectionEvent.ActionType.CUT; + return SelectionEvent.ACTION_CUT; case TextView.ID_COPY: - return SelectionEvent.ActionType.COPY; + return SelectionEvent.ACTION_COPY; case TextView.ID_PASTE: // fall through case TextView.ID_PASTE_AS_PLAIN_TEXT: - return SelectionEvent.ActionType.PASTE; + return SelectionEvent.ACTION_PASTE; case TextView.ID_SHARE: - return SelectionEvent.ActionType.SHARE; + return SelectionEvent.ACTION_SHARE; case TextView.ID_ASSIST: - return SelectionEvent.ActionType.SMART_SHARE; + return SelectionEvent.ACTION_SMART_SHARE; default: - return SelectionEvent.ActionType.OTHER; + return SelectionEvent.ACTION_OTHER; } } diff --git a/core/java/android/widget/SmartSelectSprite.java b/core/java/android/widget/SmartSelectSprite.java index a391c6ee8ec352b7bba7a95042c5ac9534361ef1..9a84f69d120a9dd49eb8c7c3ad30ff136f8b0137 100644 --- a/core/java/android/widget/SmartSelectSprite.java +++ b/core/java/android/widget/SmartSelectSprite.java @@ -26,7 +26,6 @@ import android.annotation.ColorInt; import android.annotation.FloatRange; import android.annotation.IntDef; import android.content.Context; -import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; @@ -36,7 +35,6 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.Shape; import android.text.Layout; -import android.util.TypedValue; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -54,21 +52,15 @@ import java.util.List; final class SmartSelectSprite { private static final int EXPAND_DURATION = 300; - private static final int CORNER_DURATION = 150; - private static final float STROKE_WIDTH_DP = 1.5F; - - // GBLUE700 - @ColorInt - private static final int DEFAULT_STROKE_COLOR = 0xFF3367D6; + private static final int CORNER_DURATION = 50; private final Interpolator mExpandInterpolator; private final Interpolator mCornerInterpolator; - private final float mStrokeWidth; private Animator mActiveAnimator = null; private final Runnable mInvalidator; @ColorInt - private final int mStrokeColor; + private final int mFillColor; static final Comparator RECTANGLE_COMPARATOR = Comparator .comparingDouble(e -> e.bottom) @@ -124,26 +116,11 @@ final class SmartSelectSprite { return expansionDirection * -1; } - @Retention(SOURCE) - @IntDef({RectangleBorderType.FIT, RectangleBorderType.OVERSHOOT}) - private @interface RectangleBorderType { - /** A rectangle which, fully expanded, fits inside of its bounding rectangle. */ - int FIT = 0; - /** - * A rectangle which, when fully expanded, clips outside of its bounding rectangle so that - * its edges no longer appear rounded. - */ - int OVERSHOOT = 1; - } - - private final float mStrokeWidth; private final RectF mBoundingRectangle; private float mRoundRatio = 1.0f; private final @ExpansionDirection int mExpansionDirection; - private final @RectangleBorderType int mRectangleBorderType; private final RectF mDrawRect = new RectF(); - private final RectF mClipRect = new RectF(); private final Path mClipPath = new Path(); /** How offset the left edge of the rectangle is from the left side of the bounding box. */ @@ -159,13 +136,9 @@ final class SmartSelectSprite { private RoundedRectangleShape( final RectF boundingRectangle, final @ExpansionDirection int expansionDirection, - final @RectangleBorderType int rectangleBorderType, - final boolean inverted, - final float strokeWidth) { + final boolean inverted) { mBoundingRectangle = new RectF(boundingRectangle); mBoundingWidth = boundingRectangle.width(); - mRectangleBorderType = rectangleBorderType; - mStrokeWidth = strokeWidth; mInverted = inverted && expansionDirection != ExpansionDirection.CENTER; if (inverted) { @@ -182,14 +155,8 @@ final class SmartSelectSprite { } /* - * In order to achieve the "rounded rectangle hits the wall" effect, the drawing needs to be - * done in two passes. In this context, the wall is the bounding rectangle and in the first - * pass we need to draw the rounded rectangle (expanded and with a corner radius as per - * object properties) clipped by the bounding box. If the rounded rectangle expands outside - * of the bounding box, one more pass needs to be done, as there will now be a hole in the - * rounded rectangle where it "flattened" against the bounding box. In order to fill just - * this hole, we need to draw the bounding box, but clip it with the rounded rectangle and - * this will connect the missing pieces. + * In order to achieve the "rounded rectangle hits the wall" effect, we draw an expanding + * rounded rectangle that is clipped by the bounding box of the selected text. */ @Override public void draw(Canvas canvas, Paint paint) { @@ -201,31 +168,8 @@ final class SmartSelectSprite { final float adjustedCornerRadius = getAdjustedCornerRadius(); mDrawRect.set(mBoundingRectangle); - mDrawRect.left = mBoundingRectangle.left + mLeftBoundary; - mDrawRect.right = mBoundingRectangle.left + mRightBoundary; - - if (mRectangleBorderType == RectangleBorderType.OVERSHOOT) { - mDrawRect.left -= cornerRadius / 2; - mDrawRect.right += cornerRadius / 2; - } else { - switch (mExpansionDirection) { - case ExpansionDirection.CENTER: - break; - case ExpansionDirection.LEFT: - mDrawRect.right += cornerRadius; - break; - case ExpansionDirection.RIGHT: - mDrawRect.left -= cornerRadius; - break; - } - } - - canvas.save(); - mClipRect.set(mBoundingRectangle); - mClipRect.inset(-mStrokeWidth / 2, -mStrokeWidth / 2); - canvas.clipRect(mClipRect); - canvas.drawRoundRect(mDrawRect, adjustedCornerRadius, adjustedCornerRadius, paint); - canvas.restore(); + mDrawRect.left = mBoundingRectangle.left + mLeftBoundary - cornerRadius / 2; + mDrawRect.right = mBoundingRectangle.left + mRightBoundary + cornerRadius / 2; canvas.save(); mClipPath.reset(); @@ -272,11 +216,7 @@ final class SmartSelectSprite { } private float getBoundingWidth() { - if (mRectangleBorderType == RectangleBorderType.OVERSHOOT) { - return (int) (mBoundingRectangle.width() + getCornerRadius()); - } else { - return mBoundingRectangle.width(); - } + return (int) (mBoundingRectangle.width() + getCornerRadius()); } } @@ -388,19 +328,20 @@ final class SmartSelectSprite { } /** - * @param context the {@link Context} in which the animation will run + * @param context the {@link Context} in which the animation will run + * @param highlightColor the highlight color of the underlying {@link TextView} * @param invalidator a {@link Runnable} which will be called every time the animation updates, * indicating that the view drawing the animation should invalidate itself */ - SmartSelectSprite(final Context context, final Runnable invalidator) { + SmartSelectSprite(final Context context, @ColorInt int highlightColor, + final Runnable invalidator) { mExpandInterpolator = AnimationUtils.loadInterpolator( context, android.R.interpolator.fast_out_slow_in); mCornerInterpolator = AnimationUtils.loadInterpolator( context, android.R.interpolator.fast_out_linear_in); - mStrokeWidth = dpToPixel(context, STROKE_WIDTH_DP); - mStrokeColor = getStrokeColor(context); + mFillColor = highlightColor; mInvalidator = Preconditions.checkNotNull(invalidator); } @@ -437,17 +378,14 @@ final class SmartSelectSprite { RectangleWithTextSelectionLayout centerRectangle = null; int startingOffset = 0; - int startingRectangleIndex = 0; - for (int index = 0; index < rectangleCount; ++index) { - final RectangleWithTextSelectionLayout rectangleWithTextSelectionLayout = - destinationRectangles.get(index); + for (RectangleWithTextSelectionLayout rectangleWithTextSelectionLayout : + destinationRectangles) { final RectF rectangle = rectangleWithTextSelectionLayout.getRectangle(); if (contains(rectangle, start)) { centerRectangle = rectangleWithTextSelectionLayout; break; } startingOffset += rectangle.width(); - ++startingRectangleIndex; } if (centerRectangle == null) { @@ -459,9 +397,6 @@ final class SmartSelectSprite { final @RoundedRectangleShape.ExpansionDirection int[] expansionDirections = generateDirections(centerRectangle, destinationRectangles); - final @RoundedRectangleShape.RectangleBorderType int[] rectangleBorderTypes = - generateBorderTypes(rectangleCount); - for (int index = 0; index < rectangleCount; ++index) { final RectangleWithTextSelectionLayout rectangleWithTextSelectionLayout = destinationRectangles.get(index); @@ -469,10 +404,8 @@ final class SmartSelectSprite { final RoundedRectangleShape shape = new RoundedRectangleShape( rectangle, expansionDirections[index], - rectangleBorderTypes[index], rectangleWithTextSelectionLayout.getTextSelectionLayout() - == Layout.TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT, - mStrokeWidth); + == Layout.TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT); cornerAnimators.add(createCornerAnimator(shape, updateListener)); shapes.add(shape); } @@ -480,44 +413,23 @@ final class SmartSelectSprite { final RectangleList rectangleList = new RectangleList(shapes); final ShapeDrawable shapeDrawable = new ShapeDrawable(rectangleList); - final float startingOffsetLeft; - final float startingOffsetRight; - - final RoundedRectangleShape startingRectangleShape = shapes.get(startingRectangleIndex); - final float cornerRadius = startingRectangleShape.getCornerRadius(); - if (startingRectangleShape.mRectangleBorderType - == RoundedRectangleShape.RectangleBorderType.FIT) { - switch (startingRectangleShape.mExpansionDirection) { - case RoundedRectangleShape.ExpansionDirection.LEFT: - startingOffsetLeft = startingOffsetRight = startingOffset - cornerRadius / 2; - break; - case RoundedRectangleShape.ExpansionDirection.RIGHT: - startingOffsetLeft = startingOffsetRight = startingOffset + cornerRadius / 2; - break; - case RoundedRectangleShape.ExpansionDirection.CENTER: // fall through - default: - startingOffsetLeft = startingOffset - cornerRadius / 2; - startingOffsetRight = startingOffset + cornerRadius / 2; - break; - } - } else { - startingOffsetLeft = startingOffsetRight = startingOffset; - } - final Paint paint = shapeDrawable.getPaint(); - paint.setColor(mStrokeColor); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(mStrokeWidth); + paint.setColor(mFillColor); + paint.setStyle(Paint.Style.FILL); mExistingRectangleList = rectangleList; mExistingDrawable = shapeDrawable; - mActiveAnimator = createAnimator(rectangleList, startingOffsetLeft, startingOffsetRight, - cornerAnimators, updateListener, - onAnimationEnd); + mActiveAnimator = createAnimator(rectangleList, startingOffset, startingOffset, + cornerAnimators, updateListener, onAnimationEnd); mActiveAnimator.start(); } + /** Returns whether the sprite is currently animating. */ + public boolean isAnimationActive() { + return mActiveAnimator != null && mActiveAnimator.isRunning(); + } + private Animator createAnimator( final RectangleList rectangleList, final float startingOffsetLeft, @@ -625,36 +537,6 @@ final class SmartSelectSprite { return result; } - private static @RoundedRectangleShape.RectangleBorderType int[] generateBorderTypes( - final int numberOfRectangles) { - final @RoundedRectangleShape.RectangleBorderType int[] result = new int[numberOfRectangles]; - - for (int i = 1; i < result.length - 1; ++i) { - result[i] = RoundedRectangleShape.RectangleBorderType.OVERSHOOT; - } - - result[0] = RoundedRectangleShape.RectangleBorderType.FIT; - result[result.length - 1] = RoundedRectangleShape.RectangleBorderType.FIT; - return result; - } - - private static float dpToPixel(final Context context, final float dp) { - return TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - dp, - context.getResources().getDisplayMetrics()); - } - - @ColorInt - private static int getStrokeColor(final Context context) { - final TypedValue typedValue = new TypedValue(); - final TypedArray array = context.obtainStyledAttributes(typedValue.data, new int[]{ - android.R.attr.colorControlActivated}); - final int result = array.getColor(0, DEFAULT_STROKE_COLOR); - array.recycle(); - return result; - } - /** * A variant of {@link RectF#contains(float, float)} that also allows the point to reside on * the right boundary of the rectangle. diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index 706b0ce225dc43f6108b037510ab0e9ee759eb95..77670b35a1eaf4f5d557d84e8c8ff5ad7c46baaf 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -50,6 +50,7 @@ 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; @@ -804,20 +805,56 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { private void updateHeaderSeparator() { final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale, (mIs24Hour) ? "Hm" : "hm"); - final String separatorText; - // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats - final char[] hourFormats = {'H', 'h', 'K', 'k'}; - int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats); - if (hIndex == -1) { - // Default case - separatorText = ":"; - } else { - separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1)); - } + final String separatorText = getHourMinSeparatorFromPattern(bestDateTimePattern); mSeparatorView.setText(separatorText); mTextInputPickerView.updateSeparator(separatorText); } + /** + * This helper method extracts the time separator from the {@code datetimePattern}. + * + * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":". + * + * See http://unicode.org/cldr/trac/browser/trunk/common/main + * + * @return Separator string. This is the character or set of quoted characters just after the + * hour marker in {@code dateTimePattern}. Returns a colon (:) if it can't locate the + * separator. + * + * @hide + */ + private static String getHourMinSeparatorFromPattern(String dateTimePattern) { + final String defaultSeparator = ":"; + boolean foundHourPattern = false; + for (int i = 0; i < dateTimePattern.length(); i++) { + switch (dateTimePattern.charAt(i)) { + // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats. + case 'H': + case 'h': + case 'K': + case 'k': + foundHourPattern = true; + continue; + case ' ': // skip spaces + continue; + case '\'': + if (!foundHourPattern) { + continue; + } + SpannableStringBuilder quotedSubstring = new SpannableStringBuilder( + dateTimePattern.substring(i)); + int quotedTextLength = DateFormat.appendQuotedText(quotedSubstring, 0); + return quotedSubstring.subSequence(0, quotedTextLength).toString(); + default: + if (!foundHourPattern) { + continue; + } + return Character.toString(dateTimePattern.charAt(i)); + } + } + return defaultSeparator; + } + static private int lastIndexOfAny(String str, char[] any) { final int lengthAny = any.length; if (lengthAny > 0) { diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java index ac83313bd835779354d0340261a8154cbf999669..cb68bc30c0d5316ec3d9bff8d1f6705bdbb71778 100644 --- a/core/java/android/widget/VideoView2.java +++ b/core/java/android/widget/VideoView2.java @@ -28,11 +28,10 @@ import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.media.update.ApiLoader; import android.media.update.VideoView2Provider; -import android.media.update.ViewProvider; +import android.media.update.ViewGroupHelper; import android.net.Uri; import android.os.Bundle; import android.util.AttributeSet; -import android.view.MotionEvent; import android.view.View; import java.lang.annotation.Retention; @@ -102,7 +101,7 @@ import java.util.concurrent.Executor; * * @hide */ -public class VideoView2 extends FrameLayout { +public class VideoView2 extends ViewGroupHelper { /** @hide */ @IntDef({ VIEW_TYPE_TEXTUREVIEW, @@ -112,21 +111,19 @@ public class VideoView2 extends FrameLayout { public @interface ViewType {} /** - * Indicates video is rendering on SurfaceView + * Indicates video is rendering on SurfaceView. * * @see #setViewType */ public static final int VIEW_TYPE_SURFACEVIEW = 1; /** - * Indicates video is rendering on TextureView + * Indicates video is rendering on TextureView. * * @see #setViewType */ public static final int VIEW_TYPE_TEXTUREVIEW = 2; - private final VideoView2Provider mProvider; - public VideoView2(@NonNull Context context) { this(context, null); } @@ -142,17 +139,12 @@ public class VideoView2 extends FrameLayout { public VideoView2( @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - - mProvider = ApiLoader.getProvider(context).createVideoView2(this, new SuperProvider(), - attrs, defStyleAttr, defStyleRes); - } - - /** - * @hide - */ - public VideoView2Provider getProvider() { - return mProvider; + super((instance, superProvider, privateProvider) -> + ApiLoader.getProvider(context).createVideoView2( + (VideoView2) instance, superProvider, privateProvider, + attrs, defStyleAttr, defStyleRes), + context, attrs, defStyleAttr, defStyleRes); + mProvider.initialize(attrs, defStyleAttr, defStyleRes); } /** @@ -160,9 +152,10 @@ public class VideoView2 extends FrameLayout { * instance if any. * * @param mediaControlView a media control view2 instance. + * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2. */ - public void setMediaControlView2(MediaControlView2 mediaControlView) { - mProvider.setMediaControlView2_impl(mediaControlView); + public void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs) { + mProvider.setMediaControlView2_impl(mediaControlView, intervalMs); } /** @@ -188,18 +181,22 @@ public class VideoView2 extends FrameLayout { } /** - * Starts rendering closed caption or subtitles if there is any. The first subtitle track will - * be chosen by default if there multiple subtitle tracks exist. + * Shows or hides closed caption or subtitles if there is any. + * The first subtitle track will be chosen if there multiple subtitle tracks exist. + * Default behavior of VideoView2 is not showing subtitle. + * @param enable shows closed caption or subtitles if this value is true, or hides. */ - public void showSubtitle() { - mProvider.showSubtitle_impl(); + public void setSubtitleEnabled(boolean enable) { + mProvider.setSubtitleEnabled_impl(enable); } /** - * Stops showing closed captions or subtitles. + * Returns true if showing subtitle feature is enabled or returns false. + * Although there is no subtitle track or closed caption, it can return true, if the feature + * has been enabled by {@link #setSubtitleEnabled}. */ - public void hideSubtitle() { - mProvider.hideSubtitle_impl(); + public boolean isSubtitleEnabled() { + return mProvider.isSubtitleEnabled_impl(); } /** @@ -505,74 +502,7 @@ public class VideoView2 extends FrameLayout { } @Override - protected void onAttachedToWindow() { - mProvider.onAttachedToWindow_impl(); - } - - @Override - protected void onDetachedFromWindow() { - mProvider.onDetachedFromWindow_impl(); - } - - @Override - public CharSequence getAccessibilityClassName() { - return mProvider.getAccessibilityClassName_impl(); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - return mProvider.onTouchEvent_impl(ev); - } - - @Override - public boolean onTrackballEvent(MotionEvent ev) { - return mProvider.onTrackballEvent_impl(ev); - } - - @Override - public void onFinishInflate() { - mProvider.onFinishInflate_impl(); - } - - @Override - public void setEnabled(boolean enabled) { - mProvider.setEnabled_impl(enabled); - } - - private class SuperProvider implements ViewProvider { - @Override - public void onAttachedToWindow_impl() { - VideoView2.super.onAttachedToWindow(); - } - - @Override - public void onDetachedFromWindow_impl() { - VideoView2.super.onDetachedFromWindow(); - } - - @Override - public CharSequence getAccessibilityClassName_impl() { - return VideoView2.super.getAccessibilityClassName(); - } - - @Override - public boolean onTouchEvent_impl(MotionEvent ev) { - return VideoView2.super.onTouchEvent(ev); - } - - @Override - public boolean onTrackballEvent_impl(MotionEvent ev) { - return VideoView2.super.onTrackballEvent(ev); - } - - @Override - public void onFinishInflate_impl() { - VideoView2.super.onFinishInflate(); - } - - @Override - public void setEnabled_impl(boolean enabled) { - VideoView2.super.setEnabled(enabled); - } + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mProvider.onLayout_impl(changed, l, t, r, b); } } diff --git a/core/java/com/android/internal/alsa/AlsaCardsParser.java b/core/java/com/android/internal/alsa/AlsaCardsParser.java index bb75bf6e6fb83de268138cb554cde3bbe4d694ff..fa8db96781ac44b55dc1eba80a2eb51c103ae527 100644 --- a/core/java/com/android/internal/alsa/AlsaCardsParser.java +++ b/core/java/com/android/internal/alsa/AlsaCardsParser.java @@ -31,7 +31,9 @@ public class AlsaCardsParser { private static final String TAG = "AlsaCardsParser"; protected static final boolean DEBUG = false; - private static final String kCardsFilePath = "/proc/asound/cards"; + private static final String kAlsaFolderPath = "/proc/asound"; + private static final String kCardsFilePath = kAlsaFolderPath + "/cards"; + private static final String kDeviceAddressPrefix = "/dev/bus/usb/"; private static LineTokenizer mTokenizer = new LineTokenizer(" :[]"); @@ -47,14 +49,31 @@ public class AlsaCardsParser { private static final String TAG = "AlsaCardRecord"; private static final String kUsbCardKeyStr = "at usb-"; - public int mCardNum = -1; - public String mField1 = ""; - public String mCardName = ""; - public String mCardDescription = ""; - public boolean mIsUsb = false; + int mCardNum = -1; + String mField1 = ""; + String mCardName = ""; + String mCardDescription = ""; + + private String mUsbDeviceAddress = null; public AlsaCardRecord() {} + public int getCardNum() { + return mCardNum; + } + + public String getCardName() { + return mCardName; + } + + public String getCardDescription() { + return mCardDescription; + } + + public void setDeviceAddress(String usbDeviceAddress) { + mUsbDeviceAddress = usbDeviceAddress; + } + private boolean parse(String line, int lineIndex) { int tokenIndex = 0; int delimIndex = 0; @@ -87,8 +106,8 @@ public class AlsaCardsParser { tokenIndex = mTokenizer.nextToken(line, 0); if (tokenIndex != -1) { int keyIndex = line.indexOf(kUsbCardKeyStr); - mIsUsb = keyIndex != -1; - if (mIsUsb) { + boolean isUsb = keyIndex != -1; + if (isUsb) { mCardDescription = line.substring(tokenIndex, keyIndex - 1); } } @@ -97,14 +116,18 @@ public class AlsaCardsParser { return true; } + boolean isUsb() { + return mUsbDeviceAddress != null; + } + public String textFormat() { - return mCardName + " : " + mCardDescription; + return mCardName + " : " + mCardDescription + " [addr:" + mUsbDeviceAddress + "]"; } public void log(int listIndex) { Slog.d(TAG, "" + listIndex + " [" + mCardNum + " " + mCardName + " : " + mCardDescription + - " usb:" + mIsUsb); + " usb:" + isUsb()); } } @@ -112,7 +135,7 @@ public class AlsaCardsParser { public int scan() { if (DEBUG) { - Slog.i(TAG, "AlsaCardsParser.scan()...."); + Slog.d(TAG, "AlsaCardsParser.scan()...."); } mCardRecords = new ArrayList(); @@ -125,7 +148,7 @@ public class AlsaCardsParser { while ((line = bufferedReader.readLine()) != null) { AlsaCardRecord cardRecord = new AlsaCardRecord(); if (DEBUG) { - Slog.i(TAG, " " + line); + Slog.d(TAG, " " + line); } cardRecord.parse(line, 0); @@ -134,10 +157,23 @@ public class AlsaCardsParser { break; } if (DEBUG) { - Slog.i(TAG, " " + line); + Slog.d(TAG, " " + line); } cardRecord.parse(line, 1); + // scan "usbbus" file + int cardNum = cardRecord.mCardNum; + String cardFolderPath = kAlsaFolderPath + "/card" + cardNum; + File usbbusFile = new File(cardFolderPath + "/usbbus"); + if (usbbusFile.exists()) { + // read it in + FileReader usbbusReader = new FileReader(usbbusFile); + String deviceAddress = (new BufferedReader(usbbusReader)).readLine(); + if (deviceAddress != null) { + cardRecord.setDeviceAddress(kDeviceAddressPrefix + deviceAddress); + } + usbbusReader.close(); + } mCardRecords.add(cardRecord); } reader.close(); @@ -147,14 +183,12 @@ public class AlsaCardsParser { mScanStatus = SCANSTATUS_EMPTY; } } catch (FileNotFoundException e) { - e.printStackTrace(); mScanStatus = SCANSTATUS_FAIL; } catch (IOException e) { - e.printStackTrace(); mScanStatus = SCANSTATUS_FAIL; } if (DEBUG) { - Slog.i(TAG, " status:" + mScanStatus); + Slog.d(TAG, " status:" + mScanStatus); } return mScanStatus; } @@ -163,142 +197,33 @@ public class AlsaCardsParser { return mScanStatus; } - public ArrayList getScanRecords() { - return mCardRecords; - } - - public AlsaCardRecord getCardRecordAt(int index) { - return mCardRecords.get(index); - } - - public AlsaCardRecord getCardRecordFor(int cardNum) { - for (AlsaCardRecord rec : mCardRecords) { - if (rec.mCardNum == cardNum) { - return rec; + public AlsaCardRecord findCardNumFor(String deviceAddress) { + for(AlsaCardRecord cardRec : mCardRecords) { + if (cardRec.isUsb() && cardRec.mUsbDeviceAddress.equals(deviceAddress)) { + return cardRec; } } - return null; } - public int getNumCardRecords() { - return mCardRecords.size(); - } - - public boolean isCardUsb(int cardNum) { - for (AlsaCardRecord rec : mCardRecords) { - if (rec.mCardNum == cardNum) { - return rec.mIsUsb; - } - } - - return false; - } - - // return -1 if none found - public int getDefaultUsbCard() { - // save the current list of devices - ArrayList prevRecs = mCardRecords; - if (DEBUG) { - LogDevices("Previous Devices:", prevRecs); - } - - // get the new list of devices - if (scan() != SCANSTATUS_SUCCESS) { - Slog.e(TAG, "Error scanning Alsa cards file."); - return -1; - } - - if (DEBUG) { - LogDevices("Current Devices:", mCardRecords); - } - - // Calculate the difference between the old and new device list - ArrayList newRecs = getNewCardRecords(prevRecs); - if (DEBUG) { - LogDevices("New Devices:", newRecs); - } - - // Choose the most-recently added EXTERNAL card - // Check recently added devices - for (AlsaCardRecord rec : newRecs) { - if (DEBUG) { - Slog.d(TAG, rec.mCardName + " card:" + rec.mCardNum + " usb:" + rec.mIsUsb); - } - if (rec.mIsUsb) { - // Found it - return rec.mCardNum; - } - } - - // or return the first added EXTERNAL card? - for (AlsaCardRecord rec : prevRecs) { - if (DEBUG) { - Slog.d(TAG, rec.mCardName + " card:" + rec.mCardNum + " usb:" + rec.mIsUsb); - } - if (rec.mIsUsb) { - return rec.mCardNum; - } - } - - return -1; - } - - public int getDefaultCard() { - // return an external card if possible - int card = getDefaultUsbCard(); - if (DEBUG) { - Slog.d(TAG, "getDefaultCard() default usb card:" + card); - } - - if (card < 0 && getNumCardRecords() > 0) { - // otherwise return the (internal) card with the highest number - card = getCardRecordAt(getNumCardRecords() - 1).mCardNum; - } - if (DEBUG) { - Slog.d(TAG, " returns card:" + card); - } - return card; - } - - static public boolean hasCardNumber(ArrayList recs, int cardNum) { - for (AlsaCardRecord cardRec : recs) { - if (cardRec.mCardNum == cardNum) { - return true; - } - } - return false; - } - - public ArrayList getNewCardRecords(ArrayList prevScanRecs) { - ArrayList newRecs = new ArrayList(); - for (AlsaCardRecord rec : mCardRecords) { - // now scan to see if this card number is in the previous scan list - if (!hasCardNumber(prevScanRecs, rec.mCardNum)) { - newRecs.add(rec); - } - } - return newRecs; - } - // // Logging // private void Log(String heading) { if (DEBUG) { - Slog.i(TAG, heading); + Slog.d(TAG, heading); for (AlsaCardRecord cardRec : mCardRecords) { - Slog.i(TAG, cardRec.textFormat()); + Slog.d(TAG, cardRec.textFormat()); } } } - static private void LogDevices(String caption, ArrayList deviceList) { - Slog.d(TAG, caption + " ----------------"); - int listIndex = 0; - for (AlsaCardRecord device : deviceList) { - device.log(listIndex++); - } - Slog.d(TAG, "----------------"); - } +// static private void LogDevices(String caption, ArrayList deviceList) { +// Slog.d(TAG, caption + " ----------------"); +// int listIndex = 0; +// for (AlsaCardRecord device : deviceList) { +// device.log(listIndex++); +// } +// Slog.d(TAG, caption + "----------------"); +// } } diff --git a/core/java/com/android/internal/alsa/AlsaDevicesParser.java b/core/java/com/android/internal/alsa/AlsaDevicesParser.java index 15261bafd299f96dc3fa43f559727c6003fc8d11..8d92d016be241d0ea2cdb36ac11f8529cce1b7a4 100644 --- a/core/java/com/android/internal/alsa/AlsaDevicesParser.java +++ b/core/java/com/android/internal/alsa/AlsaDevicesParser.java @@ -27,6 +27,9 @@ import java.util.ArrayList; * @hide * Retrieves information from an ALSA "devices" file. */ +/* + * NOTE: This class is currently not being used, but may be needed in the future. + */ public class AlsaDevicesParser { private static final String TAG = "AlsaDevicesParser"; protected static final boolean DEBUG = false; @@ -207,12 +210,6 @@ public class AlsaDevicesParser { // // Predicates // -/* - public boolean hasPlaybackDevices() { - return mHasPlaybackDevices; - } -*/ - public boolean hasPlaybackDevices(int card) { for (AlsaDeviceRecord deviceRecord : mDeviceRecords) { if (deviceRecord.mCardNum == card && @@ -224,12 +221,6 @@ public class AlsaDevicesParser { return false; } -/* - public boolean hasCaptureDevices() { - return mHasCaptureDevices; - } -*/ - public boolean hasCaptureDevices(int card) { for (AlsaDeviceRecord deviceRecord : mDeviceRecords) { if (deviceRecord.mCardNum == card && @@ -241,12 +232,6 @@ public class AlsaDevicesParser { return false; } -/* - public boolean hasMIDIDevices() { - return mHasMIDIDevices; - } -*/ - public boolean hasMIDIDevices(int card) { for (AlsaDeviceRecord deviceRecord : mDeviceRecords) { if (deviceRecord.mCardNum == card && @@ -280,6 +265,7 @@ public class AlsaDevicesParser { if (isLineDeviceRecord(line)) { AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord(); deviceRecord.parse(line); + Slog.i(TAG, deviceRecord.textFormat()); mDeviceRecords.add(deviceRecord); } } diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 1dfff5efcab524188f675e2a22ce7e0518cd248c..6bd693061a85f19344044dbee4d4da5cc460703b 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -106,7 +106,7 @@ public class ResolverListController { int flags = PackageManager.MATCH_DEFAULT_ONLY | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0) | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0); - if (intent.isBrowsableWebIntent() + if (intent.isWebIntent() || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) { flags |= PackageManager.MATCH_INSTANT; } diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java index 902c8c1662ea2a83ca0ea7832f9aee45ce10e291..6f7695ce8c34ae112dd635c31fe0c7769f471b6f 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -21,24 +21,15 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.app.Activity; import android.app.AlertDialog; -import android.app.admin.DevicePolicyManager; import android.content.ComponentName; -import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; -import android.text.TextUtils; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; import android.view.Window; -import android.widget.TextView; import com.android.internal.R; @@ -85,14 +76,9 @@ public class UnlaunchableAppActivity extends Activity return; } - View rootView = LayoutInflater.from(this).inflate(R.layout.unlaunchable_app_activity, null); - TextView titleView = (TextView)rootView.findViewById(R.id.unlaunchable_app_title); - TextView messageView = (TextView)rootView.findViewById(R.id.unlaunchable_app_message); - titleView.setText(dialogTitle); - messageView.setText(dialogMessage); - AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setView(rootView) + .setTitle(dialogTitle) + .setMessage(dialogMessage) .setOnDismissListener(this); if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) { builder.setPositiveButton(R.string.work_mode_turn_on, this) diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS index 10d44bdecb83c4c06dfdafc765fa5f40aee8d955..ef44ef7452f4ba2edd0db72f889ffb5869c41be2 100644 --- a/core/java/com/android/internal/net/OWNERS +++ b/core/java/com/android/internal/net/OWNERS @@ -1,7 +1,6 @@ set noparent ek@google.com -hugobenichi@google.com jchalard@google.com jsharkey@android.com lorenzo@google.com diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 7def87655ae373a6906918a5426865817759d582..40dcf25bbd104a6b928a3d85996e333b978f0996 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -3880,7 +3880,8 @@ public class BatteryStatsImpl extends BatteryStats { public void addIsolatedUidLocked(int isolatedUid, int appUid) { mIsolatedUids.put(isolatedUid, appUid); - StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid, 1); + StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid, + StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED); final Uid u = getUidStatsLocked(appUid); u.addIsolatedUid(isolatedUid); } @@ -3904,7 +3905,8 @@ public class BatteryStatsImpl extends BatteryStats { */ public void removeIsolatedUidLocked(int isolatedUid) { StatsLog.write( - StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1), isolatedUid, 0); + StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1), + isolatedUid, StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED); final int idx = mIsolatedUids.indexOfKey(isolatedUid); if (idx >= 0) { final int ownerUid = mIsolatedUids.valueAt(idx); @@ -4255,10 +4257,12 @@ public class BatteryStatsImpl extends BatteryStats { if (wc != null) { StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), - getPowerManagerWakeLockLevel(type), name, 1); + getPowerManagerWakeLockLevel(type), name, + StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); } else { StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null, - getPowerManagerWakeLockLevel(type), name, 1); + getPowerManagerWakeLockLevel(type), name, + StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); } } } @@ -4298,10 +4302,12 @@ public class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); if (wc != null) { StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), - getPowerManagerWakeLockLevel(type), name, 0); + getPowerManagerWakeLockLevel(type), name, + StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); } else { StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null, - getPowerManagerWakeLockLevel(type), name, 0); + getPowerManagerWakeLockLevel(type), name, + StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); } } } @@ -4426,7 +4432,8 @@ public class BatteryStatsImpl extends BatteryStats { public void noteLongPartialWakelockStart(String name, String historyName, int uid) { StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, - uid, null, name, historyName, 1); + uid, null, name, historyName, + StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON); uid = mapUid(uid); noteLongPartialWakeLockStartInternal(name, historyName, uid); @@ -4439,7 +4446,8 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(workSource.get(i)); noteLongPartialWakeLockStartInternal(name, historyName, uid); StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, - workSource.get(i), workSource.getName(i), name, historyName, 1); + workSource.get(i), workSource.getName(i), name, historyName, + StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON); } final ArrayList workChains = workSource.getWorkChains(); @@ -4450,7 +4458,8 @@ public class BatteryStatsImpl extends BatteryStats { noteLongPartialWakeLockStartInternal(name, historyName, uid); StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), name, historyName, 1); + workChain.getUids(), workChain.getTags(), name, historyName, + StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON); } } } @@ -4470,8 +4479,8 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { - StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, - uid, null, name, historyName, 0); + StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, null, + name, historyName, StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF); uid = mapUid(uid); noteLongPartialWakeLockFinishInternal(name, historyName, uid); @@ -4484,7 +4493,8 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(workSource.get(i)); noteLongPartialWakeLockFinishInternal(name, historyName, uid); StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, - workSource.get(i), workSource.getName(i), name, historyName, 0); + workSource.get(i), workSource.getName(i), name, historyName, + StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF); } final ArrayList workChains = workSource.getWorkChains(); @@ -4494,7 +4504,8 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = workChain.getAttributionUid(); noteLongPartialWakeLockFinishInternal(name, historyName, uid); StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), name, historyName, 0); + workChain.getUids(), workChain.getTags(), name, historyName, + StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF); } } } @@ -4518,7 +4529,8 @@ public class BatteryStatsImpl extends BatteryStats { long deltaUptime = uptimeMs - mLastWakeupUptimeMs; SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason); timer.add(deltaUptime * 1000, 1); // time in in microseconds - StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason, deltaUptime * 1000); + StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason, + /* duration_usec */ deltaUptime * 1000); mLastWakeupReason = null; } } @@ -4659,10 +4671,12 @@ public class BatteryStatsImpl extends BatteryStats { mGpsNesting++; if (workChain == null) { - StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, 1); + StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, + StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON); } else { StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 1); + workChain.getUids(), workChain.getTags(), + StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON); } getUidStatsLocked(uid).noteStartGps(elapsedRealtime); @@ -4683,10 +4697,11 @@ public class BatteryStatsImpl extends BatteryStats { } if (workChain == null) { - StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, 0); + StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null, + StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF); } else { StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(), - workChain.getTags(), 0); + workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF); } getUidStatsLocked(uid).noteStopGps(elapsedRealtime); @@ -4941,7 +4956,9 @@ public class BatteryStatsImpl extends BatteryStats { mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime); } addHistoryRecordLocked(elapsedRealtime, uptime); - StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ? 1 : 0); + StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ? + StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON : + StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF); } } @@ -5545,16 +5562,19 @@ public class BatteryStatsImpl extends BatteryStats { if (workChain != null) { StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 1); + workChain.getUids(), workChain.getTags(), + StatsLog.BLE_SCAN_STATE_CHANGED__STATE__ON); if (isUnoptimized) { StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 1); + workChain.getUids(), workChain.getTags(), + StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__ON); } } else { - StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null, 1); + StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null, + StatsLog.BLE_SCAN_STATE_CHANGED__STATE__ON); if (isUnoptimized) { StatsLog.write_non_chained(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uid, null, - 1); + StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__ON); } } @@ -5594,16 +5614,19 @@ public class BatteryStatsImpl extends BatteryStats { if (workChain != null) { StatsLog.write( - StatsLog.BLE_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(), 0); + StatsLog.BLE_SCAN_STATE_CHANGED, workChain.getUids(), workChain.getTags(), + StatsLog.BLE_SCAN_STATE_CHANGED__STATE__OFF); if (isUnoptimized) { StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 0); + workChain.getUids(), workChain.getTags(), + StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__OFF); } } else { - StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null, 0); + StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null, + StatsLog.BLE_SCAN_STATE_CHANGED__STATE__OFF); if (isUnoptimized) { StatsLog.write_non_chained(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uid, null, - 0); + StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__OFF); } } @@ -5656,7 +5679,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int j = 0; j < allWorkChains.size(); ++j) { StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, allWorkChains.get(j).getUids(), - allWorkChains.get(j).getTags(), 0); + allWorkChains.get(j).getTags(), + StatsLog.BLE_SCAN_STATE_CHANGED__STATE__OFF); } allWorkChains.clear(); } @@ -5666,7 +5690,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int j = 0; j < unoptimizedWorkChains.size(); ++j) { StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, unoptimizedWorkChains.get(j).getUids(), - unoptimizedWorkChains.get(j).getTags(), 0); + unoptimizedWorkChains.get(j).getTags(), + StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED__STATE__OFF); } unoptimizedWorkChains.clear(); } @@ -6011,7 +6036,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int i=0; i workChains = ws.getWorkChains(); @@ -6021,7 +6047,8 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(workChain.getAttributionUid()); noteFullWifiLockAcquiredLocked(uid); StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 1); + workChain.getUids(), workChain.getTags(), + StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON); } } } @@ -6031,7 +6058,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int i=0; i workChains = ws.getWorkChains(); @@ -6041,7 +6069,8 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(workChain.getAttributionUid()); noteFullWifiLockReleasedLocked(uid); StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 0); + workChain.getUids(), workChain.getTags(), + StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF); } } } @@ -6052,7 +6081,7 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(ws.get(i)); noteWifiScanStartedLocked(uid); StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i), - 1); + StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON); } final List workChains = ws.getWorkChains(); @@ -6062,7 +6091,7 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(workChain.getAttributionUid()); noteWifiScanStartedLocked(uid); StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, workChain.getUids(), - workChain.getTags(), 1); + workChain.getTags(), StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON); } } } @@ -6073,7 +6102,7 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(ws.get(i)); noteWifiScanStoppedLocked(uid); StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i), - 0); + StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF); } final List workChains = ws.getWorkChains(); @@ -6083,7 +6112,8 @@ public class BatteryStatsImpl extends BatteryStats { final int uid = mapUid(workChain.getAttributionUid()); noteWifiScanStoppedLocked(uid); StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, - workChain.getUids(), workChain.getTags(), 0); + workChain.getUids(), workChain.getTags(), + StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF); } } } @@ -7035,7 +7065,8 @@ public class BatteryStatsImpl extends BatteryStats { } mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs); StatsLog.write_non_chained( - StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, 1); + StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, + StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON); } } @@ -7045,7 +7076,8 @@ public class BatteryStatsImpl extends BatteryStats { mWifiMulticastEnabled = false; mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs); StatsLog.write_non_chained( - StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, 0); + StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, + StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__OFF); } } @@ -7098,14 +7130,16 @@ public class BatteryStatsImpl extends BatteryStats { public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) { createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, 1); + StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, + StatsLog.AUDIO_STATE_CHANGED__STATE__ON); } public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) { if (mAudioTurnedOnTimer != null) { mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs); if (!mAudioTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped - StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, 0); + StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, + StatsLog.AUDIO_STATE_CHANGED__STATE__OFF); } } } @@ -7113,7 +7147,8 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetAudioLocked(long elapsedRealtimeMs) { if (mAudioTurnedOnTimer != null) { mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, 0); + StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, + StatsLog.AUDIO_STATE_CHANGED__STATE__OFF); } } @@ -7127,7 +7162,8 @@ public class BatteryStatsImpl extends BatteryStats { public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) { createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null, 1); + StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null, + StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__ON); } public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) { @@ -7135,7 +7171,7 @@ public class BatteryStatsImpl extends BatteryStats { mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs); if (!mVideoTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), - null, 0); + null, StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF); } } } @@ -7144,7 +7180,7 @@ public class BatteryStatsImpl extends BatteryStats { if (mVideoTurnedOnTimer != null) { mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs); StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null, - 0); + StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED__STATE__OFF); } } @@ -7158,7 +7194,8 @@ public class BatteryStatsImpl extends BatteryStats { public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) { createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,1); + StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null, + StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON); } public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) { @@ -7166,7 +7203,7 @@ public class BatteryStatsImpl extends BatteryStats { mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs); if (!mFlashlightTurnedOnTimer.isRunningLocked()) { StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null, - 0); + StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF); } } } @@ -7174,7 +7211,8 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetFlashlightLocked(long elapsedRealtimeMs) { if (mFlashlightTurnedOnTimer != null) { mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null, 0); + StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null, + StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF); } } @@ -7188,14 +7226,16 @@ public class BatteryStatsImpl extends BatteryStats { public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) { createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, 1); + StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, + StatsLog.CAMERA_STATE_CHANGED__STATE__ON); } public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) { if (mCameraTurnedOnTimer != null) { mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs); if (!mCameraTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped - StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, 0); + StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, + StatsLog.CAMERA_STATE_CHANGED__STATE__OFF); } } } @@ -7203,7 +7243,8 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetCameraLocked(long elapsedRealtimeMs) { if (mCameraTurnedOnTimer != null) { mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, 0); + StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, + StatsLog.CAMERA_STATE_CHANGED__STATE__OFF); } } @@ -9777,7 +9818,8 @@ public class BatteryStatsImpl extends BatteryStats { DualTimer t = mSyncStats.startObject(name); if (t != null) { t.startRunningLocked(elapsedRealtimeMs); - StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name, 1); + StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name, + StatsLog.SYNC_STATE_CHANGED__STATE__ON); } } @@ -9786,7 +9828,8 @@ public class BatteryStatsImpl extends BatteryStats { if (t != null) { t.stopRunningLocked(elapsedRealtimeMs); if (!t.isRunningLocked()) { // only tell statsd if truly stopped - StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name, 0); + StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name, + StatsLog.SYNC_STATE_CHANGED__STATE__OFF); } } } @@ -9796,7 +9839,7 @@ public class BatteryStatsImpl extends BatteryStats { if (t != null) { t.startRunningLocked(elapsedRealtimeMs); StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null, - name, 1); + name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED); } } @@ -9806,7 +9849,7 @@ public class BatteryStatsImpl extends BatteryStats { t.stopRunningLocked(elapsedRealtimeMs); if (!t.isRunningLocked()) { // only tell statsd if truly stopped StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null, - name, 0); + name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED); } } if (mBsi.mOnBatteryTimeBase.isRunning()) { @@ -9919,7 +9962,7 @@ public class BatteryStatsImpl extends BatteryStats { t.startRunningLocked(elapsedRealtimeMs); if (sensor != Sensor.GPS) { StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor, - 1); + StatsLog.SENSOR_STATE_CHANGED__STATE__ON); } } @@ -9930,7 +9973,7 @@ public class BatteryStatsImpl extends BatteryStats { t.stopRunningLocked(elapsedRealtimeMs); if (sensor != Sensor.GPS) { StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, - sensor, 0); + sensor, StatsLog.SENSOR_STATE_CHANGED__STATE__OFF); } } } diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index f9a2341fc3e3cc151a5cd62e4e0aa7ba11a43f94..e69a36064693bad9eb0fd9025e85ee34b23bfba0 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -55,6 +55,8 @@ public final class Zygote { public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10; /** Do not enfore hidden API access restrictions. */ public static final int DISABLE_HIDDEN_API_CHECKS = 1 << 11; + /** Force generation of native debugging information for backtraces. */ + public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12; /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE; diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 39279b5055b1863191e1ed0690747165c5fc356d..74802c8bdf79233866ad2927fb1b2ae012fae898 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -583,7 +583,7 @@ public class ZygoteInit { installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, uuid, classLoaderContext, seInfo, false /* downgrade */, - targetSdkVersion, /*profileName*/ null); + targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null); } catch (RemoteException | ServiceSpecificException e) { // Ignore (but log), we need this on the classpath for fallback mode. Log.w(TAG, "Failed compiling classpath element for system server: " diff --git a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java index 245a66e4b566700cbe361a3ea4bd4ea4c8cc7ba3..1376687be019f0e8db01f97fd9dd9c9c0cb40bdd 100644 --- a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java +++ b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java @@ -96,4 +96,14 @@ public class MetricsLoggerWrapper { context.getApplicationInfo().className, StatsLog.PICTURE_IN_PICTURE_STATE_CHANGED__STATE__EXPANDED_TO_FULL_SCREEN); } + + public static void logAppOverlayEnter(int uid, String packageName, boolean usingAlertWindow) { + StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, usingAlertWindow, + StatsLog.OVERLAY_STATE_CHANGED__STATE__ENTERED); + } + + public static void logAppOverlayExit(int uid, String packageName, boolean usingAlertWindow) { + StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, usingAlertWindow, + StatsLog.OVERLAY_STATE_CHANGED__STATE__EXITED); + } } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 95bc352747d24cf6ab8f97cd837a80fe10218e3e..eadefc9199344d6106d0dffc3bda6c89a341d95d 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -86,6 +86,7 @@ import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.PopupWindow; +import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -2216,7 +2217,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind elevation = dipToPx(elevation); mElevationAdjustedForStack = true; } else if (windowingMode == WINDOWING_MODE_PINNED) { - elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP); + elevation = dipToPx(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP); mElevationAdjustedForStack = true; } else { mElevationAdjustedForStack = false; diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 34b5ec8149a7be8493b7215cfa88d2bc2fc5021d..03a7cd26da3696d873cfe35ea10591271031f809 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -3158,7 +3158,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { Bundle args = new Bundle(); args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId()); return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE)) - .launchLegacyAssist(null, UserHandle.myUserId(), args); + .launchLegacyAssist(null, getContext().getUserId(), args); } return result; } diff --git a/core/java/com/android/internal/print/DumpUtils.java b/core/java/com/android/internal/print/DumpUtils.java index 3192d5cbbd1d57295b5a13c5316a2f8a1c9f807f..1916c11e9c9d51610bda063c433d99adbf93aa33 100644 --- a/core/java/com/android/internal/print/DumpUtils.java +++ b/core/java/com/android/internal/print/DumpUtils.java @@ -16,10 +16,9 @@ package com.android.internal.print; +import static com.android.internal.util.dump.DumpUtils.writeComponentName; + import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.ComponentName; -import android.content.ComponentNameProto; import android.content.Context; import android.print.PageRange; import android.print.PrintAttributes; @@ -40,41 +39,12 @@ import android.service.print.PrinterIdProto; import android.service.print.PrinterInfoProto; import android.service.print.ResolutionProto; +import com.android.internal.util.dump.DualDumpOutputStream; + /** * Utilities for dumping print related proto buffer */ public class DumpUtils { - /** - * Write a string to a proto if the string is not {@code null}. - * - * @param proto The proto to write to - * @param idName Clear text name of the proto-id - * @param id The proto-id of the string - * @param string The string to write - */ - public static void writeStringIfNotNull(@NonNull DualDumpOutputStream proto, String idName, - long id, @Nullable String string) { - if (string != null) { - proto.write(idName, id, string); - } - } - - /** - * Write a {@link ComponentName} to a proto. - * - * @param proto The proto to write to - * @param idName Clear text name of the proto-id - * @param id The proto-id of the component name - * @param component The component name to write - */ - public static void writeComponentName(@NonNull DualDumpOutputStream proto, String idName, - long id, @NonNull ComponentName component) { - long token = proto.start(idName, id); - proto.write("package_name", ComponentNameProto.PACKAGE_NAME, component.getPackageName()); - proto.write("class_name", ComponentNameProto.CLASS_NAME, component.getClassName()); - proto.end(token); - } - /** * Write a {@link PrinterId} to a proto. * diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index ebb5f9f9e446d316e448f8fcb72fef439a625d73..f70d3c2a27fdd4fa88632632dadc5aadd3b554f9 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -132,6 +132,12 @@ oneway interface IStatusBar void clickQsTile(in ComponentName tile); void handleSystemKey(in int key); + /** + * Methods to show toast messages for screen pinning + */ + void showPinningEnterExitToast(boolean entering); + void showPinningEscapeToast(); + void showShutdownUi(boolean isReboot, String reason); // Used to show the dialog when FingerprintService starts authentication diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index cb0b53c495dcf0d12de5188f5f4ec9df805656e5..adf42878ebb3cf65bf5f0d14602ff767e9218f1f 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -81,6 +81,12 @@ interface IStatusBarService void clickTile(in ComponentName tile); void handleSystemKey(in int key); + /** + * Methods to show toast messages for screen pinning + */ + void showPinningEnterExitToast(boolean entering); + void showPinningEscapeToast(); + // Used to show the dialog when FingerprintService starts authentication void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver); // Used to hide the dialog when a finger is authenticated diff --git a/core/java/com/android/internal/usb/DumpUtils.java b/core/java/com/android/internal/usb/DumpUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..cac22652ebd7a7985245e441c61020ac6414ed35 --- /dev/null +++ b/core/java/com/android/internal/usb/DumpUtils.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.usb; + +import static android.hardware.usb.UsbPort.MODE_AUDIO_ACCESSORY; +import static android.hardware.usb.UsbPort.MODE_DEBUG_ACCESSORY; +import static android.hardware.usb.UsbPort.MODE_DFP; +import static android.hardware.usb.UsbPort.MODE_DUAL; +import static android.hardware.usb.UsbPort.MODE_NONE; +import static android.hardware.usb.UsbPort.MODE_UFP; + +import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull; + +import android.annotation.NonNull; +import android.hardware.usb.UsbAccessory; +import android.hardware.usb.UsbConfiguration; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbPort; +import android.hardware.usb.UsbPortStatus; +import android.hardware.usb.V1_0.Constants; +import android.service.usb.UsbAccessoryProto; +import android.service.usb.UsbConfigurationProto; +import android.service.usb.UsbDeviceProto; +import android.service.usb.UsbEndPointProto; +import android.service.usb.UsbInterfaceProto; +import android.service.usb.UsbPortProto; +import android.service.usb.UsbPortStatusProto; +import android.service.usb.UsbPortStatusRoleCombinationProto; + +import com.android.internal.util.dump.DualDumpOutputStream; + +/** Dump methods for public USB classes */ +public class DumpUtils { + public static void writeAccessory(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, @NonNull UsbAccessory accessory) { + long token = dump.start(idName, id); + + dump.write("manufacturer", UsbAccessoryProto.MANUFACTURER, accessory.getManufacturer()); + dump.write("model", UsbAccessoryProto.MODEL, accessory.getModel()); + writeStringIfNotNull(dump, "description", UsbAccessoryProto.DESCRIPTION, + accessory.getManufacturer()); + dump.write("version", UsbAccessoryProto.VERSION, accessory.getVersion()); + writeStringIfNotNull(dump, "uri", UsbAccessoryProto.URI, accessory.getUri()); + dump.write("serial", UsbAccessoryProto.SERIAL, accessory.getSerial()); + + dump.end(token); + } + + public static void writeDevice(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, @NonNull UsbDevice device) { + long token = dump.start(idName, id); + + dump.write("name", UsbDeviceProto.NAME, device.getDeviceName()); + dump.write("vendor_id", UsbDeviceProto.VENDOR_ID, device.getVendorId()); + dump.write("product_id", UsbDeviceProto.PRODUCT_ID, device.getProductId()); + dump.write("class", UsbDeviceProto.CLASS, device.getDeviceClass()); + dump.write("subclass", UsbDeviceProto.SUBCLASS, device.getDeviceSubclass()); + dump.write("protocol", UsbDeviceProto.PROTOCOL, device.getDeviceProtocol()); + dump.write("manufacturer_name", UsbDeviceProto.MANUFACTURER_NAME, + device.getManufacturerName()); + dump.write("product_name", UsbDeviceProto.PRODUCT_NAME, device.getProductName()); + dump.write("version", UsbDeviceProto.VERSION, device.getVersion()); + dump.write("serial_number", UsbDeviceProto.SERIAL_NUMBER, device.getSerialNumber()); + + int numConfigurations = device.getConfigurationCount(); + for (int i = 0; i < numConfigurations; i++) { + writeConfiguration(dump, "configurations", UsbDeviceProto.CONFIGURATIONS, + device.getConfiguration(i)); + } + + dump.end(token); + } + + private static void writeConfiguration(@NonNull DualDumpOutputStream dump, + @NonNull String idName, long id, @NonNull UsbConfiguration configuration) { + long token = dump.start(idName, id); + dump.write("id", UsbConfigurationProto.ID, configuration.getId()); + dump.write("name", UsbConfigurationProto.NAME, configuration.getName()); + dump.write("attributes", UsbConfigurationProto.ATTRIBUTES, configuration.getAttributes()); + dump.write("max_power", UsbConfigurationProto.MAX_POWER, configuration.getMaxPower()); + + int numInterfaces = configuration.getInterfaceCount(); + for (int i = 0; i < numInterfaces; i++) { + writeInterface(dump, "interfaces", UsbConfigurationProto.INTERFACES, + configuration.getInterface(i)); + } + dump.end(token); + } + + private static void writeInterface(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, @NonNull UsbInterface iface) { + long token = dump.start(idName, id); + + dump.write("id", UsbInterfaceProto.ID, iface.getId()); + dump.write("alternate_settings", UsbInterfaceProto.ALTERNATE_SETTINGS, + iface.getAlternateSetting()); + dump.write("name", UsbInterfaceProto.NAME, iface.getName()); + dump.write("class", UsbInterfaceProto.CLASS, iface.getInterfaceClass()); + dump.write("subclass", UsbInterfaceProto.SUBCLASS, iface.getInterfaceSubclass()); + dump.write("protocol", UsbInterfaceProto.PROTOCOL, iface.getInterfaceProtocol()); + + int numEndpoints = iface.getEndpointCount(); + for (int i = 0; i < numEndpoints; i++) { + writeEndpoint(dump, "endpoints", UsbInterfaceProto.ENDPOINTS, iface.getEndpoint(i)); + } + dump.end(token); + } + + private static void writeEndpoint(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, @NonNull UsbEndpoint endpoint) { + long token = dump.start(idName, id); + + dump.write("endpoint_number", UsbEndPointProto.ENDPOINT_NUMBER, + endpoint.getEndpointNumber()); + dump.write("direction", UsbEndPointProto.DIRECTION, endpoint.getDirection()); + dump.write("address", UsbEndPointProto.ADDRESS, endpoint.getAddress()); + dump.write("type", UsbEndPointProto.TYPE, endpoint.getType()); + dump.write("attributes", UsbEndPointProto.ATTRIBUTES, + endpoint.getAttributes()); + dump.write("max_packet_size", UsbEndPointProto.MAX_PACKET_SIZE, + endpoint.getMaxPacketSize()); + dump.write("interval", UsbEndPointProto.INTERVAL, endpoint.getInterval()); + + dump.end(token); + } + + public static void writePort(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, @NonNull UsbPort port) { + long token = dump.start(idName, id); + + dump.write("id", UsbPortProto.ID, port.getId()); + + int mode = port.getSupportedModes(); + if (dump.isProto()) { + if (mode == MODE_NONE) { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_NONE); + } else { + if ((mode & MODE_DUAL) == MODE_DUAL) { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_DUAL); + } else { + if ((mode & MODE_DFP) == MODE_DFP) { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_DFP); + } else if ((mode & MODE_UFP) == MODE_UFP) { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, MODE_UFP); + } + } + + if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, + MODE_AUDIO_ACCESSORY); + } + + if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, + MODE_DEBUG_ACCESSORY); + } + } + } else { + dump.write("supported_modes", UsbPortProto.SUPPORTED_MODES, UsbPort.modeToString(mode)); + } + + dump.end(token); + } + + private static void writePowerRole(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, int powerRole) { + if (dump.isProto()) { + dump.write(idName, id, powerRole); + } else { + dump.write(idName, id, UsbPort.powerRoleToString(powerRole)); + } + } + + private static void writeDataRole(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, int dataRole) { + if (dump.isProto()) { + dump.write(idName, id, dataRole); + } else { + dump.write(idName, id, UsbPort.dataRoleToString(dataRole)); + } + } + + + public static void writePortStatus(@NonNull DualDumpOutputStream dump, @NonNull String idName, + long id, @NonNull UsbPortStatus status) { + long token = dump.start(idName, id); + + dump.write("connected", UsbPortStatusProto.CONNECTED, status.isConnected()); + + if (dump.isProto()) { + dump.write("current_mode", UsbPortStatusProto.CURRENT_MODE, status.getCurrentMode()); + } else { + dump.write("current_mode", UsbPortStatusProto.CURRENT_MODE, + UsbPort.modeToString(status.getCurrentMode())); + } + + writePowerRole(dump, "power_role", UsbPortStatusProto.POWER_ROLE, + status.getCurrentPowerRole()); + writeDataRole(dump, "data_role", UsbPortStatusProto.DATA_ROLE, status.getCurrentDataRole()); + + int undumpedCombinations = status.getSupportedRoleCombinations(); + while (undumpedCombinations != 0) { + int index = Integer.numberOfTrailingZeros(undumpedCombinations); + undumpedCombinations &= ~(1 << index); + + int powerRole = (index / Constants.PortDataRole.NUM_DATA_ROLES + + Constants.PortPowerRole.NONE); + int dataRole = index % Constants.PortDataRole.NUM_DATA_ROLES; + + long roleCombinationToken = dump.start("role_combinations", + UsbPortStatusProto.ROLE_COMBINATIONS); + writePowerRole(dump, "power_role", UsbPortStatusRoleCombinationProto.POWER_ROLE, + powerRole); + writeDataRole(dump, "data_role", UsbPortStatusRoleCombinationProto.DATA_ROLE, + dataRole); + dump.end(roleCombinationToken); + } + + dump.end(token); + } +} diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java index 2f2c747d65092dcbd737a9104231282cc859c61c..433d14f7b45342044415c66ee1f1f649af6d7035 100644 --- a/core/java/com/android/internal/util/CollectionUtils.java +++ b/core/java/com/android/internal/util/CollectionUtils.java @@ -138,14 +138,14 @@ public class CollectionUtils { public static @NonNull List mapNotNull(@Nullable List cur, Function f) { if (isEmpty(cur)) return Collections.emptyList(); - final ArrayList result = new ArrayList<>(); + List result = null; for (int i = 0; i < cur.size(); i++) { O transformed = f.apply(cur.get(i)); if (transformed != null) { - result.add(transformed); + result = add(result, transformed); } } - return result; + return emptyIfNull(result); } /** diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java index 71550be1c8d7082deff3c7279e4b475d07afd888..f8885a20970d56024f72c2ed5b5a6b032aeca817 100644 --- a/core/java/com/android/internal/util/FileRotator.java +++ b/core/java/com/android/internal/util/FileRotator.java @@ -160,7 +160,7 @@ public class FileRotator { final File file = new File(mBasePath, name); final FileInputStream is = new FileInputStream(file); try { - Streams.copy(is, zos); + FileUtils.copy(is, zos); } finally { IoUtils.closeQuietly(is); } diff --git a/core/java/com/android/internal/print/DualDumpOutputStream.java b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java similarity index 92% rename from core/java/com/android/internal/print/DualDumpOutputStream.java rename to core/java/com/android/internal/util/dump/DualDumpOutputStream.java index 4b10ef2facbbca677b9f3faca431ea1c97341129..3ac38edaddb435a700ece3d79a613582f02da4d5 100644 --- a/core/java/com/android/internal/print/DualDumpOutputStream.java +++ b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.print; +package com.android.internal.util.dump; import android.annotation.NonNull; import android.annotation.Nullable; @@ -131,27 +131,27 @@ public class DualDumpOutputStream { } } - /** - * Create a new DualDumpOutputStream. Only one output should be set. + * Create a new DualDumpOutputStream. * - * @param proto If dumping to proto the {@link ProtoOutputStream} - * @param ipw If dumping to a print writer, the {@link IndentingPrintWriter} + * @param proto the {@link ProtoOutputStream} */ - public DualDumpOutputStream(@Nullable ProtoOutputStream proto, - @Nullable IndentingPrintWriter ipw) { - if ((proto == null) == (ipw == null)) { - Log.e(LOG_TAG, "Cannot dump to clear text and proto at once. Ignoring proto"); - proto = null; - } - + public DualDumpOutputStream(@NonNull ProtoOutputStream proto) { mProtoStream = proto; + mIpw = null; + } + + /** + * Create a new DualDumpOutputStream. + * + * @param ipw the {@link IndentingPrintWriter} + */ + public DualDumpOutputStream(@NonNull IndentingPrintWriter ipw) { + mProtoStream = null; mIpw = ipw; - if (!isProto()) { - // Add root object - mDumpObjects.add(new DumpObject(null)); - } + // Add root object + mDumpObjects.add(new DumpObject(null)); } public void write(@NonNull String fieldName, long fieldId, double val) { diff --git a/core/java/com/android/internal/util/dump/DumpUtils.java b/core/java/com/android/internal/util/dump/DumpUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..0ee204e1acacea4f14bf23b8b4bf72e4d58dc717 --- /dev/null +++ b/core/java/com/android/internal/util/dump/DumpUtils.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util.dump; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.ComponentNameProto; + +public class DumpUtils { + /** + * Write a string to a proto if the string is not {@code null}. + * + * @param proto The proto to write to + * @param idName Clear text name of the proto-id + * @param id The proto-id of the string + * @param string The string to write + */ + public static void writeStringIfNotNull(@NonNull DualDumpOutputStream proto, String idName, + long id, @Nullable String string) { + if (string != null) { + proto.write(idName, id, string); + } + } + + /** + * Write a {@link ComponentName} to a proto. + * + * @param proto The proto to write to + * @param idName Clear text name of the proto-id + * @param id The proto-id of the component name + * @param component The component name to write + */ + public static void writeComponentName(@NonNull DualDumpOutputStream proto, String idName, + long id, @NonNull ComponentName component) { + long token = proto.start(idName, id); + proto.write("package_name", ComponentNameProto.PACKAGE_NAME, component.getPackageName()); + proto.write("class_name", ComponentNameProto.CLASS_NAME, component.getClassName()); + proto.end(token); + } +} diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 5e0a986b432b4e3ae82b716fd65b18cd205e89f6..02822869f4212d9556725df4c3a6b80c7ae9ad04 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -68,6 +68,7 @@ interface IInputMethodManager { void showInputMethodPickerFromClient(in IInputMethodClient client, int auxiliarySubtypeMode); void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId); + boolean isInputMethodPickerShownForTest(); void setInputMethod(in IBinder token, String id); void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype); void hideMySoftInput(in IBinder token, int flags); diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java index 74dbaba3204341ec5a0adfd10715336b0047286b..f05bd32ba2cd071e20586220e1cd8014b98d5700 100644 --- a/core/java/com/android/internal/view/InputBindResult.java +++ b/core/java/com/android/internal/view/InputBindResult.java @@ -139,6 +139,10 @@ public final class InputBindResult implements Parcelable { * @see com.android.server.wm.WindowManagerService#inputMethodClientHasFocus(IInputMethodClient) */ int ERROR_NOT_IME_TARGET_WINDOW = 11; + /** + * Indicates that focused view in the current window is not an editor. + */ + int ERROR_NO_EDITOR = 12; } @ResultCode @@ -258,6 +262,8 @@ public final class InputBindResult implements Parcelable { return "ERROR_NULL"; case ResultCode.ERROR_NO_IME: return "ERROR_NO_IME"; + case ResultCode.ERROR_NO_EDITOR: + return "ERROR_NO_EDITOR"; case ResultCode.ERROR_INVALID_PACKAGE_NAME: return "ERROR_INVALID_PACKAGE_NAME"; case ResultCode.ERROR_SYSTEM_NOT_READY: @@ -287,6 +293,10 @@ public final class InputBindResult implements Parcelable { * Predefined error object for {@link ResultCode#NO_IME}. */ public static final InputBindResult NO_IME = error(ResultCode.ERROR_NO_IME); + /** + * Predefined error object for {@link ResultCode#NO_EDITOR}. + */ + public static final InputBindResult NO_EDITOR = error(ResultCode.ERROR_NO_EDITOR); /** * Predefined error object for {@link ResultCode#ERROR_INVALID_PACKAGE_NAME}. */ diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 5673814ca3620511c59655010026f36d92d8702a..732534ccbcbed522568861198db39219c2993a95 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -66,6 +66,8 @@ interface ILockSettings { void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList); KeyChainSnapshot getKeyChainSnapshot(); byte[] generateAndStoreKey(String alias); + String generateKey(String alias, in byte[] account); + String getKey(String alias); void removeKey(String alias); void setSnapshotCreatedPendingIntent(in PendingIntent intent); Map getRecoverySnapshotVersions(); diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index 32a7a2dadddbb8cd9429196899b2c24f535aa1e6..7a248f2642745ceda6a19ae42f3c09da913009b4 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -118,6 +118,7 @@ public class LockPatternView extends View { private float mInProgressY = -1; private long mAnimatingPeriodStart; + private long[] mLineFadeStart = new long[9]; private DisplayMode mPatternDisplayMode = DisplayMode.Correct; private boolean mInputEnabled = true; @@ -596,12 +597,14 @@ public class LockPatternView extends View { } /** - * Clear the pattern lookup table. + * Clear the pattern lookup table. Also reset the line fade start times for + * the next attempt. */ private void clearPatternDrawLookup() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { mPatternDrawLookup[i][j] = false; + mLineFadeStart[i+j] = 0; } } } @@ -1136,7 +1139,8 @@ public class LockPatternView extends View { boolean anyCircles = false; float lastX = 0f; float lastY = 0f; - for (int i = 0; i < count; i++) { + long elapsedRealtime = SystemClock.elapsedRealtime(); + for (int i = 0; i < count; i++) { Cell cell = pattern.get(i); // only draw the part of the pattern stored in @@ -1147,16 +1151,26 @@ public class LockPatternView extends View { } anyCircles = true; + if (mLineFadeStart[i] == 0) { + mLineFadeStart[i] = SystemClock.elapsedRealtime(); + } + float centerX = getCenterXForColumn(cell.column); float centerY = getCenterYForRow(cell.row); if (i != 0) { + // Set this line segment to slowly fade over the next second. + int lineFadeVal = (int) Math.min((elapsedRealtime - + mLineFadeStart[i])/2f, 255f); + CellState state = mCellStates[cell.row][cell.column]; currentPath.rewind(); currentPath.moveTo(lastX, lastY); if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) { currentPath.lineTo(state.lineEndX, state.lineEndY); + mPathPaint.setAlpha((int) 255 - lineFadeVal ); } else { currentPath.lineTo(centerX, centerY); + mPathPaint.setAlpha((int) 255 - lineFadeVal ); } canvas.drawPath(currentPath, mPathPaint); } diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java index e3436e84da71580e2e426d0fe6774c535f17bca0..fb186693979d42fa138c042e2efdd306fe61f14b 100644 --- a/core/java/com/android/server/BootReceiver.java +++ b/core/java/com/android/server/BootReceiver.java @@ -35,6 +35,7 @@ import android.text.TextUtils; import android.util.AtomicFile; import android.util.EventLog; import android.util.Slog; +import android.util.StatsLog; import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; @@ -112,6 +113,8 @@ public class BootReceiver extends BroadcastReceiver { private static final String SHUTDOWN_METRICS_FILE = "/data/system/shutdown-metrics.txt"; private static final String SHUTDOWN_TRON_METRICS_PREFIX = "shutdown_"; + private static final String METRIC_SYSTEM_SERVER = "shutdown_system_server"; + private static final String METRIC_SHUTDOWN_TIME_START = "begin_shutdown"; @Override public void onReceive(final Context context, Intent intent) { @@ -401,6 +404,10 @@ public class BootReceiver extends BroadcastReceiver { } } if (!TextUtils.isEmpty(metricsStr)) { + String reboot = null; + String reason = null; + String start_time = null; + String duration = null; String[] array = metricsStr.split(","); for (String keyValueStr : array) { String[] keyValue = keyValueStr.split(":"); @@ -411,8 +418,19 @@ public class BootReceiver extends BroadcastReceiver { // Ignore keys that are not indended for tron if (keyValue[0].startsWith(SHUTDOWN_TRON_METRICS_PREFIX)) { logTronShutdownMetric(keyValue[0], keyValue[1]); + if (keyValue[0].equals(METRIC_SYSTEM_SERVER)) { + duration = keyValue[1]; + } + } + if (keyValue[0].equals("reboot")) { + reboot = keyValue[1]; + } else if (keyValue[0].equals("reason")) { + reason = keyValue[1]; + } else if (keyValue[0].equals(METRIC_SHUTDOWN_TIME_START)) { + start_time = keyValue[1]; } } + logStatsdShutdownAtom(reboot, reason, start_time, duration); } metricsFile.delete(); } @@ -430,6 +448,52 @@ public class BootReceiver extends BroadcastReceiver { } } + private static void logStatsdShutdownAtom( + String rebootStr, String reasonStr, String startStr, String durationStr) { + boolean reboot = false; + String reason = ""; + long start = 0; + long duration = 0; + + if (rebootStr != null) { + if (rebootStr.equals("y")) { + reboot = true; + } else if (!rebootStr.equals("n")) { + Slog.e(TAG, "Unexpected value for reboot : " + rebootStr); + } + } else { + Slog.e(TAG, "No value received for reboot"); + } + + if (reasonStr != null) { + reason = reasonStr; + } else { + Slog.e(TAG, "No value received for shutdown reason"); + } + + if (startStr != null) { + try { + start = Long.parseLong(startStr); + } catch (NumberFormatException e) { + Slog.e(TAG, "Cannot parse shutdown start time: " + startStr); + } + } else { + Slog.e(TAG, "No value received for shutdown start time"); + } + + if (durationStr != null) { + try { + duration = Long.parseLong(durationStr); + } catch (NumberFormatException e) { + Slog.e(TAG, "Cannot parse shutdown duration: " + startStr); + } + } else { + Slog.e(TAG, "No value received for shutdown duration"); + } + + StatsLog.write(StatsLog.SHUTDOWN_SEQUENCE_REPORTED, reboot, reason, start, duration); + } + private static void logFsShutdownTime() { File f = null; for (String fileName : LAST_KMSG_FILES) { diff --git a/core/java/com/android/server/backup/SliceBackupHelper.java b/core/java/com/android/server/backup/SliceBackupHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..8e5a5eecec89e53ce21de4395fa49fbfd56e64d4 --- /dev/null +++ b/core/java/com/android/server/backup/SliceBackupHelper.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.server.backup; + +import android.app.backup.BlobBackupHelper; +import android.app.slice.ISliceManager; +import android.content.Context; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.util.Log; +import android.util.Slog; + +public class SliceBackupHelper extends BlobBackupHelper { + static final String TAG = "SliceBackupHelper"; + static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + // Current version of the blob schema + static final int BLOB_VERSION = 1; + + // Key under which the payload blob is stored + static final String KEY_SLICES = "slices"; + + public SliceBackupHelper(Context context) { + super(BLOB_VERSION, KEY_SLICES); + // context is currently unused + } + + @Override + protected byte[] getBackupPayload(String key) { + byte[] newPayload = null; + if (KEY_SLICES.equals(key)) { + try { + ISliceManager sm = ISliceManager.Stub.asInterface( + ServiceManager.getService(Context.SLICE_SERVICE)); + // TODO: http://b/22388012 + newPayload = sm.getBackupPayload(UserHandle.USER_SYSTEM); + } catch (Exception e) { + // Treat as no data + Slog.e(TAG, "Couldn't communicate with slice manager"); + newPayload = null; + } + } + return newPayload; + } + + @Override + protected void applyRestoredPayload(String key, byte[] payload) { + if (DEBUG) Slog.v(TAG, "Got restore of " + key); + + if (KEY_SLICES.equals(key)) { + try { + ISliceManager sm = ISliceManager.Stub.asInterface( + ServiceManager.getService(Context.SLICE_SERVICE)); + // TODO: http://b/22388012 + sm.applyRestore(payload, UserHandle.USER_SYSTEM); + } catch (Exception e) { + Slog.e(TAG, "Couldn't communicate with slice manager"); + } + } + } + +} diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java index a96b5dd3ed70b9e95eb23b99795069ed2e03b4d2..47e7a0e745635ac96a3cc5f928640215b7ba1f4c 100644 --- a/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/core/java/com/android/server/backup/SystemBackupAgent.java @@ -51,6 +51,7 @@ public class SystemBackupAgent extends BackupAgentHelper { private static final String USAGE_STATS_HELPER = "usage_stats"; private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager"; private static final String ACCOUNT_MANAGER_HELPER = "account_manager"; + private static final String SLICES_HELPER = "slices"; // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME // are also used in the full-backup file format, so must not change unless steps are @@ -88,6 +89,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); + addHelper(SLICES_HELPER, new SliceBackupHelper(this)); super.onBackup(oldState, data, newState); } @@ -116,6 +118,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); + addHelper(SLICES_HELPER, new SliceBackupHelper(this)); super.onRestore(data, appVersionCode, newState); } diff --git a/core/java/com/android/server/net/OWNERS b/core/java/com/android/server/net/OWNERS index 6f77e04da3c0580c3fff9361596eb734e49b0436..ce50558bf4f6d6840fc672bdb89db8fad314213a 100644 --- a/core/java/com/android/server/net/OWNERS +++ b/core/java/com/android/server/net/OWNERS @@ -1,7 +1,6 @@ set noparent ek@google.com -hugobenichi@google.com jchalard@google.com lorenzo@google.com satk@google.com diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 93f95c634ae385e1d8e1affcb7ce6de36e99802e..33f80ce8ffb089d4663a5b84b9892c439f77aa24 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -164,6 +164,7 @@ cc_library_shared { "android_media_DeviceCallback.cpp", "android_media_JetPlayer.cpp", "android_media_MediaMetricsJNI.cpp", + "android_media_MicrophoneInfo.cpp", "android_media_RemoteDisplay.cpp", "android_media_ToneGenerator.cpp", "android_hardware_Camera.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index bf7a7794fcc6fed77529a7705603a8b4eb4e2d51..d20217386b1e3a9f316293950b14b506b102ff3a 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -104,6 +104,7 @@ extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv extern int register_android_media_AudioRecord(JNIEnv *env); extern int register_android_media_AudioSystem(JNIEnv *env); extern int register_android_media_AudioTrack(JNIEnv *env); +extern int register_android_media_MicrophoneInfo(JNIEnv *env); extern int register_android_media_JetPlayer(JNIEnv *env); extern int register_android_media_ToneGenerator(JNIEnv *env); @@ -765,18 +766,17 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) /* * Enable debugging only for apps forked from zygote. - * Set suspend=y to pause during VM init and use android ADB transport. */ if (zygote) { + // Set the JDWP provider and required arguments. By default let the runtime choose how JDWP is + // implemented. When this is not set the runtime defaults to not allowing JDWP. addOption("-XjdwpOptions:suspend=n,server=y"); + parseRuntimeOption("dalvik.vm.jdwp-provider", + jdwpProviderBuf, + "-XjdwpProvider:", + "default"); } - // Set the JDWP provider. By default let the runtime choose. - parseRuntimeOption("dalvik.vm.jdwp-provider", - jdwpProviderBuf, - "-XjdwpProvider:", - "default"); - parseRuntimeOption("dalvik.vm.lockprof.threshold", lockProfThresholdBuf, "-Xlockprofthreshold:"); @@ -1461,6 +1461,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_media_AudioSystem), REG_JNI(register_android_media_AudioTrack), REG_JNI(register_android_media_JetPlayer), + REG_JNI(register_android_media_MicrophoneInfo), REG_JNI(register_android_media_RemoteDisplay), REG_JNI(register_android_media_ToneGenerator), diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp index 0e562c03b7620b310067be70a07fe989cddc066b..ba56d592acef312ffd198177236f9b479c757597 100644 --- a/core/jni/android/graphics/AnimatedImageDrawable.cpp +++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp @@ -16,20 +16,21 @@ #include "GraphicsJNI.h" #include "ImageDecoder.h" -#include "core_jni_helpers.h" #include "Utils.h" +#include "core_jni_helpers.h" -#include -#include #include #include #include #include #include +#include +#include +#include using namespace android; -static jmethodID gAnimatedImageDrawable_postOnAnimationEndMethodID; +static jmethodID gAnimatedImageDrawable_onAnimationEndMethodID; // Note: jpostProcess holds a handle to the ImageDecoder. static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, @@ -85,6 +86,9 @@ static jlong AnimatedImageDrawable_nGetNativeFinalizer(JNIEnv* /*env*/, jobject return static_cast(reinterpret_cast(&AnimatedImageDrawable_destruct)); } +// Java's FINISHED relies on this being -1 +static_assert(SkAnimatedImage::kFinished == -1); + static jlong AnimatedImageDrawable_nDraw(JNIEnv* env, jobject /*clazz*/, jlong nativePtr, jlong canvasPtr) { auto* drawable = reinterpret_cast(nativePtr); @@ -115,17 +119,14 @@ static jboolean AnimatedImageDrawable_nIsRunning(JNIEnv* env, jobject /*clazz*/, return drawable->isRunning(); } -// Java's NOT_RUNNING relies on this being -2.0. -static_assert(SkAnimatedImage::kNotRunning == -2.0); - static jboolean AnimatedImageDrawable_nStart(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) { auto* drawable = reinterpret_cast(nativePtr); return drawable->start(); } -static void AnimatedImageDrawable_nStop(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) { +static jboolean AnimatedImageDrawable_nStop(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) { auto* drawable = reinterpret_cast(nativePtr); - drawable->stop(); + return drawable->stop(); } // Java's LOOP_INFINITE relies on this being the same. @@ -137,33 +138,63 @@ static void AnimatedImageDrawable_nSetLoopCount(JNIEnv* env, jobject /*clazz*/, drawable->setRepetitionCount(loopCount); } -class JniAnimationEndListener : public OnAnimationEndListener { +class InvokeListener : public MessageHandler { public: - JniAnimationEndListener(JNIEnv* env, jobject javaObject) { + InvokeListener(JNIEnv* env, jobject javaObject) { LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mJvm) != JNI_OK); - mJavaObject = env->NewGlobalRef(javaObject); + // Hold a weak reference to break a cycle that would prevent GC. + mWeakRef = env->NewWeakGlobalRef(javaObject); } - ~JniAnimationEndListener() override { + ~InvokeListener() override { auto* env = get_env_or_die(mJvm); - env->DeleteGlobalRef(mJavaObject); + env->DeleteWeakGlobalRef(mWeakRef); } - void onAnimationEnd() override { + virtual void handleMessage(const Message&) override { auto* env = get_env_or_die(mJvm); - env->CallVoidMethod(mJavaObject, gAnimatedImageDrawable_postOnAnimationEndMethodID); + jobject localRef = env->NewLocalRef(mWeakRef); + if (localRef) { + env->CallVoidMethod(localRef, gAnimatedImageDrawable_onAnimationEndMethodID); + } } private: JavaVM* mJvm; - jobject mJavaObject; + jweak mWeakRef; +}; + +class JniAnimationEndListener : public OnAnimationEndListener { +public: + JniAnimationEndListener(sp&& looper, JNIEnv* env, jobject javaObject) { + mListener = new InvokeListener(env, javaObject); + mLooper = std::move(looper); + } + + void onAnimationEnd() override { mLooper->sendMessage(mListener, 0); } + +private: + sp mListener; + sp mLooper; }; static void AnimatedImageDrawable_nSetOnAnimationEndListener(JNIEnv* env, jobject /*clazz*/, jlong nativePtr, jobject jdrawable) { auto* drawable = reinterpret_cast(nativePtr); - drawable->setOnAnimationEndListener(std::unique_ptr( - new JniAnimationEndListener(env, jdrawable))); + if (!jdrawable) { + drawable->setOnAnimationEndListener(nullptr); + } else { + sp looper = Looper::getForThread(); + if (!looper.get()) { + doThrowISE(env, + "Must set AnimatedImageDrawable's AnimationCallback on a thread with a " + "looper!"); + return; + } + + drawable->setOnAnimationEndListener( + std::make_unique(std::move(looper), env, jdrawable)); + } } static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) { @@ -172,6 +203,11 @@ static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/ return sizeof(drawable); } +static void AnimatedImageDrawable_nMarkInvisible(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) { + auto* drawable = reinterpret_cast(nativePtr); + drawable->markInvisible(); +} + static const JNINativeMethod gAnimatedImageDrawableMethods[] = { { "nCreate", "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate }, { "nGetNativeFinalizer", "()J", (void*) AnimatedImageDrawable_nGetNativeFinalizer }, @@ -181,15 +217,16 @@ static const JNINativeMethod gAnimatedImageDrawableMethods[] = { { "nSetColorFilter", "(JJ)V", (void*) AnimatedImageDrawable_nSetColorFilter }, { "nIsRunning", "(J)Z", (void*) AnimatedImageDrawable_nIsRunning }, { "nStart", "(J)Z", (void*) AnimatedImageDrawable_nStart }, - { "nStop", "(J)V", (void*) AnimatedImageDrawable_nStop }, + { "nStop", "(J)Z", (void*) AnimatedImageDrawable_nStop }, { "nSetLoopCount", "(JI)V", (void*) AnimatedImageDrawable_nSetLoopCount }, { "nSetOnAnimationEndListener", "(JLandroid/graphics/drawable/AnimatedImageDrawable;)V", (void*) AnimatedImageDrawable_nSetOnAnimationEndListener }, { "nNativeByteSize", "(J)J", (void*) AnimatedImageDrawable_nNativeByteSize }, + { "nMarkInvisible", "(J)V", (void*) AnimatedImageDrawable_nMarkInvisible }, }; int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) { jclass animatedImageDrawable_class = FindClassOrDie(env, "android/graphics/drawable/AnimatedImageDrawable"); - gAnimatedImageDrawable_postOnAnimationEndMethodID = GetMethodIDOrDie(env, animatedImageDrawable_class, "postOnAnimationEnd", "()V"); + gAnimatedImageDrawable_onAnimationEndMethodID = GetMethodIDOrDie(env, animatedImageDrawable_class, "onAnimationEnd", "()V"); return android::RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedImageDrawable", gAnimatedImageDrawableMethods, NELEM(gAnimatedImageDrawableMethods)); diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index dd3e6f02e9fed44b60c9efeed47bc4be25428535..937b3ffb9d6062c50f21ac28ecc1eb3a00d3da5b 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -44,11 +44,9 @@ namespace android { struct NativeFamilyBuilder { NativeFamilyBuilder(uint32_t langId, int variant) - : langId(langId), variant(static_cast(variant)), - allowUnsupportedFont(false) {} + : langId(langId), variant(static_cast(variant)) {} uint32_t langId; minikin::FontFamily::Variant variant; - bool allowUnsupportedFont; std::vector fonts; std::vector axes; }; @@ -70,22 +68,17 @@ static jlong FontFamily_create(jlong builderPtr) { } std::unique_ptr builder( reinterpret_cast(builderPtr)); + if (builder->fonts.empty()) { + return 0; + } std::shared_ptr family = std::make_shared( builder->langId, builder->variant, std::move(builder->fonts)); - if (family->getCoverage().length() == 0 && !builder->allowUnsupportedFont) { + if (family->getCoverage().length() == 0) { return 0; } return reinterpret_cast(new FontFamilyWrapper(std::move(family))); } -static void FontFamily_allowUnsupportedFont(jlong builderPtr) { - if (builderPtr == 0) { - return; - } - NativeFamilyBuilder* builder = reinterpret_cast(builderPtr); - builder->allowUnsupportedFont = true; -} - static void FontFamily_abort(jlong builderPtr) { NativeFamilyBuilder* builder = reinterpret_cast(builderPtr); delete builder; @@ -270,7 +263,6 @@ static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) { static const JNINativeMethod gFontFamilyMethods[] = { { "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder }, { "nCreateFamily", "(J)J", (void*)FontFamily_create }, - { "nAllowUnsupportedFont", "(J)V", (void*)FontFamily_allowUnsupportedFont }, { "nAbort", "(J)V", (void*)FontFamily_abort }, { "nUnrefFamily", "(J)V", (void*)FontFamily_unref }, { "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont }, diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp index 743a7efa2b24af1e041e95b555e41ade668ad741..e2ce1a465fd73faa31942f93d2770ee486e4897f 100644 --- a/core/jni/android/graphics/ImageDecoder.cpp +++ b/core/jni/android/graphics/ImageDecoder.cpp @@ -74,7 +74,8 @@ static jobject native_create(JNIEnv* env, std::unique_ptr stream) { // FIXME: Avoid parsing the whole image? const bool animated = codec->getFrameCount() > 1; - decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec)); + decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec), + SkAndroidCodec::ExifOrientationBehavior::kRespect); if (!decoder->mCodec.get()) { doThrowIOE(env, "Could not create AndroidCodec"); return nullptr; diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index c79f5bd96e99d15590185289eb5ce92856dc0770..12da27307adec33288d4144da25bce6255f1a220 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -36,6 +36,7 @@ #define ENCODING_AAC_ELD 15 #define ENCODING_AAC_XHE 16 #define ENCODING_AC4 17 +#define ENCODING_E_AC3_JOC 18 #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -80,6 +81,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC; // FIXME temporary value, needs addition of xHE-AAC case ENCODING_AC4: return AUDIO_FORMAT_AC4; + // case ENCODING_E_AC3_JOC: // FIXME Not defined on the native side yet + // return AUDIO_FORMAT_E_AC3_JOC; case ENCODING_DEFAULT: return AUDIO_FORMAT_DEFAULT; default: @@ -130,6 +133,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) // return ENCODING_AAC_XHE; case AUDIO_FORMAT_AC4: return ENCODING_AC4; + // case AUDIO_FORMAT_E_AC3_JOC: // FIXME Not defined on the native side yet + // return ENCODING_E_AC3_JOC; case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; default: diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index ebd16c7084ac579b61adcea9cd66ed1861139141..375d68b858240944af873847d8748d8f4b521c52 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -25,6 +25,8 @@ #include #include +#include +#include #include @@ -32,6 +34,7 @@ #include "android_media_AudioErrors.h" #include "android_media_DeviceCallback.h" #include "android_media_MediaMetricsJNI.h" +#include "android_media_MicrophoneInfo.h" // ---------------------------------------------------------------------------- @@ -41,6 +44,11 @@ using namespace android; static const char* const kClassPathName = "android/media/AudioRecord"; static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes"; +static jclass gArrayListClass; +static struct { + jmethodID add; +} gArrayListMethods; + struct audio_record_fields_t { // these fields provide access from C++ to the... jmethodID postNativeEventInJava; //... event post callback method @@ -784,6 +792,46 @@ android_media_AudioRecord_native_getMetrics(JNIEnv *env, jobject thiz) return mybundle; } +// ---------------------------------------------------------------------------- +static jint android_media_AudioRecord_get_active_microphones(JNIEnv *env, + jobject thiz, jobject jActiveMicrophones) { + if (jActiveMicrophones == NULL) { + ALOGE("jActiveMicrophones is null"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + if (!env->IsInstanceOf(jActiveMicrophones, gArrayListClass)) { + ALOGE("getActiveMicrophones not an arraylist"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + + sp lpRecorder = getAudioRecord(env, thiz); + if (lpRecorder == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioRecord pointer for getActiveMicrophones()"); + return (jint)AUDIO_JAVA_ERROR; + } + + jint jStatus = AUDIO_JAVA_SUCCESS; + std::vector activeMicrophones; + status_t status = lpRecorder->getActiveMicrophones(&activeMicrophones); + if (status != NO_ERROR) { + ALOGE_IF(status != NO_ERROR, "AudioRecord::getActiveMicrophones error %d", status); + jStatus = nativeToJavaStatus(status); + return jStatus; + } + + for (size_t i = 0; i < activeMicrophones.size(); i++) { + jobject jMicrophoneInfo; + jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &activeMicrophones[i]); + if (jStatus != AUDIO_JAVA_SUCCESS) { + return jStatus; + } + env->CallBooleanMethod(jActiveMicrophones, gArrayListMethods.add, jMicrophoneInfo); + env->DeleteLocalRef(jMicrophoneInfo); + } + return jStatus; +} + // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -824,6 +872,8 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioRecord_disableDeviceCallback}, {"native_get_timestamp", "(Landroid/media/AudioTimestamp;I)I", (void *)android_media_AudioRecord_get_timestamp}, + {"native_get_active_microphones", "(Ljava/util/ArrayList;)I", + (void *)android_media_AudioRecord_get_active_microphones}, }; // field names found in android/media/AudioRecord.java @@ -873,6 +923,10 @@ int register_android_media_AudioRecord(JNIEnv *env) javaAudioTimestampFields.fieldNanoTime = GetFieldIDOrDie(env, audioTimestampClass, "nanoTime", "J"); + jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); + gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); + gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); + return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 376a7971767798fca917840b8c064678b492bf38..adaff1fcfbcbda8509c2c4718d1532de91ec5fc8 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -21,17 +21,20 @@ #include #include +#include #include #include #include "core_jni_helpers.h" #include #include +#include #include #include #include #include "android_media_AudioFormat.h" #include "android_media_AudioErrors.h" +#include "android_media_MicrophoneInfo.h" // ---------------------------------------------------------------------------- @@ -143,7 +146,6 @@ static struct { jfieldID mSource; } gAudioAttributesFields; - static const char* const kEventHandlerClassPathName = "android/media/AudioPortEventHandler"; static struct { @@ -1158,7 +1160,6 @@ exit: return jStatus; } - static jint android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, jobject jPorts, jintArray jGeneration) @@ -1789,6 +1790,45 @@ android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, return AudioSystem::isOffloadSupported(format); } +static jint +android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMicrophonesInfo) +{ + ALOGV("getMicrophones"); + + if (jMicrophonesInfo == NULL) { + ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) { + ALOGE("getMicrophones not an arraylist"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + + jint jStatus; + std::vector microphones; + status_t status = AudioSystem::getMicrophones(µphones); + if (status != NO_ERROR) { + ALOGE_IF(status != NO_ERROR, "AudioSystem::getMicrophones error %d", status); + jStatus = nativeToJavaStatus(status); + return jStatus; + } + if (microphones.size() == 0) { + jStatus = (jint)AUDIO_JAVA_SUCCESS; + return jStatus; + } + for (size_t i = 0; i < microphones.size(); i++) { + jobject jMicrophoneInfo; + jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, µphones[i]); + if (jStatus != AUDIO_JAVA_SUCCESS) { + return jStatus; + } + env->CallBooleanMethod(jMicrophonesInfo, gArrayListMethods.add, jMicrophoneInfo); + env->DeleteLocalRef(jMicrophoneInfo); + } + + return jStatus; +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -1843,6 +1883,7 @@ static const JNINativeMethod gMethods[] = { {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported}, + {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones}, }; diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index afbc579136880955ae59e63371a603b684da0a90..61a22c144f1b1f76fc7b38c916356b3d34931864 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -1262,6 +1262,18 @@ static jobject android_media_AudioTrack_get_volume_shaper_state(JNIEnv *env, job return VolumeShaperHelper::convertStateToJobject(env, gVolumeShaperFields, state); } +static int android_media_AudioTrack_setPresentation( + JNIEnv *env, jobject thiz, jint presentationId, jint programId) { + sp lpTrack = getAudioTrack(env, thiz); + if (lpTrack == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "AudioTrack not initialized"); + return (jint)AUDIO_JAVA_ERROR; + } + + return (jint)lpTrack->selectPresentation((int)presentationId, (int)programId); +} + // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -1333,6 +1345,7 @@ static const JNINativeMethod gMethods[] = { {"native_getVolumeShaperState", "(I)Landroid/media/VolumeShaper$State;", (void *)android_media_AudioTrack_get_volume_shaper_state}, + {"native_setPresentation", "(II)I", (void *)android_media_AudioTrack_setPresentation}, }; diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9198cbe648eb02c0d5a2cb477ac324758276fd4c --- /dev/null +++ b/core/jni/android_media_MicrophoneInfo.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android_media_MicrophoneInfo.h" +#include "android_media_AudioErrors.h" +#include "core_jni_helpers.h" + +using namespace android; + +static jclass gArrayListClass; +static jmethodID gArrayListCstor; +static struct { + jmethodID add; +} gArrayListMethods; + +static jclass gFloatClass; +static jmethodID gFloatCstor; + +static jclass gFloatArrayClass; + +static jclass gIntegerClass; +static jmethodID gIntegerCstor; + +static jclass gMicrophoneInfoClass; +static jmethodID gMicrophoneInfoCstor; + +static jclass gMicrophoneInfoCoordinateClass; +static jmethodID gMicrophoneInfoCoordinateCstor; + +static jclass gPairClass; +static jmethodID gPairCstor; + +namespace android { + +jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo, + const media::MicrophoneInfo *microphoneInfo) +{ + jint jStatus = (jint)AUDIO_JAVA_SUCCESS; + jstring jDeviceId = NULL; + jstring jAddress = NULL; + jobject jGeometricLocation = NULL; + jobject jOrientation = NULL; + jobject jFrequencyResponses = NULL; + jobject jChannelMappings = NULL; + + jDeviceId = env->NewStringUTF(String8(microphoneInfo->getDeviceId()).string()); + jAddress = env->NewStringUTF(String8(microphoneInfo->getAddress()).string()); + if (microphoneInfo->getGeometricLocation().size() != 3 || + microphoneInfo->getOrientation().size() != 3) { + jStatus = nativeToJavaStatus(BAD_VALUE); + goto exit; + } + jGeometricLocation = env->NewObject(gMicrophoneInfoCoordinateClass, + gMicrophoneInfoCoordinateCstor, + NULL, + microphoneInfo->getGeometricLocation()[0], + microphoneInfo->getGeometricLocation()[1], + microphoneInfo->getGeometricLocation()[2]); + jOrientation = env->NewObject(gMicrophoneInfoCoordinateClass, + gMicrophoneInfoCoordinateCstor, + NULL, + microphoneInfo->getOrientation()[0], + microphoneInfo->getOrientation()[1], + microphoneInfo->getOrientation()[2]); + // Create a list of Pair for frequency response. + if (microphoneInfo->getFrequencyResponses().size() != 2 || + microphoneInfo->getFrequencyResponses()[0].size() != + microphoneInfo->getFrequencyResponses()[1].size()) { + jStatus = nativeToJavaStatus(BAD_VALUE); + goto exit; + } + jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor); + for (size_t i = 0; i < microphoneInfo->getFrequencyResponses()[0].size(); i++) { + jobject jFrequency = env->NewObject(gFloatClass, gFloatCstor, + microphoneInfo->getFrequencyResponses()[0][i]); + jobject jResponse = env->NewObject(gFloatClass, gFloatCstor, + microphoneInfo->getFrequencyResponses()[1][i]); + jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse); + env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse); + env->DeleteLocalRef(jFrequency); + env->DeleteLocalRef(jResponse); + env->DeleteLocalRef(jFrequencyResponse); + } + // Create a list of Pair for channel mapping. + if (microphoneInfo->getChannelMapping().size() != AUDIO_CHANNEL_COUNT_MAX) { + jStatus = nativeToJavaStatus(BAD_VALUE); + goto exit; + } + jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor); + for (size_t i = 0; i < microphoneInfo->getChannelMapping().size(); i++) { + int channelMappingType = microphoneInfo->getChannelMapping()[i]; + if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) { + jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i); + jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor, + channelMappingType); + jobject jChannelMapping = env->NewObject(gPairClass, gPairCstor, + jChannelIndex, jChannelMappingType); + env->CallBooleanMethod(jChannelMappings, gArrayListMethods.add, jChannelMapping); + env->DeleteLocalRef(jChannelIndex); + env->DeleteLocalRef(jChannelMappingType); + env->DeleteLocalRef(jChannelMapping); + } + } + *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId, + microphoneInfo->getType(), jAddress, + microphoneInfo->getDeviceLocation(), + microphoneInfo->getDeviceGroup(), + microphoneInfo->getIndexInTheGroup(), + jGeometricLocation, jOrientation, + jFrequencyResponses, jChannelMappings, + microphoneInfo->getSensitivity(), + microphoneInfo->getMaxSpl(), + microphoneInfo->getMinSpl(), + microphoneInfo->getDirectionality()); + +exit: + if (jDeviceId != NULL) { + env->DeleteLocalRef(jDeviceId); + } + if (jAddress != NULL) { + env->DeleteLocalRef(jAddress); + } + if (jFrequencyResponses != NULL) { + env->DeleteLocalRef(jFrequencyResponses); + } + if (jChannelMappings != NULL) { + env->DeleteLocalRef(jChannelMappings); + } + if (jGeometricLocation != NULL) { + env->DeleteLocalRef(jGeometricLocation); + } + if (jOrientation != NULL) { + env->DeleteLocalRef(jOrientation); + } + return jStatus; +} + +} + +int register_android_media_MicrophoneInfo(JNIEnv *env) +{ + jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); + gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); + gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "", "()V"); + gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); + + jclass floatClass = FindClassOrDie(env, "java/lang/Float"); + gFloatClass = MakeGlobalRefOrDie(env, floatClass); + gFloatCstor = GetMethodIDOrDie(env, floatClass, "", "(F)V"); + + jclass floatArrayClass = FindClassOrDie(env, "[F"); + gFloatArrayClass = MakeGlobalRefOrDie(env, floatArrayClass); + + jclass integerClass = FindClassOrDie(env, "java/lang/Integer"); + gIntegerClass = MakeGlobalRefOrDie(env, integerClass); + gIntegerCstor = GetMethodIDOrDie(env, integerClass, "", "(I)V"); + + jclass microphoneInfoClass = FindClassOrDie(env, "android/media/MicrophoneInfo"); + gMicrophoneInfoClass = MakeGlobalRefOrDie(env, microphoneInfoClass); + gMicrophoneInfoCstor = GetMethodIDOrDie(env, microphoneInfoClass, "", + "(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V"); + + jclass microphoneInfoCoordinateClass = FindClassOrDie( + env, "android/media/MicrophoneInfo$Coordinate3F"); + gMicrophoneInfoCoordinateClass = MakeGlobalRefOrDie(env, microphoneInfoCoordinateClass); + gMicrophoneInfoCoordinateCstor = GetMethodIDOrDie(env, microphoneInfoCoordinateClass, "", + "(Landroid/media/MicrophoneInfo;FFF)V"); + + jclass pairClass = FindClassOrDie(env, "android/util/Pair"); + gPairClass = MakeGlobalRefOrDie(env, pairClass); + gPairCstor = GetMethodIDOrDie(env, pairClass, "", "(Ljava/lang/Object;Ljava/lang/Object;)V"); + + return 0; +} diff --git a/core/jni/android_media_MicrophoneInfo.h b/core/jni/android_media_MicrophoneInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..241b6d05b724d4065ab608ba2c1b2373fa07209d --- /dev/null +++ b/core/jni/android_media_MicrophoneInfo.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_MEDIA_MICROPHONEINFO_H +#define ANDROID_MEDIA_MICROPHONEINFO_H + +#include +#include + +#include "jni.h" + +namespace android { + +// Conversion from C++ MicrophoneInfo object to Java MicrophoneInfo object + +extern jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo, + const media::MicrophoneInfo *microphoneInfo); +} // namespace android + +#endif \ No newline at end of file diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android_text_MeasuredParagraph.cpp index dddddbbb37960d8430cf8cd34f028c4a7d6a7c7d..d33337dabae0865cd2ffdc2f1ae554ca05ccdd37 100644 --- a/core/jni/android_text_MeasuredParagraph.cpp +++ b/core/jni/android_text_MeasuredParagraph.cpp @@ -72,8 +72,7 @@ static void nAddStyleRun(JNIEnv* /* unused */, jclass /* unused */, jlong builde Paint* paint = toPaint(paintPtr); const Typeface* typeface = Typeface::resolveDefault(paint->getAndroidTypeface()); minikin::MinikinPaint minikinPaint = MinikinUtils::prepareMinikinPaint(paint, typeface); - toBuilder(builderPtr)->addStyleRun(start, end, std::move(minikinPaint), - typeface->fFontCollection, isRtl); + toBuilder(builderPtr)->addStyleRun(start, end, std::move(minikinPaint), isRtl); } // Regular JNI diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 37ff8c8cefd2f62540263d7d606c7a55e4d5d8d3..8770d788fc372f537c3f66c2b01bb9c8a44b1d4b 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -174,8 +174,25 @@ static jboolean android_view_RenderNode_hasShadow(jlong renderNodePtr) { return renderNode->stagingProperties().hasShadow(); } -static jboolean android_view_RenderNode_setShadowColor(jlong renderNodePtr, jint shadowColor) { - return SET_AND_DIRTY(setShadowColor, static_cast(shadowColor), RenderNode::GENERIC); +static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) { + return SET_AND_DIRTY(setSpotShadowColor, + static_cast(shadowColor), RenderNode::GENERIC); +} + +static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast(renderNodePtr); + return renderNode->stagingProperties().getSpotShadowColor(); +} + +static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr, + jint shadowColor) { + return SET_AND_DIRTY(setAmbientShadowColor, + static_cast(shadowColor), RenderNode::GENERIC); +} + +static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast(renderNodePtr); + return renderNode->stagingProperties().getAmbientShadowColor(); } static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr, @@ -575,7 +592,10 @@ static const JNINativeMethod gMethods[] = { { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow }, - { "nSetShadowColor", "(JI)Z", (void*) android_view_RenderNode_setShadowColor }, + { "nSetSpotShadowColor", "(JI)Z", (void*) android_view_RenderNode_setSpotShadowColor }, + { "nGetSpotShadowColor", "(J)I", (void*) android_view_RenderNode_getSpotShadowColor }, + { "nSetAmbientShadowColor","(JI)Z", (void*) android_view_RenderNode_setAmbientShadowColor }, + { "nGetAmbientShadowColor","(J)I", (void*) android_view_RenderNode_getAmbientShadowColor }, { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, { "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip }, diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 421e0de52cc0a93bda3c2027fde3ac42a9cff8ce..f5c09fd316de9fac6a236d279a1caba8303ba678 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -524,15 +524,15 @@ static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeOb static jint nativeSetSharedBufferModeEnabled(JNIEnv* env, jclass clazz, jlong nativeObject, jboolean enabled) { Surface* surface = reinterpret_cast(nativeObject); - return ((ANativeWindow*) nativeObject)->perform(surface, - NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, enabled); + ANativeWindow* anw = static_cast(surface); + return anw->perform(surface, NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, int(enabled)); } static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeObject, jboolean enabled) { Surface* surface = reinterpret_cast(nativeObject); - return ((ANativeWindow*) nativeObject)->perform(surface, - NATIVE_WINDOW_SET_AUTO_REFRESH, enabled); + ANativeWindow* anw = static_cast(surface); + return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled)); } namespace uirenderer { diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 13e6fcdc842617b4b596cecbacc204dc75e96ce1..32945bfbceb149d1718871590d498842dfc6c8ce 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -141,32 +141,45 @@ static void SigChldHandler(int /*signal_number*/) { errno = saved_errno; } -// Configures the SIGCHLD handler for the zygote process. This is configured -// very late, because earlier in the runtime we may fork() and exec() -// other processes, and we want to waitpid() for those rather than +// Configures the SIGCHLD/SIGHUP handlers for the zygote process. This is +// configured very late, because earlier in the runtime we may fork() and +// exec() other processes, and we want to waitpid() for those rather than // have them be harvested immediately. // +// Ignore SIGHUP because all processes forked by the zygote are in the same +// process group as the zygote and we don't want to be notified if we become +// an orphaned group and have one or more stopped processes. This is not a +// theoretical concern : +// - we can become an orphaned group if one of our direct descendants forks +// and is subsequently killed before its children. +// - crash_dump routinely STOPs the process it's tracing. +// +// See issues b/71965619 and b/25567761 for further details. +// // This ends up being called repeatedly before each fork(), but there's // no real harm in that. -static void SetSigChldHandler() { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SigChldHandler; +static void SetSignalHandlers() { + struct sigaction sig_chld = {}; + sig_chld.sa_handler = SigChldHandler; - int err = sigaction(SIGCHLD, &sa, NULL); - if (err < 0) { + if (sigaction(SIGCHLD, &sig_chld, NULL) < 0) { ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); } + + struct sigaction sig_hup = {}; + sig_hup.sa_handler = SIG_IGN; + if (sigaction(SIGHUP, &sig_hup, NULL) < 0) { + ALOGW("Error setting SIGHUP handler: %s", strerror(errno)); + } } // Sets the SIGCHLD handler back to default behavior in zygote children. -static void UnsetSigChldHandler() { +static void UnsetChldSignalHandler() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; - int err = sigaction(SIGCHLD, &sa, NULL); - if (err < 0) { + if (sigaction(SIGCHLD, &sa, NULL) < 0) { ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno)); } } @@ -505,7 +518,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra bool is_system_server, jintArray fdsToClose, jintArray fdsToIgnore, jstring instructionSet, jstring dataDir) { - SetSigChldHandler(); + SetSignalHandlers(); sigset_t sigchld; sigemptyset(&sigchld); @@ -682,7 +695,8 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra delete se_info; delete se_name; - UnsetSigChldHandler(); + // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers). + UnsetChldSignalHandler(); env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, instructionSet); diff --git a/core/proto/android/app/window_configuration.proto b/core/proto/android/app/window_configuration.proto index 4d748e8fb1da15e63114538c355b324d7b2a8bad..1e8ace4fa06b9d660fe0d5f956a86d6c875bd7cc 100644 --- a/core/proto/android/app/window_configuration.proto +++ b/core/proto/android/app/window_configuration.proto @@ -21,9 +21,12 @@ option java_multiple_files = true; package android.app; import "frameworks/base/core/proto/android/graphics/rect.proto"; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; /** Proto representation for WindowConfiguration.java class. */ message WindowConfigurationProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + optional .android.graphics.RectProto app_bounds = 1; optional int32 windowing_mode = 2; optional int32 activity_type = 3; diff --git a/core/proto/android/media/audioattributes.proto b/core/proto/android/media/audioattributes.proto index 860d60807c0e4c13297a00f06498f7652ae8404d..ef04720405f5aebfb1dfea85678cc3b359449408 100644 --- a/core/proto/android/media/audioattributes.proto +++ b/core/proto/android/media/audioattributes.proto @@ -20,15 +20,19 @@ option java_multiple_files = true; package android.media; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + /** * An android.media.AudioAttributes object. */ message AudioAttributesProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + optional Usage usage = 1; optional ContentType content_type = 2; // Bit representation of set flags. optional int32 flags = 3; - repeated string tags = 4; + repeated string tags = 4 [ (android.privacy).dest = DEST_EXPLICIT ]; } enum ContentType { diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index 3ec6f057af882b59eda3d7a9d60f7d6fa6d20009..0b0ed8386c60bfcbd5345b16198cbb242a9e20c8 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -16,7 +16,6 @@ syntax = "proto2"; option java_multiple_files = true; -option java_outer_classname = "IncidentProtoMetadata"; import "frameworks/base/core/proto/android/os/batterytype.proto"; import "frameworks/base/core/proto/android/os/cpufreq.proto"; @@ -43,6 +42,7 @@ import "frameworks/base/core/proto/android/service/notification.proto"; import "frameworks/base/core/proto/android/service/package.proto"; import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/service/procstats.proto"; +import "frameworks/base/core/proto/android/service/usb.proto"; import "frameworks/base/core/proto/android/util/event_log_tags.proto"; import "frameworks/base/core/proto/android/util/log.proto"; import "frameworks/base/libs/incident/proto/android/os/header.proto"; @@ -255,4 +255,9 @@ message IncidentProto { (section).type = SECTION_DUMPSYS, (section).args = "jobscheduler --proto" ]; + + optional android.service.usb.UsbServiceDumpProto usb = 3021 [ + (section).type = SECTION_DUMPSYS, + (section).args = "usb --proto" + ]; } diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto index bfd575a5b18d6502802b4e036b6933ec85e5cddb..ff0f4fd4d3ac63215dbf434353ea40ae94949fe2 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -208,7 +208,7 @@ message GlobalSettingsProto { optional SettingProto wifi_on = 136 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto wifi_scan_always_available = 137 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto wifi_wakeup_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_wakeup_available = 305 [ (android.privacy).dest = DEST_AUTOMATIC ]; + reserved 305; // Removed wifi_wakeup_available optional SettingProto network_scoring_ui_enabled = 306 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto speed_label_cache_eviction_age_millis = 307 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto recommended_network_evaluator_cache_expiry_ms = 308 [ (android.privacy).dest = DEST_AUTOMATIC ]; diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto index aa2663fa2cc4c105057568d81e79c51ff5ccdcb2..0342c9c8952705639c16606335aa1ce38e461586 100644 --- a/core/proto/android/server/alarmmanagerservice.proto +++ b/core/proto/android/server/alarmmanagerservice.proto @@ -27,6 +27,7 @@ package com.android.server; option java_multiple_files = true; +// next ID: 43 message AlarmManagerServiceProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; @@ -114,7 +115,14 @@ message AlarmManagerServiceProto { optional int32 uid = 1; // In the 'elapsed' timebase. optional int64 time_ms = 2; + + // Time when the next while-idle is allowed, in the 'elapsed' timebase. + optional int64 next_allowed_ms = 3; } + + // Whether the short or long while-idle timeout should be used for each UID. + repeated int32 use_allow_while_idle_short_time = 42; + // For each uid, this is the last time we dispatched an "allow while idle" // alarm, used to determine the earliest we can dispatch the next such alarm. repeated LastAllowWhileIdleDispatch last_allow_while_idle_dispatch_times = 36; diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/forceappstandbytracker.proto index d0fd0b4bbc4b9cdb8029a3b41e83955d16e6e456..5296e4764f0cd2fb260206f722835debc1c7f203 100644 --- a/core/proto/android/server/forceappstandbytracker.proto +++ b/core/proto/android/server/forceappstandbytracker.proto @@ -17,22 +17,26 @@ syntax = "proto2"; import "frameworks/base/core/proto/android/server/statlogger.proto"; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; package com.android.server; option java_multiple_files = true; -import "frameworks/base/libs/incident/proto/android/privacy.proto"; - // Dump from com.android.server.ForceAppStandbyTracker. +// +// Next ID: 12 message ForceAppStandbyTrackerProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; // Whether all apps are forced standby or not. optional bool force_all_apps_standby = 1; + // UIDs currently active. + repeated int32 active_uids = 2; + // UIDs currently in the foreground. - repeated int32 foreground_uids = 2; + repeated int32 foreground_uids = 11; // App ids that are in power-save whitelist. repeated int32 power_save_whitelist_app_ids = 3; @@ -62,6 +66,8 @@ message ForceAppStandbyTrackerProto { optional StatLoggerProto stats = 9; message ExemptedPackage { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + optional int32 userId = 1; optional string package_name = 2; } diff --git a/core/proto/android/server/intentresolver.proto b/core/proto/android/server/intentresolver.proto index 60c060c02b1b6742828d6cfa49377da70b4ab020..0ada89533cb4ee58013a282284ba8d3fcfb153d6 100644 --- a/core/proto/android/server/intentresolver.proto +++ b/core/proto/android/server/intentresolver.proto @@ -19,9 +19,15 @@ option java_multiple_files = true; package com.android.server; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + message IntentResolverProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + message ArrayMapEntry { + option (.android.msg_privacy).dest = DEST_EXPLICIT; + optional string key = 1; repeated string values = 2; } diff --git a/core/proto/android/server/statlogger.proto b/core/proto/android/server/statlogger.proto index fa430d8264d0e0c943eb828fce389cdaaf87fdce..2ae526a599663ce154268f1215da86af4a7c2dc0 100644 --- a/core/proto/android/server/statlogger.proto +++ b/core/proto/android/server/statlogger.proto @@ -20,8 +20,12 @@ package com.android.server; option java_multiple_files = true; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + // Dump from StatLogger. message StatLoggerProto { + option (.android.msg_privacy).dest = DEST_EXPLICIT; + message Event { optional int32 eventId = 1; optional string label = 2; diff --git a/core/proto/android/server/wirelesschargerdetector.proto b/core/proto/android/server/wirelesschargerdetector.proto index 89cf2f8900fed33965bae0ddb133c2abeb9c748a..2118deb6edeb0d42e85fde428ef0cbc1a4ab933e 100644 --- a/core/proto/android/server/wirelesschargerdetector.proto +++ b/core/proto/android/server/wirelesschargerdetector.proto @@ -19,8 +19,14 @@ package com.android.server.power; option java_multiple_files = true; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + message WirelessChargerDetectorProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + message VectorProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + optional float x = 1; optional float y = 2; optional float z = 3; diff --git a/core/proto/android/service/enums.proto b/core/proto/android/service/enums.proto new file mode 100644 index 0000000000000000000000000000000000000000..b64e685104b7c1f2cf6a1991e0f0afcc3e0811bf --- /dev/null +++ b/core/proto/android/service/enums.proto @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package android.service; + +option java_outer_classname = "ServiceProtoEnums"; +option java_multiple_files = true; + +enum UsbEndPointType { + USB_ENDPOINT_TYPE_XFER_CONTROL = 0; + USB_ENDPOINT_TYPE_XFER_ISOC = 1; + USB_ENDPOINT_TYPE_XFER_BULK = 2; + USB_ENDPOINT_TYPE_XFER_INT = 3; +} + +enum UsbEndPointDirection { + USB_ENDPOINT_DIR_OUT = 0; + USB_ENDPOINT_DIR_IN = 0x80; +} + +enum UsbConnectionRecordMode { + USB_CONNECTION_RECORD_MODE_CONNECT = 0; + USB_CONNECTION_RECORD_MODE_CONNECT_BADPARSE = 1; + USB_CONNECTION_RECORD_MODE_CONNECT_BADDEVICE = 2; + USB_CONNECTION_RECORD_MODE_DISCONNECT = -1; +} \ No newline at end of file diff --git a/core/proto/android/service/network_watchlist.proto b/core/proto/android/service/network_watchlist.proto new file mode 100644 index 0000000000000000000000000000000000000000..fb03b93974aadd4214a15ef65d0edfa95d715f4d --- /dev/null +++ b/core/proto/android/service/network_watchlist.proto @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package com.android.service; + +option java_multiple_files = true; + +// It will be used by com.android.server.net.watchlist.ReportEncoder to +// generate network watchlist report. +message NetworkWatchlistReportProto { + + optional int32 report_version = 1; + + optional string watchlist_config_hash = 2; + + repeated NetworkWatchlistAppResultProto app_result = 3; +} + +message NetworkWatchlistAppResultProto { + optional string app_digest = 1; + optional bool encoded_result = 2; +} diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto index 9013a23664f69cc602f6cf385e6519a533f6a6e1..5c40e5fe346f21a6eedba8f88335f227462583a7 100644 --- a/core/proto/android/service/notification.proto +++ b/core/proto/android/service/notification.proto @@ -50,7 +50,7 @@ message NotificationServiceDumpProto { message NotificationRecordProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; - optional string key = 1 [ (.android.privacy).dest = DEST_EXPLICIT ]; + optional string key = 1; enum State { ENQUEUED = 0; @@ -88,7 +88,7 @@ message ManagedServiceInfoProto { message ManagedServicesProto { option (android.msg_privacy).dest = DEST_AUTOMATIC; - optional string caption = 1 [ (.android.privacy).dest = DEST_EXPLICIT ]; + optional string caption = 1; message ServiceProto { option (android.msg_privacy).dest = DEST_AUTOMATIC; diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto new file mode 100644 index 0000000000000000000000000000000000000000..b60c569952236012e02a1578c487c29581d86964 --- /dev/null +++ b/core/proto/android/service/usb.proto @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package android.service.usb; + +option java_multiple_files = true; +option java_outer_classname = "UsbServiceProto"; + +import "frameworks/base/core/proto/android/content/component_name.proto"; +import "frameworks/base/core/proto/android/service/enums.proto"; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + +message UsbServiceDumpProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbDeviceManagerProto device_manager = 1; + optional UsbHostManagerProto host_manager = 2; + optional UsbPortManagerProto port_manager = 3; + optional UsbAlsaManagerProto alsa_manager = 4; + optional UsbSettingsManagerProto settings_manager = 5; +} + +message UsbDeviceManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbHandlerProto handler = 1; + optional UsbDebuggingManagerProto debugging_manager = 2; +} + +message UsbHandlerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + /* Same as android.hardware.usb.gadget.V1_0.GadgetFunction.* */ + enum Function { + FUNCTION_ADB = 1; + FUNCTION_ACCESSORY = 2; + FUNCTION_MTP = 4; + FUNCTION_MIDI = 8; + FUNCTION_PTP = 16; + FUNCTION_RNDIS = 32; + FUNCTION_AUDIO_SOURCE = 64; + } + + repeated Function current_functions = 1; + optional bool current_functions_applied = 2; + repeated Function screen_unlocked_functions = 3; + optional bool screen_locked = 4; + optional bool connected = 5; + optional bool configured = 6; + optional UsbAccessoryProto current_accessory = 7; + optional bool host_connected = 8; + optional bool source_power = 9; + optional bool sink_power = 10; + optional bool usb_charging = 11; + optional bool hide_usb_notification = 12; + optional bool audio_accessory_connected = 13; + optional bool adb_enabled = 14; + optional string kernel_state = 15; + optional string kernel_function_list = 16; +} + +message UsbAccessoryProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string manufacturer = 1; + optional string model = 2; + optional string description = 3; + optional string version = 4; + optional string uri = 5; + optional string serial = 6 [ (android.privacy).dest = DEST_EXPLICIT ]; +} + +message UsbDebuggingManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool connected_to_adb = 1; + optional string last_key_recevied = 2 [ (android.privacy).dest = DEST_EXPLICIT ]; + optional string user_keys = 3 [ (android.privacy).dest = DEST_LOCAL ]; + optional string system_keys = 4 [ (android.privacy).dest = DEST_LOCAL ]; +} + +message UsbHostManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional android.content.ComponentNameProto default_usb_host_connection_handler = 1; + repeated UsbDeviceProto devices = 2; + optional int32 num_connects = 3; + repeated UsbConnectionRecordProto connections = 4; +} + +message UsbDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string name = 1; + optional int32 vendor_id = 2; + optional int32 product_id = 3; + optional int32 class = 4; + optional int32 subclass = 5; + optional int32 protocol = 6; + optional string manufacturer_name = 7; + optional string product_name = 8; + optional string version = 9; + optional string serial_number = 10 [ (android.privacy).dest = DEST_EXPLICIT ]; + repeated UsbConfigurationProto configurations = 11; +} + +message UsbConfigurationProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 id = 1; + optional string name = 2; + optional uint32 attributes = 3; + optional int32 max_power = 4; + repeated UsbInterfaceProto interfaces = 5; +} + +message UsbInterfaceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 id = 1; + optional int32 alternate_settings = 2; + optional string name = 3; + optional int32 class = 4; + optional int32 subclass = 5; + optional int32 protocol = 6; + repeated UsbEndPointProto endpoints = 7; +} + +message UsbEndPointProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 endpoint_number = 1; + optional android.service.UsbEndPointDirection direction = 2; + optional int32 address = 3; + optional android.service.UsbEndPointType type = 4; + optional uint32 attributes = 5; + optional int32 max_packet_size = 6; + optional int32 interval = 7; +} + +message UsbConnectionRecordProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string device_address = 1; + optional android.service.UsbConnectionRecordMode mode = 2; + optional int64 timestamp = 3; + optional int32 manufacturer = 4; + optional int32 product = 5; + optional UsbIsHeadsetProto is_headset = 6; +} + +message UsbIsHeadsetProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool in = 1; + optional bool out = 2; +} + +message UsbPortManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool is_simulation_active = 1; + repeated UsbPortInfoProto usb_ports = 2; +} + +message UsbPortInfoProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbPortProto port = 1; + optional UsbPortStatusProto status = 2; + optional bool can_change_mode = 3; + optional bool can_change_power_role = 4; + optional bool can_change_data_role = 5; +} + +message UsbPortProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + /* Same as android.hardware.usb.V1_1.Constants.PortMode_1_1 */ + enum Mode { + MODE_NONE = 0; + MODE_UFP = 1; + MODE_DFP = 2; + MODE_DRP = 3; + MODE_AUDIO_ACCESSORY = 4; + MODE_DEBUG_ACCESSORY = 8; + } + + optional string id = 1; + repeated Mode supported_modes = 2; +} + +message UsbPortStatusProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + /* Same as android.hardware.usb.V1_0.Constants.PortPowerRole */ + enum PowerRole { + POWER_ROLE_NONE = 0; + POWER_ROLE_SOURCE = 1; + POWER_ROLE_SINK = 2; + } + + /* Same as android.hardware.usb.V1_0.Constants.PortDataRole */ + enum DataRole { + DATA_ROLE_NONE = 0; + DATA_ROLE_HOST = 1; + DATA_ROLE_DEVICE = 2; + } + + optional bool connected = 1; + optional UsbPortProto.Mode current_mode = 2; + optional PowerRole power_role = 3; + optional DataRole data_role = 4; + repeated UsbPortStatusRoleCombinationProto role_combinations = 5; +} + +message UsbPortStatusRoleCombinationProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbPortStatusProto.PowerRole power_role = 1; + optional UsbPortStatusProto.DataRole data_role = 2; +} + +message UsbAlsaManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 cards_parser = 1; + repeated UsbAlsaDeviceProto alsa_devices = 2; + repeated UsbMidiDeviceProto midi_devices = 3; +} + +message UsbAlsaDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 card = 1; + optional int32 device = 2; + optional string name = 3; + optional bool has_playback = 4; + optional bool has_capture = 5; + optional string address = 6; +} + +message UsbMidiDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 card = 1; + optional int32 device = 2; + optional string device_address = 3; +} + +message UsbSettingsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + repeated UsbUserSettingsManagerProto user_settings = 1; + repeated UsbProfileGroupSettingsManagerProto profile_group_settings = 2; +} + +message UsbUserSettingsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 user_id = 1; + repeated UsbSettingsDevicePermissionProto device_permissions = 2; + repeated UsbSettingsAccessoryPermissionProto accessory_permissions = 3; +} + +message UsbSettingsDevicePermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string device_name = 1; + repeated int32 uids = 2; +} + +message UsbSettingsAccessoryPermissionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string accessory_description = 1; + repeated int32 uids = 2; +} + +message UsbProfileGroupSettingsManagerProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 parent_user_id = 1; + repeated UsbSettingsDevicePreferenceProto device_preferences = 2; + repeated UsbSettingsAccessoryPreferenceProto accessory_preferences = 3; +} + +message UsbSettingsDevicePreferenceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbDeviceFilterProto filter = 1; + optional UserPackageProto user_package = 2; +} + +message UsbDeviceFilterProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 vendor_id = 1; + optional int32 product_id = 2; + optional int32 class = 3; + optional int32 subclass = 4; + optional int32 protocol = 5; + optional string manufacturer_name = 6; + optional string product_name = 7; + optional string serial_number = 8 [ (android.privacy).dest = DEST_EXPLICIT ]; +} + +message UserPackageProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 user_id = 1; + optional string package_name =2; +} + +message UsbSettingsAccessoryPreferenceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional UsbAccessoryFilterProto filter = 1; + optional UserPackageProto user_package = 2; +} + +message UsbAccessoryFilterProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string manufacturer = 1; + optional string model = 2; + optional string version = 3; +} \ No newline at end of file diff --git a/core/proto/android/util/event_log_tags.proto b/core/proto/android/util/event_log_tags.proto index cb039be55b8519710a1cf69e2967e3886036a098..457219fde835bf71dd0d7a99a7aee19269a1380e 100644 --- a/core/proto/android/util/event_log_tags.proto +++ b/core/proto/android/util/event_log_tags.proto @@ -19,17 +19,25 @@ package android.util; option java_multiple_files = true; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + // Proto representation of event.logtags. // Usually sit in /system/etc/event-log-tags. message EventLogTagMapProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + repeated EventLogTag event_log_tags = 1; } message EventLogTag { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + optional uint32 tag_number = 1; // keyed by tag number. optional string tag_name = 2; message ValueDescriptor { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + optional string name = 1; enum DataType { @@ -55,4 +63,4 @@ message EventLogTag { optional DataUnit unit = 3; } repeated ValueDescriptor value_descriptors = 3; -} \ No newline at end of file +} diff --git a/core/proto/android/view/displaycutout.proto b/core/proto/android/view/displaycutout.proto index ff13fab35bf20df866d6f53c2d310d5daed42149..ee258b7369a0b8a48d16d7125e2023e50d2952f3 100644 --- a/core/proto/android/view/displaycutout.proto +++ b/core/proto/android/view/displaycutout.proto @@ -17,11 +17,14 @@ syntax = "proto2"; import "frameworks/base/core/proto/android/graphics/rect.proto"; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; package android.view; option java_multiple_files = true; message DisplayCutoutProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + optional .android.graphics.RectProto insets = 1; optional .android.graphics.RectProto bounds = 2; } diff --git a/core/proto/android/view/surfacecontrol.proto b/core/proto/android/view/surfacecontrol.proto index 9288b4fc36710db374583f3fe2a4769938ea5036..665d688b05ac4f3a13d020a3b7f60a911cd57c52 100644 --- a/core/proto/android/view/surfacecontrol.proto +++ b/core/proto/android/view/surfacecontrol.proto @@ -19,10 +19,14 @@ package android.view; option java_multiple_files = true; +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + /** * Represents a {@link android.view.SurfaceControl} object. */ message SurfaceControlProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + optional int32 hash_code = 1; - optional string name = 2; + optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ]; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a0ba3ade4b34a85529c8b80974ffd87e1da8c11d..56e276d3523a93c2429f6c7a64d852b9cf8339ae 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -323,6 +323,7 @@ + @@ -331,6 +332,25 @@ + + + + + + + + + + + + + + + + + + + @@ -354,6 +374,7 @@ + @@ -1785,13 +1806,31 @@ + + + + + + + + + + @@ -3012,6 +3068,13 @@ + + + @@ -3818,6 +3881,7 @@ android:excludeFromRecents="true" android:label="@string/user_owner_label" android:exported="true" + android:visibleToInstantApps="true" > + + + + + diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml index 3b89f0d0cde7348bf95c955f313364114572d15a..1be915e809e628e8357817104fbd9ed66bc25954 100644 --- a/core/res/res/layout/popup_menu_item_layout.xml +++ b/core/res/res/layout/popup_menu_item_layout.xml @@ -28,18 +28,18 @@ android:layout_marginBottom="4dip" android:background="@drawable/list_divider_material" /> - - - - + + + - + - - + + + diff --git a/core/res/res/layout/unlaunchable_app_activity.xml b/core/res/res/layout/unlaunchable_app_activity.xml deleted file mode 100644 index 429d5edea8b7110b12723c240b8a87283f5be101..0000000000000000000000000000000000000000 --- a/core/res/res/layout/unlaunchable_app_activity.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index f3db59883233c94e7c65e0d456bf0739b9d66d24..ab54ad84a785e37c7a3fd5078a34d2a799d671ae 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Veiligmodus" "Android-stelsel" - - - - + "Skakel oor na persoonlike profiel" + "Skakel oor na werkprofiel" "Kontakte" "in te gaan by jou kontakte" "Gee <b>%1$s</b> toegang tot jou kontakte" @@ -419,10 +417,8 @@ "Laat die program toe om toegang tot die foonfunksies van die toestel te verkry. Hierdie toestemming laat die program toe om te bepaal wat die foonnommer en toestel-IDs is, of die oproep aan die gang is, en die afgeleë nommer wat deur \'n oproep verbind word." "roeteer oproepe deur die stelsel" "Laat die program toe om sy oproepe deur die stelsel te stuur om die oproepervaring te verbeter." - - - - + "gaan voort met \'n oproep uit \'n ander program" + "Laat die program toe om \'n oproep voort te sit wat in \'n ander program begin is." "lees foonnommers" "Laat die program toe om toegang tot die toestel se foonnommers te kry." "verhoed dat tablet slaap" @@ -497,11 +493,14 @@ "Vingerafdruk kan nie gestoor word nie. Verwyder asseblief \'n bestaande vingerafdruk." "Vingerafdrukuittelling is bereik. Probeer weer." "Vingerafdrukhandeling is gekanselleer." - - + "Vingerafdrukhandeling is deur gebruiker gekanselleer." "Te veel pogings. Probeer later weer." "Te veel pogings. Vingerafdruksensor is gedeaktiveer." "Probeer weer." + + + + "Vinger %d" @@ -1000,12 +999,9 @@ "Maak oop" "SMS" "Voeg by" - - - - - - + "Bekyk" + "Skeduleer" + "Spoor na" "Bergingspasie word min" "Sommige stelselfunksies werk moontlik nie" "Nie genoeg berging vir die stelsel nie. Maak seker jy het 250 MB spasie beskikbaar en herbegin." @@ -1131,8 +1127,7 @@ Oop Wi-Fi-netwerk beskikbaar "Koppel aan oop Wi-Fi-netwerk" - - + "Koppel aan diensverskaffer se Wi‑Fi-netwerk" "Koppel tans aan oop Wi‑Fi-netwerk" "Aan Wi-Fi-netwerk gekoppel" "Kon nie aan Wi-Fi-netwerk koppel nie" @@ -1216,13 +1211,23 @@ "Geen toestemmings benodig nie" "dit kan jou dalk geld kos" "OK" - "USB laai tans hierdie toestel" - "USB verskaf tans krag aan gekoppelde toestel" - "USB vir lêeroordrag" - "USB vir foto-oordrag" - "USB vir MIDI" - "Gekoppel aan \'n USB-toebehoorsel" + + + + + + + + + + + + + + "Tik vir meer opsies." + + "Analoë oudiobykomstigheid bespeur" "Die aangehegde toestel is nie met hierdie foon versoenbaar nie. Tik om meer te wete te kom." "USB-ontfouter gekoppel" @@ -1661,9 +1666,6 @@ "Werk-%1$s" "2e werk-%1$s" "3e werk-%1$s" - "Raak en hou die Terug- en Oorsig-knoppie om hierdie skerm te ontspeld" - "Skerm vasgespeld" - "Skerm ontspeld" "Vra PIN voordat jy ontspeld" "Vra ontsluitpatroon voordat jy ontspeld" "Vra wagwoord voordat jy ontspeld" @@ -1757,15 +1759,11 @@ "Alle tale" "Allle streke" "Soek" - - - - + "Skakel werkprofiel aan?" + "Jou werkprogramme, kennisgewings, data en ander werkprofielkenmerke sal aangeskakel word" "Skakel aan" - - - - + "Hierdie program is vir \'n ouer weergawe van Android gebou en sal dalk nie behoorlik werk nie. Probeer kyk vir opdaterings, of kontak die ontwikkelaar." + "Kyk vir opdatering" "Jy het nuwe boodskappe" "Maak SMS-program oop om te bekyk" "Sommige funksies kan beperk wees" @@ -1832,17 +1830,15 @@ "Foon nie toegelaat vir stem nie" "Opspringvenster" "+ %1$d" - "Hierdie kortpad vereis die jongste program" + + "Kon nie die kortpad teruglaai nie omdat die program nie rugsteun en teruglaai steun nie" "Kon nie teruglaai nie omdat programondertekening nie ooreenstem nie" "Kon nie kortpad teruglaai nie" "Kortpad is gedeaktiveer" - - - - - - + "DEΪNSTALLEER" + "MAAK TOG OOP" + "Skadelike program is bespeur" "%1$s wil %2$s-skyfies wys" "Wysig" diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 0dbda7f927da78859e52c32b6fdfbae5da648962..54b913e2000197917875a274c03fb5295dae33cb 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -264,10 +264,8 @@ "%1$s%2$s" "የሚያስተማምን ሁነታ" "Android ስርዓት" - - - - + "ወደ የግል መገለጫ ቀይር" + "ወደ የስራ መገለጫ ቀይር" "ዕውቂያዎች" "የእርስዎ እውቂያዎች ላይ ይድረሱባቸው" "<b>%1$s</b> እውቂያዎችዎን እንዲደርስ ይፍቀዱለት" @@ -419,10 +417,8 @@ "መተግበሪያው የመሳሪያውን የስልክ ባህሪያት ላይ እንዲደርስ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው የስልክ ቁጥሩን እና የመሳሪያውን መታወቂያዎች፣ ጥሪ የነቃ እንደሆነ፣ እና በጥሪ የተገናኘውን የሩቅ ቁጥር እንዲወስን ይፈቅድለታል።" "ጥሪዎችን በስርዓቱ በኩል አዙር" "መተግበሪያው የጥሪ ተሞክሮን እንዲያሻሽል ጥሪዎቹን በስርዓቱ በኩል እንዲያዞር ያስችለዋል።" - - - - + "በሌላ መተግበሪያ የተጀመረ ጥሪን መቀጠል" + "መተግበሪያው በሌላ መተግበሪያ ውስጥ የተጀመረ ጥሪ እንዲቀጥል ያስችለዋል።" "ስልክ ቁጥሮች ያንብቡ" "መተግበሪያው የመሣሪያውን የስልክ ቁጥሮች እንዲደርስባቸው ይፈቅድለታል።" "ጡባዊ ከማንቀላፋት ተከላከል" @@ -497,11 +493,14 @@ "የጣት አሻራ ሊከማች አይችልም። እባክዎ አሁን ያለውን የጣት አሻራ ያስወግዱ።" "የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።" "የጣት አሻራ ስርዓተ ክወና ተትቷል።" - - + "የጣት አሻራ ክወና በተጠቃሚ ተሰርዟል።" "ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።" "በጣም ብዙ ሙከራዎች። የጣት አሻራ ዳሳሽ ተሰናክሏል።" "እንደገና ይሞክሩ።" + + + + "ጣት %d" @@ -1000,12 +999,9 @@ "ክፈት" "መልዕክት" "አክል" - - - - - - + "ይመልከቱ" + "መርሐግብር" + "ተከታተል" "የማከማቻ ቦታ እያለቀ ነው" "አንዳንድ የስርዓት ተግባራት ላይሰሩ ይችላሉ" "ለስርዓቱ የሚሆን በቂ ቦታ የለም። 250 ሜባ ነጻ ቦታ እንዳለዎት ያረጋግጡና ዳግም ያስጀምሩ።" @@ -1131,8 +1127,7 @@ የሚገኙ የWi-Fi አውታረ መረቦችን ክፈት "ከክፍት የWi‑Fi አውታረ መረብ ጋር ያገናኙ" - - + "ከአገልግሎት አቅራቢ Wi-Fi አውታረ መረብ ጋር ይገናኙ" "ከክፍት የWi‑Fi አውታረ መረብ ጋር በመገናኘት ላይ" "ከWi‑Fi አውታረ መረብ ጋር ተገናኝቷል" "ከWi‑Fi አውታረ መረብ ጋር መገናኘት አልተቻለም" @@ -1216,13 +1211,23 @@ "ምንም ፍቃዶች አይጠየቁም" "ይህ ገንዘብ ሊያስወጣዎት ይችላል" "እሺ" - "ዩኤስቢ የዚህን መሣሪያ ኃይል በመሙላት ላይ" - "ዩኤስቢ ለተያያዘው መሣሪያ ኃይል በማቅረብ ላይ" - "ዩኤስቢ ለፋይል ሽግግር" - "ዩኤስቢ ለፎቶ ሽግግር" - "ዩኤስቢ ለMIDI" - "ለUSB ተቀጥላ ተያይዟል" + + + + + + + + + + + + + + "ለተጨማሪ አማራጮች መታ ያድርጉ።" + + "የአናሎግ ኦዲዮ ረዳት እንዳለ ተደርሶበታል" "ዓባሪ የተያያዘው መሣሪያ ከዚህ ስልክ ጋር ተኳዃኝ አይደለም። የበለጠ ለመረዳት መታ ያድርጉ።" "USB አድስ ተያይዟል" @@ -1661,9 +1666,6 @@ "ስራ %1$s" "2ኛ ስራ %1$s" "3ኛ ስራ %1$s" - "ይህን ማያ ገጽ ለመንቀል ተመለስ እና አጠቃላይ ዕይታን ተጭነው ይያዙ" - "ማያ ገጽ ተሰክቷል" - "ማያ ገጽ ተነቅሏል" "ከመንቀል በፊት ፒን ጠይቅ" "ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ" "ከመንቀል በፊት የይለፍ ቃል ጠይቅ" @@ -1757,15 +1759,11 @@ "ሁሉም ቋንቋዎች" "ሁሉም ክልሎች" "ፈልግ" - - - - + "የስራ መገለጫ ይብራ?" + "የእርስዎ የስራ መተግበሪያዎች፣ ማሳወቂያዎች፣ ውሂብ እና ሌሎች የስራ መገለጫ ባህሪያት ይበራሉ" "አብራ" - - - - + "ይህ መተግበሪያ ለቆየ የAndroid ስሪት ነው የተገነባው፣ እና በአግባቡ ላይሰራ ይችላል። ዝማኔዎች ካሉ ለመመልከት ይሞክሩ፣ ወይም ደግሞ ገንቢውን ያነጋግሩ።" + "ዝማኔ ካለ አረጋግጥ" "አዲስ መልእክቶች አለዎት" "ለመመልከት የኤስኤምኤስ መተግበሪያ ይክፈቱ" "አንዳንድ ተግባሮች የተገደቡ ሊሆኑ ይችላሉ" @@ -1832,17 +1830,15 @@ "ስልክ ለድምጽ አይፈቀድም" "ብቅ-ባይ መስኮት" "+ %1$d" - "ይህ አቋራጭ በጣም የቅርብ ጊዜውን መተግበሪያ ይፈልጋል" + + "መተግበሪያ ምትኬን እና ወደ ነበረበት መመለስን ሳለማይደግፍ አቋራጭ ወደ ነበረበት ሊመለስ አልቻለም" "በመተግበሪያ ፊርማ አለመዛመድ አቋራጭን ወደነበረበት መመለስ አልተቻለም" "አቋራጭን ወደ ነበረበት መመለስ አልተቻለም" "አቋራጭ ተሰናክሏል" - - - - - - + "አራግፍ" + "ለማንኛውም ክፈት" + "ጎጂ መተግበሪያ ተገኝቷል" "%1$s%2$s ቁራጮችን ማሳየት ይፈልጋል" "አርትዕ" diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 5255a12673c57e839bf48d7e1a80a035cd1c2a2f..5254fcd45981e1e72e734f86d2f93aeb6ac93225 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -417,10 +417,8 @@ "Tətbiqə cihazın telefon funksiyalarına giriş icazəsi verir. Belə icazəli tətbiq bu telefonun nömrəsini və cihaz İD\'ni, zəngin aktiv olub-olmadığını və zəng edilən nömrəni müəyyən edə bilər." "zəngləri sistem üzərindən yönləndirin" "Tətbiqə, zəng təcrübəsini yaxşılaşdırmaq üçün, zəngləri sistem üzərindən yönləndirməyə icazə verilir." - - - - + "zəngə digər tətbiqdən davam edin" + "Tətbiqə digər tətbiqdə başlayan zəngə davam etmək icazəsi verilir." "telefon nömrələrini oxuyun" "Tətbiqə cihazın telefon nömrələrinə daxil olmağa icazə verir." "planşetin yuxu rejiminin qarşısını almaq" @@ -499,6 +497,10 @@ "Cəhdlər çox oldu. Sonraya saxlayın." "Həddindən çox cəhd. Barmaq izi sensoru deaktiv edilib." "Yenidən cəhd edin." + + + + "Barmaq %d" @@ -997,12 +999,9 @@ "Açın" "Mesaj" "Əlavə edin" - - - - - - + "Baxın" + "Cədvəl" + "Trek" "Yaddaş yeri bitir" "Bəzi sistem funksiyaları işləməyə bilər" "Sistem üçün yetərincə yaddaş ehtiyatı yoxdur. 250 MB yaddaş ehtiyatının olmasına əmin olun və yenidən başladın." @@ -1128,8 +1127,7 @@ Əlçatan açıq Wi-Fi şəbəkəsi "Açıq Wi‑Fi şəbəkəsinə qoşulun" - - + "Operatorun Wi‑Fi şəbəkəsinə qoşulun" "Açıq Wi‑Fi şəbəkəsinə qoşulur" "Wi‑Fi şəbəkəsinə qoşuldu" "Wi‑Fi şəbəkəsinə qoşulmaq mümkün deyil" @@ -1213,13 +1211,23 @@ "Heç bir icazə tələb olunmur" "bununla sizdən xərc tutula bilər" "OK" - "USB bu cihaza enerji doldurur" - "Qolulmuş cihaz üçün USB enerji tədarükü" - "Fayl transferi üçün USB" - "Foto transfer üçün USB" - "MIDI üçün USB" - "USB aksesuara qoşuldu" + + + + + + + + + + + + + + "Əlavə seçimlər üçün tıklayın." + + "Analoq audio aksesuar aşkarlandı" "Əlavə edilən cihaz bu telefonla uyğun deyil. Ətraflı məlumat üçün klikləyin." "USB sazlama qoşuludur" @@ -1658,9 +1666,6 @@ "İş %1$s" "2-ci İş %1$s" "3-cü İş %1$s" - "Bu ekrandan sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın" - "Screen pinned" - "Screen unpinned" "Ayırmadan öncə PIN istənilsin" "Ayırmadan öncə kilid modeli istənilsin" "Ayırmadan öncə parol istənilsin" @@ -1757,10 +1762,8 @@ "İş profili aktiv edilsin?" "İş tətbiqləri, bildirişləri, data və digər iş profili funksiyaları aktiv ediləcək" "Aktivləşdirin" - - - - + "Bu tətbiq köhnə Android versiyası üçün hazırlanıb və düzgün işləməyə bilər. Güncəlləməni yoxlayın və ya developer ilə əlaqə saxlayın." + "Güncəlləməni yoxlayın" "Yeni mesajlarınız var" "Baxmaq üçün SMS tətbiqini açın" "Bir neçə funksionallıq məhdudlaşdırıla bilər" @@ -1827,17 +1830,15 @@ "Səs üçün telefona icazə verilmir" "Popap Pəncərəsi" "+ %1$d" - "Bu qısayol ən son tətbiqi tələb edir" + + "Qısayolu bərpa etmək mümkün olmadı, çünki tətbiq yedəkləməni və bərpa etməyi dəstəkləmir" "Tətbiqin imza uyğunsuzluğu səbəbilə qısayolu bərpa etmək mümkün olmadı" "Qısayolu bərpa etmək mümkün olmadı" "Qısayol deaktiv edildi" - - - - - - + "SİSTEMDƏN SİLİN" + "İSTƏNİLƏN HALDA AÇIN" + "Zərərli tətbiq aşkarlandı" "%1$s %2$s tətbiqindən bölmələr göstərmək istəyir" "Redaktə edin" diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index ecadbbf38b2fccd7630c08b86205308349ba5e24..21cf7d6a5b87f5cfe93d33369934363f6ce385e8 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "নিরাপদ মোড" "Android সিস্টেম" - - - - + "এর বদলে ব্যক্তিগত প্রোফাইল ব্যবহার করুন" + "এর বদলে কাজের প্রোফাইল ব্যবহার করুন" "পরিচিতি" "আপনার পরিচিতিগুলিতে অ্যাক্সেস" "<b>%1$s</b> কে আপনার পরিচিতিগুলি অ্যাক্সেস করতে দিন" @@ -419,10 +417,8 @@ "অ্যাপ্লিকেশানটিকে ডিভাইসের ফোন বৈশিষ্ট্যগুলিকে অ্যাক্সেস করার অনুমতি দেয়৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে একটি কল সক্রিয় থাকা অবস্থায় এবং দূরবর্তী নম্বর একটি কল দ্বারা সংযুক্ত থাকাকালীনও ফোন নম্বর এবং ডিভাইসের IDগুলি নির্ধারণ করার অনুমতি দেয়৷" "সিস্টেমের মাধ্যমে কলগুলি রুট করতে দিন" "কল করার অভিজ্ঞতা উন্নত করার জন্য অ্যাপকে সিস্টেমের মাধ্যমে তার কলগুলি রুট করতে দেয়।" - - - - + "অন্য কোনও অ্যাপ দিয়ে করে থাকা কল চালিয়ে যান" + "অন্য কোনও অ্যাপ দিয়ে কল করলে এই অ্যাপটিকে সেটি চালিয়ে যেতে দেয়।" "ফোন নম্বরগুলি পড়া হোক" "অ্যাপটিকে এই ডিভাইসের ফোন নম্বরগুলি অ্যাক্সেস করতে দেয়।" "ঘুমানো থেকে ট্যাবলেটকে প্রতিরোধ করে" @@ -497,11 +493,14 @@ "আঙ্গুলের ছাপ সংরক্ষণ করা যাবে না৷ অনুগ্রহ করে একটি বিদ্যমান আঙ্গুলের ছাপ সরান৷" "আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷" "আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷" - - + "ব্যবহারকারী আঙ্গুলের ছাপের অপারেশনটি বাতিল করেছেন।" "অনেকবার প্রচেষ্টা করা হয়েছে৷ পরে আবার চেষ্টা করুন৷" "বহুবার চেষ্টা করেছেন। আঙ্গুলের ছাপ নেওয়ার সেন্সর অক্ষম করা হয়েছে।" "আবার চেষ্টা করুন৷" + + + + "আঙ্গুল %d" @@ -1000,12 +999,9 @@ "খুলুন" "মেসেজ" "যোগ করুন" - - - - - - + "দেখুন" + "সময়সূচী" + "ট্র্যাক" "স্টোরেজ পূর্ণ হতে চলেছে" "কিছু কিছু সিস্টেম ক্রিয়াকলাপ কাজ নাও করতে পারে" "সিস্টেমের জন্য যথেষ্ট স্টোরেজ নেই৷ আপনার কাছে ২৫০এমবি ফাঁকা স্থান রয়েছে কিনা সে বিষয়ে নিশ্চিত হন এবং সিস্টেম চালু করুন৷" @@ -1131,8 +1127,7 @@ খোলা ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে "উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযোগ করুন" - - + "পরিষেবা প্রদানকারীর ওয়াই-ফাই নেটওয়ার্কে সংযোগ করুন" "উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযোগ করা হচ্ছে" "উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযুক্ত করা হয়েছে" "ওয়াই-ফাই নেটওয়ার্কে সংযোগ করা গেল না" @@ -1217,13 +1212,23 @@ "কোনো অনুমতির প্রয়োজন নেই" "এর জন্য অর্থপ্রদান করতে হতে পারে" "ঠিক আছে" - "এই ডিভাইসটি USB দ্বারা চার্জ করা হচ্ছে" - "সংযুক্ত ডিভাইসটিতে USB পাওয়ার সরবরাহ করছে" - "ফাইল স্থানান্তরের জন্য USB" - "ফটো স্থানান্তরের জন্য USB" - "MIDI এর জন্য USB" - "একটি USB যন্ত্রাংশতে সংযুক্ত হয়েছে" + + + + + + + + + + + + + + "আরও বিকল্পের জন্য আলতো চাপুন৷" + + "অ্যানালগ অডিও অ্যাক্সেসরি শনাক্ত করা হয়েছে" "সংযুক্ত ডিভাইসটি এই ফোনের সাথে ব্যবহার করা যাবে না। আরও জানতে ট্যাপ করুন।" "USB ডিবাগিং সংযুক্ত হয়েছে" @@ -1662,9 +1667,6 @@ "কর্মক্ষেত্র %1$s" "দ্বিতীয় কার্যক্ষেত্র %1$s" "তৃতীয় কার্যক্ষেত্র %1$s" - "এই স্ক্রিনটিকে আনপিন করতে ফিরে যাওয়া এবং এক নজরে বোতামদুটি ট্যাপ করে ধরে রাখুন" - "স্ক্রিন পিন করা হয়েছে" - "পিন না করা স্ক্রীন" "আনপিন করার আগে পিন চান" "আনপিন করার আগে আনলক প্যাটার্ন চান" "আনপিন করার আগে পাসওয়ার্ড চান" @@ -1758,15 +1760,11 @@ "সকল ভাষা" "সমস্ত অঞ্চল" "খুঁজুন" - - - - + "কাজের প্রোফাইল চালু করবেন?" + "আপনার কাজের অ্যাপ, বিজ্ঞপ্তি, ডেটা এবং কাজের প্রোফাইলের অন্যান্য বৈশিষ্ট্য চালু করা হবে" "চালু করুন" - - - - + "এই অ্যাপটি Android এর একটি পুরনো ভার্সনের জন্য তৈরি করা হয়েছিল, তাই এখানে সেটি ঠিকমতো কাজ নাও করতে পারে। আপডেট পাওয়া যাচ্ছে কিনা দেখুন বা ডেভেলপারের সাথে যোগাযোগ করুন।" + "আপডেট পাওয়া যাচ্ছে কিনা দেখুন" "আপনার নতুন মেসেজ আছে" "দেখার জন্য SMS অ্যাপ্লিকেশান খুলুন" "কিছু ক্রিয়াকলাপ সীমিত হতে পারে" @@ -1833,17 +1831,15 @@ "এই ফোন দিয়ে ভয়েস কল করা যাবে না" "পপ-আপ উইন্ডো" "+ %1$dটি" - "এই শর্টকাটটির জন্য লেটেস্ট অ্যাপ প্রয়োজন" + + "শর্টকাট ফিরিয়ে আনা যায়নি কারণ অ্যাপটিতে \'ব্যাক-আপ এবং রিস্টোর\' করার সুবিধা নেই" "শর্টকাট ফিরিয়ে আনা যায়নি কারণ অ্যাপের সিগ্নেচারটি মিল হচ্ছে না" "শর্টকাট ফিরিয়ে আনা যায়নি" "শর্টকাট অক্ষম করা আছে" - - - - - - + "আন-ইনস্টল করুন" + "যাই হোক, খুলতে চাই" + "ক্ষতিকর অ্যাপ শনাক্ত করা হয়েছে" "%1$s অ্যাপটি %2$s এর অংশ দেখাতে চায়" "এডিট করুন" diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index f143d4e13a44352283561cd8bcce355f720db777..6eef37cc26f513e1f7b413a8d66357b346c2e84e 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -267,10 +267,8 @@ "%1$s, %2$s" "Siguran način rada" "Android sistem" - - - - + "Pređite na lični profil" + "Pređite na radni profil" "Kontakti" "pristupa vašim kontaktima" "Dozvolite aplikaciji <b>%1$s</b> pristup vašim kontaktima" @@ -422,10 +420,8 @@ "Omogućava aplikaciji pristup telefonskim funkcijama uređaja. Ovo odobrenje omogućava aplikaciji određivanje telefonskog i identifikacionog broja uređaja, bez obzira da li je poziv aktivan i da li je uspostavljena veza sa pozivanim brojem." "usmjeravanje poziva preko sistema" "Dopušta aplikaciji da pozive usmjeri preko sistema radi poboljšanja iskustva pozivanja." - - - - + "nastavlja poziv iz druge aplikacije" + "Dozvoljava aplikaciji nastavljanje poziva koji je započet u drugoj aplikaciji." "čitanje telefonskih brojeva" "Dozvoljava aplikaciji pristup telefonskim brojevima uređaja." "sprečavanje tableta da uđe u režim mirovanja" @@ -500,11 +496,14 @@ "Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta." "Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo." "Radnja sa otiskom prsta je otkazana." - - + "Korisnik je otkazao radnju s otiskom prsta." "Previše pokušaja. Pokušajte ponovo kasnije." "Previše pokušaja. Senzor za otisak prsta je onemogućen." "Pokušajte ponovo." + + + + "Prst %d" @@ -567,8 +566,8 @@ "Dozvoljava vlasniku povezivanje s interfejsom najvišeg nivoa u servisu za poruke operatera. Nije potrebno za obične aplikacije." "povezivanje na usluge operatera" "Omogućava vlasniku povezivanje sa uslugama operatera. Obično nije potrebno za obične aplikacije." - "pristup opciji Ne ometaj" - "Omogućava aplikaciji da čita i upisuje konfiguraciju opcije Ne ometaj." + "pristup načinu rada Ne ometaj" + "Omogućava aplikaciji da čita i upisuje konfiguraciju načina rada Ne ometaj." "Postavljanje pravila za lozinke" "Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN-ovima." "Prati pokušaje otključavanja ekrana" @@ -1020,12 +1019,9 @@ "Otvorite" "Poruka" "Dodajte" - - - - - - + "Prikaži" + "Zakaži" + "Prati" "Ponestaje prostora za pohranu" "Neke funkcije sistema možda neće raditi" "Nema dovoljno prostora za sistem. Obezbijedite 250MB slobodnog prostora i ponovo pokrenite uređaj." @@ -1155,8 +1151,7 @@ Otvorene Wi-Fi mreže su dostupne "Povežite se na otvorenu Wi‑Fi mrežu" - - + "Povežite se na Wi‑Fi mrežu mobilnog operatera" "Povezivanje na otvorenu Wi‑Fi mrežu" "Povezani ste na Wi‑Fi mrežu" "Nije se moguće povezati na Wi‑Fi mrežu" @@ -1240,13 +1235,23 @@ "Nisu potrebna odobrenja" "ovo se možda dodatno plaća" "Uredu" - "Punjenje uređaja putem USB-a" - "USB napaja priključeni uređaj" - "USB za prijenos fajlova" - "USB za prijenos slika" - "USB za MIDI" - "Uspostavljena veza sa USB pohranom" + + + + + + + + + + + + + + "Dodirnite za više opcija." + + "Otkriven je analogni periferni uređaj" "Priključeni uređaj nije kompatibilan s ovim telefonom. Dodirnite da saznate više." "Otklanjanje grešaka putem uređaja spojenog na USB je uspostavljeno" @@ -1688,9 +1693,6 @@ "Poslovni %1$s" "2. poslovni %1$s" "3. poslovni %1$s" - "Da otkačite ovaj ekran, dodirnite i držite dugmad Nazad i Pregled." - "Ekran je zakačen" - "Ekran je otkačen" "Traži PIN prije nego se otkači" "Traži uzorak za otključavanje prije nego se otkači" "Traži lozinku prije nego se otkači" @@ -1744,7 +1746,7 @@ "Do %1$s" "Do %1$s (sljedeći alarm)" "Dok ne isključite" - "Dok ne isključite opciju Ne ometaj" + "Dok ne isključite način rada Ne ometaj" "%1$s/%2$s" "Skupi" "Ne ometaj" @@ -1793,15 +1795,11 @@ "Svi jezici" "Sve regije" "Pretraga" - - - - + "Uključiti radni profil?" + "Uključit će se poslovne aplikacije, obavještenja, podaci i druge funkcije radnog profila" "Uključi" - - - - + "Ova aplikacija je pravljena za stariju verziju Androida i možda neće ispravno raditi. Provjerite jesu li dostupna ažuriranja ili kontaktirajte programera." + "Provjeri je li dostupno ažuriranje" "Imate nove poruke" "Otvorite SMS aplikaciju da biste pregledali poruke" "Neke funkcije mogu biti ograničene" @@ -1869,17 +1867,15 @@ "Telefon nije dozvoljen za govor" "Iskočni prozor" "+ %1$d" - "Za ovu prečicu potrebna je najnovija aplikacija" + + "Prečica nije uspješno vraćena jer aplikacija ne podržava izradu sigurnosne kopije i vraćanje" "Prečica nije uspješno vraćena zbog nepodudaranja potpisa aplikacije" "Prečica nije uspješno vraćena" "Prečica je onemogućena" - - - - - - + "DEINSTALIRAJ" + "IPAK OTVORI" + "Otkrivena je štetna aplikacija" "Aplikacija %1$s želi prikazati isječke aplikacije %2$s" "Uredi" diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index bf91550ceeeb1ca676cc556e5d9ba15b2e03169a..abdb966c13f33b69c3e01a8d05022acfdd03f718 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Mode segur" "Sistema Android" - - - - + "Canvia al perfil personal" + "Canvia al perfil professional" "Contactes" "accedir als contactes" "Permet que <b>%1$s</b> accedeixi als contactes" @@ -419,10 +417,8 @@ "Permet que l\'aplicació accedeixi a les funcions de telèfon del dispositiu. Aquest permís permet que l\'aplicació determini el número de telèfon i els identificadors del dispositiu, si hi ha una trucada activa i el número remot connectat amb una trucada." "encaminar trucades a través del sistema" "Permet que l\'aplicació encamini les trucades a través del sistema per millorar-ne l\'experiència." - - - - + "Continua una trucada d\'una altra aplicació" + "Permet que l\'aplicació continuï una trucada que s\'havia iniciat en una altra aplicació." "llegir els números de telèfon" "Permet que l\'aplicació accedeixi als números de telèfon del dispositiu." "evita que la tauleta entri en mode de repòs" @@ -497,11 +493,14 @@ "L\'empremta digital no es pot desar. Suprimeix-ne una." "S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar." "S\'ha cancel·lat l\'operació d\'empremta digital." - - + "L\'usuari ha cancel·lat l\'operació d\'empremta digital." "S\'han produït massa intents. Torna-ho a provar més tard." "S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes digitals." "Torna-ho a provar." + + + + "Dit %d" @@ -1000,12 +999,9 @@ "Obre" "Missatge" "Afegeix" - - - - - - + "Mostra" + "Programa" + "Fes un seguiment" "L\'espai d\'emmagatzematge s\'està esgotant" "És possible que algunes funcions del sistema no funcionin" "No hi ha prou espai d\'emmagatzematge per al sistema. Comprova que tinguis 250 MB d\'espai lliure i reinicia." @@ -1131,8 +1127,7 @@ Xarxa Wi-Fi oberta disponible "Connecta\'t a una xarxa Wi-Fi oberta" - - + "Connecta\'t a la xarxa Wi-Fi de l\'operador de telefonia mòbil" "S\'està connectant a una xarxa Wi-Fi oberta" "S\'ha connectat a la xarxa Wi-Fi" "No s\'ha pogut connectar a una xarxa Wi-Fi" @@ -1216,13 +1211,23 @@ "No cal cap permís" "pot ser que comporti càrrecs" "D\'acord" - "El dispositiu s\'està carregant per USB" - "L\'USB subministra energia al dispositiu connectat" - "USB per transferir fitxers" - "USB per transferir fotos" - "USB per a MIDI" - "Connectat a un accessori USB" + + + + + + + + + + + + + + "Toca per veure més opcions." + + "S\'ha detectat un accessori d\'àudio analògic" "El dispositiu connectat no és compatible amb aquest telèfon. Toca per obtenir més informació." "Depuració USB activada" @@ -1661,9 +1666,6 @@ "%1$s de la feina" "2n %1$s de la feina" "3r %1$s de la feina" - "Toca i mantén premuts els botons Enrere i Aplicacions recents per deixar de fixar aquesta pantalla" - "Pantalla fixada" - "Fixació de la pantalla anul·lada" "Sol·licita el codi PIN per deixar de fixar" "Sol·licita el patró de desbloqueig per deixar de fixar" "Demana la contrasenya per deixar de fixar" @@ -1757,15 +1759,11 @@ "Tots els idiomes" "Totes les regions" "Cerca" - - - - + "Activar el perfil professional?" + "S\'activaran les teves aplicacions per a la feina, les notificacions, les dades i altres funcions del perfil professional" "Activa" - - - - + "Aquesta aplicació es va crear per a una versió antiga d\'Android i pot ser que no funcioni correctament. Prova de cercar actualitzacions o contacta amb el desenvolupador." + "Cerca actualitzacions" "Tens missatges nous" "Obre l\'aplicació d\'SMS per veure\'ls" "Algunes funcions es limitaran" @@ -1832,17 +1830,15 @@ "El telèfon no és compatible per a la veu" "Finestra emergent" "%1$d més" - "Per fer servir aquesta drecera has de tenir l\'última versió de l\'aplicació" + + "No s\'ha pogut restaurar la drecera perquè l\'aplicació no permet la còpia de seguretat ni la restauració" "No s\'ha pogut restaurar la drecera perquè la signatura de l\'aplicació no coincideix" "No s\'ha pogut restaurar la drecera" "S\'ha desactivat la drecera" - - - - - - + "DESINSTAL·LA" + "OBRE IGUALMENT" + "S\'ha detectat una aplicació perjudicial" "%1$s vol mostrar porcions de l\'aplicació %2$s" "Edita" diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 32d4294e0292d172f53e8ae7ad94587763555f58..89b6e296528d378ee19757c332d921a8e8e51843 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -270,10 +270,8 @@ "%1$s, %2$s" "Nouzový režim" "Systém Android" - - - - + "Přepnout na osobní profil" + "Přepnout na pracovní profil" "Kontakty" "přístup ke kontaktům" "Povolte aplikaci <b>%1$s</b> přístup ke kontaktům" @@ -425,10 +423,8 @@ "Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen." "směrování volání prostřednictvím systému" "Umožňuje aplikaci směrovat volání prostřednictvím systému za účelem vylepšení funkcí volání." - - - - + "pokračování v hovoru v jiné aplikaci" + "Umožňuje aplikace pokračovat v hovoru, který byl zahájen v jiné aplikaci." "přístup k telefonním číslům" "Umožňuje aplikaci přístup k telefonním číslům v zařízení." "bránění přechodu tabletu do režimu spánku" @@ -503,11 +499,14 @@ "Otisk prstu nelze uložit. Odstraňte existující otisk prstu." "Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu." "Operace otisku prstu byla zrušena." - - + "Uživatel operaci s otiskem prstu zrušil." "Příliš mnoho pokusů. Zkuste to později." "Příliš mnoho pokusů. Snímač otisků prstů byl deaktivován." "Zkuste to znovu." + + + + "Prst %d" @@ -1040,12 +1039,9 @@ "Otevřít" "Zpráva" "Přidat" - - - - - - + "Zobrazit" + "Naplánovat" + "Sledovat" "V úložišti je málo místa" "Některé systémové funkce nemusí fungovat" "Pro systém není dostatek místa v úložišti. Uvolněte alespoň 250 MB místa a restartujte zařízení." @@ -1175,8 +1171,7 @@ K dispozici je veřejná síť Wi-Fi "Připojení k otevřené síti Wi-Fi" - - + "Připojte se k síti Wi-Fi operátora" "Připojování k otevřené síti Wi-Fi" "Připojeno k síti Wi-Fi" "Připojení k síti Wi-Fi se nezdařilo" @@ -1260,13 +1255,23 @@ "Nejsou vyžadována žádná oprávnění" "může vás to něco stát" "OK" - "Nabíjení zařízení přes USB" - "Připojené zařízení se nabíjí přes USB" - "USB na přenos souborů" - "USB na přenos fotek" - "USB v režimu MIDI" - "Připojeno k perifernímu zařízení USB" + + + + + + + + + + + + + + "Klepnutím zobrazíte další možnosti." + + "Bylo zjištěno analogové zvukové příslušenství" "Připojené zařízení není s tímto telefonem kompatibilní. Klepnutím zobrazíte další informace." "Ladění přes USB připojeno" @@ -1711,9 +1716,6 @@ "Pracovní %1$s" "2. %1$s do práce" "3. %1$s do práce" - "Chcete-li tuto obrazovku uvolnit, podržte tlačítka Zpět a Přehled" - "Obrazovka připnuta" - "Obrazovka uvolněna" "Před uvolněním požádat o PIN" "Před uvolněním požádat o bezpečnostní gesto" "Před uvolněním požádat o heslo" @@ -1825,15 +1827,11 @@ "Všechny jazyky" "Všechny oblasti" "Vyhledávání" - - - - + "Zapnout pracovní profil?" + "Vaše pracovní aplikace, oznámení, data a ostatní funkce pracovního účtu budou zapnuty" "Zapnout" - - - - + "Tato aplikace byla vytvořena pro starší verzi systému Android a nemusí fungovat správně. Zkuste vyhledat aktualizace, případně kontaktujte vývojáře." + "Zkontrolovat aktualizace" "Máte nové zprávy" "Zobrazíte je v aplikaci pro SMS" "Funkce mohou být omezeny" @@ -1902,17 +1900,15 @@ "Telefon není povolen pro hlasovou komunikaci" "Vyskakovací okno" "a ještě %1$d" - "Tato zkratka vyžaduje nejnovější verzi aplikace" + + "Zkratku nelze obnovit, protože aplikace nepodporuje zálohování a obnovu" "Zkratku nelze obnovit, protože se neshoduje podpis aplikace" "Zkratku nelze obnovit" "Zkratka nefunguje" - - - - - - + "ODINSTALOVAT" + "PŘESTO OTEVŘÍT" + "Byla zjištěna škodlivá aplikace" "Aplikace %1$s chce zobrazovat ukázky z aplikace %2$s" "Upravit" diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 0f774d6b5ff62fbe1757818e9674e13b8bf3f2e6..873dd61581ebf85e40d7b62c5a381a3bc981bbea 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -417,10 +417,8 @@ "Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call." "route calls through the system" "Allows the app to route its calls through the system in order to improve the calling experience." - - - - + "continue a call from another app" + "Allows the app to continue a call which was started in another app." "read phone numbers" "Allows the app to access the phone numbers of the device." "prevent tablet from sleeping" @@ -499,6 +497,10 @@ "Too many attempts. Try again later." "Too many attempts. Fingerprint sensor disabled." "Try again." + + + + "Finger %d" @@ -997,12 +999,9 @@ "Open" "Message" "Add" - - - - - - + "View" + "Schedule" + "Track" "Storage space running out" "Some system functions may not work" "Not enough storage for the system. Make sure that you have 250 MB of free space and restart." @@ -1128,8 +1127,7 @@ Open Wi-Fi network available "Connect to open Wi‑Fi network" - - + "Connect to operator Wi‑Fi network" "Connecting to open Wi‑Fi network" "Connected to Wi‑Fi network" "Could not connect to Wi‑Fi network" @@ -1213,13 +1211,23 @@ "No permission required" "this may cost you money" "OK" - "USB charging this device" - "USB supplying power to attached device" - "USB for file transfer" - "USB for photo transfer" - "USB for MIDI" - "Connected to a USB accessory" + + + + + + + + + + + + + + "Tap for more options." + + "Analogue audio accessory detected" "The attached device is not compatible with this phone. Tap to learn more." "USB debugging connected" @@ -1658,9 +1666,6 @@ "Work %1$s" "2nd Work %1$s" "3rd Work %1$s" - "To unpin this screen, touch & hold Back and Overview buttons" - "Screen pinned" - "Screen unpinned" "Ask for PIN before unpinning" "Ask for unlock pattern before unpinning" "Ask for password before unpinning" @@ -1757,10 +1762,8 @@ "Turn on work profile?" "Your work apps, notifications, data and other work profile features will be turned on" "Turn on" - - - - + "This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer." + "Check for update" "You have new messages" "Open SMS app to view" "Some functionality may be limited" @@ -1827,17 +1830,15 @@ "Phone not allowed for voice" "Pop-Up Window" "+ %1$d" - "This shortcut requires latest app" + + "Couldn’t restore shortcut because app doesn’t support backup and restore" "Couldn’t restore shortcut because of app signature mismatch" "Couldn’t restore shortcut" "Shortcut is disabled" - - - - - - + "UNINSTALL" + "OPEN ANYWAY" + "Harmful app detected" "%1$s wants to show %2$s slices" "Edit" diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 0f774d6b5ff62fbe1757818e9674e13b8bf3f2e6..873dd61581ebf85e40d7b62c5a381a3bc981bbea 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -417,10 +417,8 @@ "Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call." "route calls through the system" "Allows the app to route its calls through the system in order to improve the calling experience." - - - - + "continue a call from another app" + "Allows the app to continue a call which was started in another app." "read phone numbers" "Allows the app to access the phone numbers of the device." "prevent tablet from sleeping" @@ -499,6 +497,10 @@ "Too many attempts. Try again later." "Too many attempts. Fingerprint sensor disabled." "Try again." + + + + "Finger %d" @@ -997,12 +999,9 @@ "Open" "Message" "Add" - - - - - - + "View" + "Schedule" + "Track" "Storage space running out" "Some system functions may not work" "Not enough storage for the system. Make sure that you have 250 MB of free space and restart." @@ -1128,8 +1127,7 @@ Open Wi-Fi network available "Connect to open Wi‑Fi network" - - + "Connect to operator Wi‑Fi network" "Connecting to open Wi‑Fi network" "Connected to Wi‑Fi network" "Could not connect to Wi‑Fi network" @@ -1213,13 +1211,23 @@ "No permission required" "this may cost you money" "OK" - "USB charging this device" - "USB supplying power to attached device" - "USB for file transfer" - "USB for photo transfer" - "USB for MIDI" - "Connected to a USB accessory" + + + + + + + + + + + + + + "Tap for more options." + + "Analogue audio accessory detected" "The attached device is not compatible with this phone. Tap to learn more." "USB debugging connected" @@ -1658,9 +1666,6 @@ "Work %1$s" "2nd Work %1$s" "3rd Work %1$s" - "To unpin this screen, touch & hold Back and Overview buttons" - "Screen pinned" - "Screen unpinned" "Ask for PIN before unpinning" "Ask for unlock pattern before unpinning" "Ask for password before unpinning" @@ -1757,10 +1762,8 @@ "Turn on work profile?" "Your work apps, notifications, data and other work profile features will be turned on" "Turn on" - - - - + "This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer." + "Check for update" "You have new messages" "Open SMS app to view" "Some functionality may be limited" @@ -1827,17 +1830,15 @@ "Phone not allowed for voice" "Pop-Up Window" "+ %1$d" - "This shortcut requires latest app" + + "Couldn’t restore shortcut because app doesn’t support backup and restore" "Couldn’t restore shortcut because of app signature mismatch" "Couldn’t restore shortcut" "Shortcut is disabled" - - - - - - + "UNINSTALL" + "OPEN ANYWAY" + "Harmful app detected" "%1$s wants to show %2$s slices" "Edit" diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 0f774d6b5ff62fbe1757818e9674e13b8bf3f2e6..873dd61581ebf85e40d7b62c5a381a3bc981bbea 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -417,10 +417,8 @@ "Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call." "route calls through the system" "Allows the app to route its calls through the system in order to improve the calling experience." - - - - + "continue a call from another app" + "Allows the app to continue a call which was started in another app." "read phone numbers" "Allows the app to access the phone numbers of the device." "prevent tablet from sleeping" @@ -499,6 +497,10 @@ "Too many attempts. Try again later." "Too many attempts. Fingerprint sensor disabled." "Try again." + + + + "Finger %d" @@ -997,12 +999,9 @@ "Open" "Message" "Add" - - - - - - + "View" + "Schedule" + "Track" "Storage space running out" "Some system functions may not work" "Not enough storage for the system. Make sure that you have 250 MB of free space and restart." @@ -1128,8 +1127,7 @@ Open Wi-Fi network available "Connect to open Wi‑Fi network" - - + "Connect to operator Wi‑Fi network" "Connecting to open Wi‑Fi network" "Connected to Wi‑Fi network" "Could not connect to Wi‑Fi network" @@ -1213,13 +1211,23 @@ "No permission required" "this may cost you money" "OK" - "USB charging this device" - "USB supplying power to attached device" - "USB for file transfer" - "USB for photo transfer" - "USB for MIDI" - "Connected to a USB accessory" + + + + + + + + + + + + + + "Tap for more options." + + "Analogue audio accessory detected" "The attached device is not compatible with this phone. Tap to learn more." "USB debugging connected" @@ -1658,9 +1666,6 @@ "Work %1$s" "2nd Work %1$s" "3rd Work %1$s" - "To unpin this screen, touch & hold Back and Overview buttons" - "Screen pinned" - "Screen unpinned" "Ask for PIN before unpinning" "Ask for unlock pattern before unpinning" "Ask for password before unpinning" @@ -1757,10 +1762,8 @@ "Turn on work profile?" "Your work apps, notifications, data and other work profile features will be turned on" "Turn on" - - - - + "This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer." + "Check for update" "You have new messages" "Open SMS app to view" "Some functionality may be limited" @@ -1827,17 +1830,15 @@ "Phone not allowed for voice" "Pop-Up Window" "+ %1$d" - "This shortcut requires latest app" + + "Couldn’t restore shortcut because app doesn’t support backup and restore" "Couldn’t restore shortcut because of app signature mismatch" "Couldn’t restore shortcut" "Shortcut is disabled" - - - - - - + "UNINSTALL" + "OPEN ANYWAY" + "Harmful app detected" "%1$s wants to show %2$s slices" "Edit" diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 0f774d6b5ff62fbe1757818e9674e13b8bf3f2e6..873dd61581ebf85e40d7b62c5a381a3bc981bbea 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -417,10 +417,8 @@ "Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call." "route calls through the system" "Allows the app to route its calls through the system in order to improve the calling experience." - - - - + "continue a call from another app" + "Allows the app to continue a call which was started in another app." "read phone numbers" "Allows the app to access the phone numbers of the device." "prevent tablet from sleeping" @@ -499,6 +497,10 @@ "Too many attempts. Try again later." "Too many attempts. Fingerprint sensor disabled." "Try again." + + + + "Finger %d" @@ -997,12 +999,9 @@ "Open" "Message" "Add" - - - - - - + "View" + "Schedule" + "Track" "Storage space running out" "Some system functions may not work" "Not enough storage for the system. Make sure that you have 250 MB of free space and restart." @@ -1128,8 +1127,7 @@ Open Wi-Fi network available "Connect to open Wi‑Fi network" - - + "Connect to operator Wi‑Fi network" "Connecting to open Wi‑Fi network" "Connected to Wi‑Fi network" "Could not connect to Wi‑Fi network" @@ -1213,13 +1211,23 @@ "No permission required" "this may cost you money" "OK" - "USB charging this device" - "USB supplying power to attached device" - "USB for file transfer" - "USB for photo transfer" - "USB for MIDI" - "Connected to a USB accessory" + + + + + + + + + + + + + + "Tap for more options." + + "Analogue audio accessory detected" "The attached device is not compatible with this phone. Tap to learn more." "USB debugging connected" @@ -1658,9 +1666,6 @@ "Work %1$s" "2nd Work %1$s" "3rd Work %1$s" - "To unpin this screen, touch & hold Back and Overview buttons" - "Screen pinned" - "Screen unpinned" "Ask for PIN before unpinning" "Ask for unlock pattern before unpinning" "Ask for password before unpinning" @@ -1757,10 +1762,8 @@ "Turn on work profile?" "Your work apps, notifications, data and other work profile features will be turned on" "Turn on" - - - - + "This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer." + "Check for update" "You have new messages" "Open SMS app to view" "Some functionality may be limited" @@ -1827,17 +1830,15 @@ "Phone not allowed for voice" "Pop-Up Window" "+ %1$d" - "This shortcut requires latest app" + + "Couldn’t restore shortcut because app doesn’t support backup and restore" "Couldn’t restore shortcut because of app signature mismatch" "Couldn’t restore shortcut" "Shortcut is disabled" - - - - - - + "UNINSTALL" + "OPEN ANYWAY" + "Harmful app detected" "%1$s wants to show %2$s slices" "Edit" diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 8160f0d3a0fae0b369f92d9c594ffa3b85dd2760..85cfb87ba63d672dea6efea6b411c89a838332da 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -417,10 +417,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‎‎Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active, and the remote number connected by a call.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‎route calls through the system‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎Allows the app to route its calls through the system in order to improve the calling experience.‎‏‎‎‏‎" - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎continue a call from another app‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎Allows the app to continue a call which was started in another app.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎read phone numbers‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎Allows the app to access the phone numbers of the device.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎prevent tablet from sleeping‎‏‎‎‏‎" @@ -499,6 +497,10 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎Too many attempts. Try again later.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‏‎Too many attempts. Fingerprint sensor disabled.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎Try again.‎‏‎‎‏‎" + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎Finger ‎‏‎‎‏‏‎%d‎‏‎‎‏‏‏‎‎‏‎‎‏‎" @@ -997,12 +999,9 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎Open‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎Message‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎Add‎‏‎‎‏‎" - - - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎View‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎Schedule‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎Track‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎Storage space running out‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎Some system functions may not work‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎Not enough storage for the system. Make sure you have 250MB of free space and restart.‎‏‎‎‏‎" @@ -1128,8 +1127,7 @@ ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎Open Wi-Fi network available‎‏‎‎‏‎ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎Connect to open Wi‑Fi network‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎Connect to carrier Wi‑Fi network‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎Connecting to open Wi‑Fi network‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎Connected to Wi‑Fi network‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎Could not connect to Wi‑Fi network‎‏‎‎‏‎" @@ -1213,13 +1211,23 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‎No permissions required‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎this may cost you money‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎OK‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎USB charging this device‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎USB supplying power to attached device‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎USB for file transfer‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎USB for photo transfer‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎USB for MIDI‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎Connected to a USB accessory‎‏‎‎‏‎" + + + + + + + + + + + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‎Tap for more options.‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎Analog audio accessory detected‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎The attached device is not compatible with this phone. Tap to learn more.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎USB debugging connected‎‏‎‎‏‎" @@ -1658,9 +1666,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎Work ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎2nd Work ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎3rd Work ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‎To unpin this screen, touch & hold Back and Overview buttons‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎Screen pinned‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎Screen unpinned‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‎‎Ask for PIN before unpinning‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‎Ask for unlock pattern before unpinning‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‎Ask for password before unpinning‎‏‎‎‏‎" @@ -1757,10 +1762,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎Turn on work profile?‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎Your work apps, notifications, data, and other work profile features will be turned on‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎Turn on‎‏‎‎‏‎" - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎Check for update‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎You have new messages‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎Open SMS app to view‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎Some functionality may be limited‎‏‎‎‏‎" @@ -1827,17 +1830,15 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎Phone not allowed for voice‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎Popup Window‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‎+ ‎‏‎‎‏‏‎%1$d‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‎This shortcut requires latest app‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‏‏‎‎Couldn’t restore shortcut because app doesn’t support backup and restore‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎Couldn’t restore shortcut because of app signature mismatch‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎Couldn’t restore shortcut‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‎Shortcut is disabled‎‏‎‎‏‎" - - - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎UNINSTALL‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎OPEN ANYWAY‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎Harmful app detected‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ wants to show ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ slices‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎Edit‎‏‎‎‏‎" diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index d1a2fa337330d891531f388d4898780322167b5c..487d68af53fd68b61537b942e3a64aade461e8f2 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Modo seguro" "Sistema Android" - - - - + "Cambiar al perfil personal" + "Cambiar al perfil de trabajo" "Contactos" "acceder a tus contactos" "Permite que <b>%1$s</b> acceda a tus contactos" @@ -419,10 +417,8 @@ "Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada." "direccionar llamadas a través del sistema" "Permite a la aplicación direccionar sus llamadas hacia el sistema para mejorar la calidad de estas." - - - - + "continuar una llamada de otra aplicación" + "Permite que la aplicación continúe una llamada que se ha iniciado en otra aplicación." "leer números de teléfono" "Permite que la aplicación acceda a los números de teléfono del dispositivo." "impedir que el tablet entre en modo de suspensión" @@ -497,11 +493,14 @@ "No se puede almacenar la huella digital. Elimina una ya creada." "Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo." "Se ha cancelado la operación de huella digital." - - + "El usuario ha cancelado la operación de huella digital." "Demasiados intentos. Vuelve a intentarlo más tarde." "Demasiados intentos. Se ha inhabilitado el sensor de huellas digitales." "Vuelve a intentarlo." + + + + "Dedo %d" @@ -1000,12 +999,9 @@ "Abrir" "Mensaje" "Añadir" - - - - - - + "Ver" + "Programar" + "Buscar" "Queda poco espacio" "Es posible que algunas funciones del sistema no funcionen." "No hay espacio suficiente para el sistema. Comprueba que haya 250 MB libres y reinicia el dispositivo." @@ -1131,8 +1127,7 @@ Red Wi-Fi abierta disponible "Conectarse a una red Wi-Fi abierta" - - + "Conectarse a la red Wi‑Fi de un operador" "Conectándose a una red Wi-Fi abierta" "Conectado a la red Wi-Fi" "No se ha podido conectar a la red Wi-Fi" @@ -1216,13 +1211,23 @@ "No es necesario ningún permiso" "es posible que esto te cueste dinero" "Aceptar" - "Cargando este dispositivo por USB" - "El dispositivo conectado recibe la alimentación por USB" - "USB para transferir archivos" - "USB para transferir fotos" - "USB para MIDI" - "Conectado a un accesorio USB" + + + + + + + + + + + + + + "Toca para ver más opciones." + + "Se ha detectado un accesorio de audio analógico" "El dispositivo adjunto no es compatible con este teléfono. Toca para obtener más información." "Depuración USB habilitada" @@ -1661,9 +1666,6 @@ "%1$s de trabajo" "%1$s de trabajo 2" "%1$s de trabajo 3" - "Mantén pulsado el botón Atrás y el de aplicaciones recientes para dejar de fijar esta pantalla" - "Pantalla fijada" - "La pantalla ya no está fija" "Solicitar PIN para desactivar" "Solicitar patrón de desbloqueo para desactivar" "Solicitar contraseña para desactivar" @@ -1757,15 +1759,11 @@ "Todos los idiomas" "Todas las regiones" "Buscar" - - - - + "¿Activar el perfil de trabajo?" + "Tus aplicaciones, notificaciones, datos y otras funciones del perfil de trabajo se activarán" "Activar" - - - - + "Esta aplicación se ha diseñado para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o ponte en contacto con el desarrollador." + "Comprobar actualizaciones" "Tienes mensajes nuevos" "Abre la aplicación de SMS para ver el mensaje" "Algunas funciones limitadas" @@ -1832,17 +1830,15 @@ "Teléfono no permitido para voz" "Ventana emergente" "%1$d más" - "Para usar este acceso directo, necesitas la última versión de la aplicación" + + "No se ha podido restaurar el acceso directo porque la aplicación no es compatible con la función de copia de seguridad y restauración" "No se ha podido restaurar el acceso directo porque la firma de la aplicación no coincide" "No se ha podido restaurar el acceso directo" "El acceso directo está inhabilitado" - - - - - - + "DESINSTALAR" + "ABRIR IGUALMENTE" + "Se ha detectado una aplicación dañina" "%1$s quiere mostrar fragmentos de %2$s" "Editar" diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index e5ed2a37af35528ced591a6ec8a668360aafb136..8d1350a6f22622efb51ce540a691afa1f36f6563 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Suojattu tila" "Android-järjestelmä" - - - - + "Vaihda henkilökohtaiseen profiiliin" + "Vaihda työprofiiliin" "Kontaktit" "käyttää yhteystietoja" "Anna sovellukselle <b>%1$s</b> yhteystietojesi käyttöoikeus." @@ -419,10 +417,8 @@ "Antaa sovelluksen käyttää laitteen puhelinominaisuuksia. Sovellus voi määrittää puhelinnumeron ja laitteen tunnuksen, puhelun tilan sekä soitetun numeron." "ohjata puhelut järjestelmän kautta" "Tämä sallii sovelluksen ohjata puhelut järjestelmän kautta, mikä auttaa parantamaan puhelujen laatua." - - - - + "jatkaa toisen sovelluksen puhelua" + "Antaa sovelluksen jatkaa puhelua, joka aloitettiin toisessa sovelluksessa." "lukea puhelinnumeroita" "Anna sovelluksen käyttää laitteella olevia puhelinnumeroita." "estä tablet-laitetta menemästä virransäästötilaan" @@ -497,11 +493,14 @@ "Sormenjälkeä ei voida tallentaa. Poista aiemmin lisätty sormenjälki." "Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen." "Sormenjälkitoiminto peruutettiin." - - + "Käyttäjä peruutti sormenjälkitoiminnon." "Liian monta yritystä. Yritä myöhemmin uudelleen." "Liian monta yritystä. Sormenjälkitunnistin poistettu käytöstä." "Yritä uudelleen." + + + + "Sormi %d" @@ -1000,12 +999,9 @@ "Avaa" "Viesti" "Lisää" - - - - - - + "Näytä" + "Aikataulu" + "Seuraa" "Tallennustila loppumassa" "Kaikki järjestelmätoiminnot eivät välttämättä toimi" "Tallennustila ei riitä. Varmista, että vapaata tilaa on 250 Mt, ja käynnistä uudelleen." @@ -1131,8 +1127,7 @@ Avoin Wi-Fi-verkko käytettävissä "Yhdistä avoimeen Wi‑Fi-verkkoon" - - + "Yhdistä operaattorin Wi-Fi-verkkoon" "Yhdistetään avoimeen Wi‑Fi-verkkoon" "Yhdistetty Wi-Fi-verkkoon" "Wi‑Fi-verkkoon yhdistäminen epäonnistui" @@ -1216,13 +1211,23 @@ "Lupia ei tarvita" "tämä voi maksaa" "OK" - "Laitetta ladataan USB-yhteyden kautta" - "Liitetty laite saa virtaa USB-yhteyden kautta" - "USB on tiedonsiirtotilassa" - "USB on kuvansiirtotilassa" - "USB on MIDI-tilassa" - "Liitetty USB-laitteeseen" + + + + + + + + + + + + + + "Näet lisää vaihtoehtoja napauttamalla." + + "Analoginen äänilaite havaittu" "Liitetty laite ei ole yhteensopiva puhelimen kanssa. Napauta, niin näet lisätietoja." "USB-vianetsintä yhdistetty" @@ -1661,9 +1666,6 @@ "%1$s (työ)" "Toinen %1$s, työ" "Kolmas %1$s, työ" - "Irrota näyttö koskettamalla pitkään Takaisin- ja Viimeisimmät-painikkeita" - "Näyttö kiinnitetty" - "Näyttö irrotettu" "Pyydä PIN ennen irrotusta" "Pyydä lukituksenpoistokuvio ennen irrotusta" "Pyydä salasana ennen irrotusta" @@ -1757,15 +1759,11 @@ "Kaikki kielet" "Kaikki alueet" "Haku" - - - - + "Otetaanko työprofiili käyttöön?" + "Työsovellukset, ‑ilmoitukset, ‑tiedot ja muut työprofiiliominaisuudet otetaan käyttöön" "Ota käyttöön" - - - - + "Tämä sovellus on suunniteltu vanhemmalle Android-versiolle eikä välttämättä toimi oikein. Kokeile tarkistaa päivitykset tai ottaa yhteyttä kehittäjään." + "Tarkista päivitykset" "Sinulle on uusia viestejä" "Katso avaamalla tekstiviestisovellus." "Toimintorajoitus mahdollinen" @@ -1832,17 +1830,15 @@ "Äänipalvelujen käyttö ei sallittua puhelimella" "Ponnahdusikkuna" "+ %1$d" - "Tämä pikakuvake edellyttää uusinta sovellusta." + + "Pikakuvakkeen palautus epäonnistui, koska sovellus ei tue varmuuskopiointia eikä palauttamista." "Pikakuvakkeen palautus epäonnistui sovelluksen allekirjoituksen yhteensopimattomuuden vuoksi." "Pikakuvakkeen palautus epäonnistui." "Pikakuvake on poistettu käytöstä." - - - - - - + "POISTA" + "AVAA SILTI" + "Haitallinen sovellus havaittu" "%1$s haluaa näyttää osia sovelluksesta %2$s." "Muokkaa" diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index aa6608aeaa5c219ed627d89dd4254a06cfbd297e..2891b8ca28f76fd5b250b550ac220f37989c9fd7 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -181,6 +181,7 @@ "Votre organisation gère cet appareil et peut surveiller le trafic réseau. Touchez ici pour obtenir plus d\'information." "Le contenu de votre appareil sera effacé" "Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation." + "Impression désactivée par %s." "Moi" "Options de la tablette" "Options du téléviseur" @@ -263,8 +264,8 @@ "%1$s, %2$s" "Mode sans échec" "Système Android" - "Passer au profil personnel" - "Passer au profil professionnel" + "Passer au profil personnel" + "Passer au profil professionnel" "Contacts" "accéder à vos contacts" "Autoriser « %1$s » à accéder à vos contacts" @@ -416,6 +417,8 @@ "Permet à l\'application d\'accéder aux fonctionnalités téléphoniques de l\'appareil. Cette autorisation permet à l\'application de déterminer le numéro de téléphone et les identifiants de l\'appareil, si un appel est actif et le numéro distant connecté par un appel." "acheminer les appels dans le système" "Permet à l\'application d\'acheminer ses appels dans le système afin d\'améliorer l\'expérience d\'appel." + "continuer un appel d\'une autre application" + "Permet à l\'application de continuer un appel commencé dans une autre application." "lire les numéros de téléphone" "Permet à l\'application d\'accéder aux numéros de téléphone de l\'appareil." "empêcher la tablette de passer en mode veille" @@ -485,13 +488,19 @@ "Vous avez déplacé votre doigt trop lentement. Veuillez réessayer." + "Doigt non reconnu" "Matériel d\'empreinte numérique indisponible." "L\'empreinte digitale ne peut pas être enregistrée. Veuillez supprimer une empreinte existante." "Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau." "Opération d\'empreinte numérique annulée." + "L\'opération d\'empreinte digitale a été annulée par l\'utilisateur." "Trop de tentatives. Veuillez réessayer plus tard." "Trop de tentatives. Capteur d\'empreintes digitales désactivé." "Réessayer." + + + + "Doigt %d" @@ -990,6 +999,9 @@ "Ouvrir" "Message" "Ajouter" + "Afficher" + "Calendrier" + "Effectuer le suivi" "Espace de stockage bientôt saturé" "Il est possible que certaines fonctionnalités du système ne soient pas opérationnelles." "Espace de stockage insuffisant pour le système. Assurez-vous de disposer de 250 Mo d\'espace libre, puis redémarrez." @@ -1115,6 +1127,7 @@ Réseaux Wi-Fi ouverts à proximité "Connectez-vous pour ouvrir un réseau Wi-Fi" + "Se connecter au réseau Wi-Fi du fournisseur de services" "Connexion en cours au réseau Wi-Fi ouvert…" "Connecté au réseau Wi-Fi" "Impossible de se connecter au réseau Wi-Fi" @@ -1198,13 +1211,23 @@ "Aucune autorisation requise" "cela peut engendrer des frais" "OK" - "Cet appareil est en cours de charge par USB" - "Un connecteur USB alimente cet appareil" - "USB pour le transfert de fichiers" - "USB pour le transfert de photos" - "USB pour MIDI" - "Connecté à un accessoire USB" + + + + + + + + + + + + + + "Touchez pour afficher plus d\'options." + + "Un accessoire audio analogique a été détecté" "L\'appareil connecté n\'est pas compatible avec ce téléphone. Touchez ici en savoir plus." "Débogage USB activé" @@ -1412,6 +1435,8 @@ "%s au-delà de la limite spécifiée." "Données en arrière-plan limitées" "Touchez pour suppr. restriction." + "Consomm. importante de données" + "Votre consommation récente de données est plus importante que d\'habitude. Touchez l\'écran pour afficher l\'usage et les paramètres." "Certificat de sécurité" "Ce certificat est valide." "Émis à :" @@ -1641,9 +1666,6 @@ "%1$s (travail)" "2e %1$s professionnel(le)" "3e %1$s professionnel(le)" - "Pour annuler l\'épinglage de cet écran, maintenez enfoncés les boutons Retour et Aperçu." - "Écran épinglé" - "Épinglage d\'écran annulé" "Demander le NIP avant d\'annuler l\'épinglage" "Demander le schéma de déverrouillage avant d\'annuler l\'épinglage" "Demander le mot de passe avant d\'annuler l\'épinglage" @@ -1688,7 +1710,7 @@ "Jusqu\'à %1$s" "Jusqu\'à %1$s (alarme suivante)" - "Jusqu\'à ce que vous désactiviez ce mode" + "Jusqu\'à la désactivation" "Jusqu\'à ce que vous désactiviez le mode « Ne pas déranger »" "%1$s / %2$s" "Réduire" @@ -1737,9 +1759,11 @@ "Toutes les langues" "Toutes les régions" "Rechercher" - "Activer le mode professionnel?" - "Votre profil professionnel sera activé, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées" + "Activer le profil professionnel?" + "Vos applications professionnelles, vos notifications, vos données et les autres fonctionnalités de profil professionnel seront activées" "Activer" + "Cette application a été conçue pour une ancienne version d\'Android et pourrait ne pas fonctionner correctement. Essayez de vérifier les mises à jour ou communiquez avec son concepteur." + "Vérifier la présence de mises à jour" "Vous avez de nouveaux messages" "Ouvrez l\'application de messagerie texte pour l\'afficher" "Certaines fonct. sont limitées" @@ -1806,12 +1830,15 @@ "Ce téléphone n\'est pas autorisé pour la voix" "Fenêtre contextuelle" "+ %1$d" - "Ce raccourci nécessite la dernière version de l\'application" + + "Impossible de restaurer le raccourci, car l\'application ne prend pas en charge la sauvegarde et la restauration" "Impossible de restaurer le raccourci en raison d\'une erreur de correspondance des signature d\'applications" "Impossible de restaurer le raccourci" "Le raccourci est désactivé" - "Désinstaller" - "Lancer quand même" - "Désinstaller l\'application nuisible?" + "DÉSINSTALLER" + "OUVRIR QUAND MÊME" + "Une application nuisible a été détectée" + "%1$s souhaite afficher %2$s tranches" + "Modifier" diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 0ed3d6d412dd0ac08979b141e26dc5354bd069b7..9356c969ed03240039bbf3e9411632d0119a1bd8 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "સુરક્ષિત મોડ" "Android સિસ્ટમ" - - - - + "વ્યક્તિગત પ્રોફાઇલ પર સ્વિચ કરો" + "કાર્યાલયની પ્રોફાઇલ પર સ્વિચ કરો" "સંપર્કો" "તમારા સંપર્કોને ઍક્સેસ કરવાની" "<b>%1$s</b>ને તમારા સંપર્કોને ઍક્સેસ કરવાની મંજૂરી આપો" @@ -419,10 +417,8 @@ "એપ્લિકેશનને ફોન સુવિધાઓને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને ફોન નંબર અને ઉપકરણ ID, કૉલ સક્રિય છે અને કોઈ કૉલ દ્વારા કનેક્ટ થયેલ રિમોટ નંબર નિર્ધારિત કરવાની મંજૂરી આપે છે." "સિસ્ટમ મારફતે કૉલ બીજે વાળો" "કૉલિંગ અનુભવ સુધારવા માટે ઍપ્લિકેશનને સિસ્ટમ મારફતે કૉલ બીજે વાળવાની મંજૂરી આપે છે." - - - - + "તૃતીય પક્ષ ઍપમાંનો કૉલ ચાલુ રાખો" + "એક અન્ય તૃતીય પક્ષ ઍપમાં ચાલુ થયેલા કૉલને આ ઍપમાં ચાલુ રાખવાની મંજૂરી આપે છે." "ફોન નંબર વાંચો" "ઍપ્લિકેશનને ઉપકરણનાં ફોન નંબરને ઍક્સેસ કરવાની મંજૂરી આપે છે." "ટેબ્લેટને નિષ્ક્રિય થતું અટકાવો" @@ -497,11 +493,14 @@ "ફિંગરપ્રિન્ટ સંગ્રહિત કરી શકાતી નથી. કૃપા કરીને અસ્તિત્વમાંની ફિંગરપ્રિન્ટ દૂર કરો." "ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો." "ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું." - - + "ફિંગરપ્રિન્ટ ચકાસવાની પ્રક્રિયા વપરાશકર્તાએ રદ કરી." "ઘણા બધા પ્રયત્નો. પછીથી ફરી પ્રયાસ કરો." "ઘણા વધુ પ્રયત્નો. ફિંગરપ્રિન્ટ સેન્સર અક્ષમ કરવામાં આવ્યું છે." "ફરી પ્રયાસ કરો." + + + + "આંગળી %d" @@ -1000,12 +999,9 @@ "ખોલો" "સંદેશ મોકલો" "ઉમેરો" - - - - - - + "જુઓ" + "શેડ્યૂલ કરો" + "ટ્રૅક કરો" "સ્ટોરેજ સ્થાન સમાપ્ત થયું" "કેટલાક સિસ્ટમ કાર્યો કામ કરી શકશે નહીં" "સિસ્ટમ માટે પર્યાપ્ત સ્ટોરેજ નથી. ખાતરી કરો કે તમારી પાસે 250MB ખાલી સ્થાન છે અને ફરીથી પ્રારંભ કરો." @@ -1131,8 +1127,7 @@ ખુલ્લા વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ છે "ખુલ્લા વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરો" - - + "કૅરિઅરના વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરો" "ખુલ્લા વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરી રહ્યાં છીએ" "વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કર્યુ" "વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરી શકાયું નથી" @@ -1217,13 +1212,23 @@ "કોઈ પરવાનગીઓ જરૂરી નથી" "આનાથી તમારા પૈસા ખર્ચ થઈ શકે છે" "ઓકે" - "આ ઉપકરણને USB થી ચાર્જ કરે છે" - "જોડાયેલ ઉપકરણ માટે USB પાવર પૂરો પાડે છે" - "ફાઇલ ટ્રાન્સફર માટે USB" - "ફોટો ટ્રાન્સફર માટે USB" - "MIDI માટે USB" - "USB ઍક્સેસરીથી કનેક્ટ થયાં" + + + + + + + + + + + + + + "વધુ વિકલ્પો માટે ટૅપ કરો." + + "એનાલોગ ઑડિઓ ઍક્સેસરી મળી" "જોડેલ ઉપકરણ આ ફોન સાથે સુસંગત નથી. વધુ જાણવા માટે ટૅપ કરો." "USB ડીબગિંગ કનેક્ટ થયું." @@ -1662,9 +1667,6 @@ "કાર્યાલય %1$s" "2જું કાર્ય %1$s" "3જું કાર્ય %1$s" - "આ સ્ક્રીનને અનપિન કરવા માટે, પાછળ અને ઝલક બટનોને સ્પર્શ કરી રાખો" - "સ્ક્રીન પિન કરી" - "સ્ક્રીન અનપિન કરી" "અનપિન કરતા પહેલાં પિન માટે પૂછો" "અનપિન કરતા પહેલાં અનલૉક પૅટર્ન માટે પૂછો" "અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો" @@ -1758,15 +1760,11 @@ "બધી ભાષાઓ" "તમામ પ્રદેશ" "શોધ" - - - - + "કાર્યાલયની પ્રોફાઇલ ચાલુ કરીએ?" + "તમારી કાર્યાલયની ઍપ, નોટિફિકેશન, ડેટા અને અન્ય કાર્યાલયની પ્રોફાઇલ સુવિધાઓ ચાલુ કરવામાં આવશે" "ચાલુ કરો" - - - - + "આ ઍપ Androidના જૂના વર્ઝન માટે બનાવવામાં આવ્યું હતું અને તે કદાચ તે યોગ્ય રીતે કાર્ય કરી શકશે નહીં. અપડેટ માટે તપાસવાનો પ્રયાસ કરો અથવા ડેવલપરનો સંપર્ક કરો." + "અપડેટ માટે તપાસો" "તમારી પાસે નવા સંદેશા છે" "જોવા માટે SMS ઍપ્લિકેશન ખોલો" "કેટલીક કાર્યક્ષમતા મર્યાદિત હોઈ શકે છે" @@ -1833,17 +1831,15 @@ "વૉઇસ માટે આ ફોનને મંજૂરી નથી" "પૉપઅપ વિંડો" "+ %1$d" - "આ શૉર્ટકટ માટે નવી ઍપ જરૂરી છે" + + "શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપ બૅકઅપ અને ફરી મેળવવાનું સમર્થન કરતી નથી" "શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપમાં છે તે સહી મેળ ખાતી નથી" "શૉર્ટકટ પાછો મેળવી શકાયો નથી" "શૉર્ટકટને બંધ કરવામાં આવ્યો છે" - - - - - - + "અનઇન્સ્ટૉલ કરો" + "કોઈપણ રીતે ખોલો" + "નુકસાનકારક ઍપ મળી આવી છે" "%1$s%2$s સ્લાઇસ બતાવવા માગે છે" "ફેરફાર કરો" diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index d9f592c396a1e384dd10d83dfbf60bee8f6b226e..9dc0e2f23ec9f521f11e2c82c77a0cfa0d2e5dd1 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "सुरक्षित मोड" "Android सिस्‍टम" - - - - + "प्रोफ़ाइल बदलकर निजी प्रोफ़ाइल पर जाएं" + "प्रोफ़ाइल बदलकर कार्य प्रोफ़ाइल पर जाएं" "संपर्क" "अपने संपर्कों को ऐक्सेस करने की" "<b>%1$s</b> को अपने संपर्क तक पहुंचने दें" @@ -419,10 +417,8 @@ "ऐप्स को डिवाइस की फ़ोन सुविधाओं तक पहुंचने देता है. यह अनुमति ऐप्स को फ़ोन नंबर और डिवाइस आईडी, कॉल सक्रिय है या नहीं, और कॉल द्वारा कनेक्ट किया गया दूरस्‍थ नंबर निर्धारित करने देती है." "सिस्टम के माध्यम से कॉल रूट करें" "कॉल करने के अनुभव को बेहतर बनाने के लिए ऐप्लिकेशन को सिस्टम के माध्यम से उसके कॉल रूट करने देती है." - - - - + "दूसरे ऐप्लिकेशन से शुरू किया गया कॉल जारी रखें" + "इसके ज़रिए आप, किसी ऐप्लिकेशन में शुरू किया गया कॉल दूसरे ऐप्लिकेशन में जारी रख सकते हैं." "फ़ोन नंबर पढ़ना" "ऐप को डिवाइस के फ़ोन नंबर का इस्तेमाल करने देती है." "टैबलेट को सोने (कम बैटरी मोड) से रोकें" @@ -497,11 +493,14 @@ "फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें." "फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें." "फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया." - - + "उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि की कार्रवाई रद्द कर दी है." "बहुत अधिक प्रयास कर लिए गए हैं. बाद में पुन: प्रयास करें." "बहुत अधिक कोशिशें. फ़िंगरप्रिंट सेंसर अक्षम है." "पुन: प्रयास करें." + + + + "उंगली %d" @@ -1000,12 +999,9 @@ "खोलें" "मैसेज" "जोड़ें" - - - - - - + "देखें" + "शेड्यूल करें" + "मौजूदा स्थिति जानें" "मेमोरी में जगह नहीं बची है" "हो सकता है कुछ सिस्टम फ़ंक्शन कार्य न करें" "सिस्टम के लिए ज़रूरी मेमोरी नहीं है. पक्का करें कि आपके पास 250एमबी की खाली जगह है और फिर से शुरू करें." @@ -1131,8 +1127,7 @@ खुले वाई-फ़ाई नेटवर्क उपलब्‍ध "खुले वाई-फ़ाई नेटवर्क से कनेक्ट करें" - - + "मोबाइल और इंटरनेट सेवा देने वाली कंपनी के वाई-फ़ाई नेटवर्क से कनेक्ट करें" "खुले वाई-फ़ाई नेटवर्क से कनेक्ट हो रहा है" "वाई-फ़ाई नेटवर्क से कनेक्‍ट हो गया है" "वाई-फ़ाई नेटवर्क से कनेक्‍ट नहीं हो सका" @@ -1216,13 +1211,23 @@ "किसी अनुमति की आवश्‍यकता नहीं है" "इससे आपको धन देना पड़ सकता है" "ठीक है" - "यह डिवाइस USB से चार्ज हो रहा है" - "अटैच किए गए डिवाइस को USB से पावर मिल रही है" - "फ़ाइल स्‍थानांतरण के लिए USB" - "फ़ोटो स्‍थानांतरण के लिए USB" - "MIDI के लिए USB" - "USB सहायक सामग्री से कनेक्‍ट कि‍या गया" + + + + + + + + + + + + + + "ज़्यादा विकल्पों के लिए टैप करें." + + "एनालॉग ऑडियो एक्सेसरी का पता चला" "अटैच किया गया डिवाइस इस फ़ोन से संगत नहीं है. अधिक जानने के लिए टैप करें." "USB डीबग कनेक्ट किया गया" @@ -1661,9 +1666,6 @@ "कार्यस्थल का %1$s" "दूसरा कार्य %1$s" "तीसरा कार्य %1$s" - "इस स्क्रीन को अनपिन करने के लिए, \'वापस जाएं\' और \'खास जानकारी\' के बटन को दबाकर रखें" - "स्‍क्रीन पिन की गई" - "स्‍क्रीन अनपिन की गई" "अनपिन करने से पहले पिन के लिए पूछें" "अनपिन करने से पहले लॉक खोलने के पैटर्न के लिए पूछें" "अनपिन करने से पहले पासवर्ड के लिए पूछें" @@ -1757,15 +1759,11 @@ "सभी भाषाएं" "सभी क्षेत्र" "सर्च करें" - - - - + "कार्य प्रोफ़ाइल चालू करें?" + "आपके काम से जुड़े ऐप्लिकेशन, सूचनाएं, डेटा और कार्य प्रोफ़ाइल से जुड़ी दूसरी सुविधाएं चालू हो जाएंगी" "चालू करें" - - - - + "यह ऐप्लिकेशन Android के पुराने वर्शन के लिए बनाया गया था, इसलिए हो सकता है कि यह सही से काम न करे. देखें कि अपडेट मौजूद हैं या नहीं, या फिर डेवलपर से संपर्क करें." + "देखें कि अपडेट मौजूद है या नहीं" "आपके पास नए संदेश हैं" "देखने के लिए मैसेज (एसएमएस) ऐप खोलें" "कुछ कार्य क्षमताएं सीमित हो सकती हैं" @@ -1832,17 +1830,15 @@ "फ़ोन से कॉल करने की इजाज़त नहीं है" "पॉपअप विंडो" "+ %1$d" - "इस शॉर्टकट वाला ऐप चलाने के लिए इसका नया वर्शन डाउनलोड करें" + + "शॉर्टकट बहाल नहीं किया जा सका क्योंकि इस ऐप में बैकअप लेने और उसे बहाल करने की सुविधा नहीं है" "ऐप सिग्नेचर अलग होने के कारण शॉर्टकट बहाल नहीं किया जा सका" "शॉर्टकट बहाल नहीं किया जा सका" "शॉर्टकट बंद है" - - - - - - + "अनइंस्‍टॉल करें" + "फिर भी खोलें" + "नुकसान पहुंचाने वाले ऐप का पता चला" "%1$s, %2$s के हिस्से (स्लाइस) दिखाना चाहता है" "बदलाव करें" diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 880728253d3a09b8507594e089fc56d32089809a..e0df831e949c0d85ea6bda48f7f11d28a1a8556b 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -417,10 +417,8 @@ "Consente all\'applicazione di accedere alle funzioni telefoniche del dispositivo. Questa autorizzazione consente all\'applicazione di determinare il numero di telefono e gli ID dei dispositivi, se una chiamata è attiva e il numero remoto connesso da una chiamata." "indirizzamento delle chiamate tramite il sistema" "Consente all\'app di indirizzare le proprie chiamate tramite il sistema al fine di migliorare l\'esperienza di chiamata." - - - - + "Continuazione di una chiamata da un\'altra app" + "Consente all\'app di continuare una chiamata che è stata iniziata in un\'altra app." "lettura dei numeri di telefono" "Consente all\'app di accedere ai numeri di telefono del dispositivo." "disattivazione stand-by del tablet" @@ -495,10 +493,14 @@ "Impossibile memorizzare l\'impronta digitale. Rimuovi un\'impronta esistente." "Timeout impronta digitale. Riprova." "Operazione associata all\'impronta digitale annullata." - "Operazione associata all\'impronta digitale annullata dall\'utente." + "Operazione di autenticazione dell\'impronta digitale annullata dall\'utente." "Troppi tentativi. Riprova più tardi." "Troppi tentativi. Sensore di impronte digitali disattivato." "Riprova." + + + + "Dito %d" @@ -997,12 +999,9 @@ "Apri" "Invia messaggio" "Aggiungi" - - - - - - + "Visualizza" + "Pianifica" + "Monitora" "Spazio di archiviazione in esaurimento" "Alcune funzioni di sistema potrebbero non funzionare" "Memoria insufficiente per il sistema. Assicurati di avere 250 MB di spazio libero e riavvia." @@ -1128,8 +1127,7 @@ Apri rete Wi-Fi disponibile "Stabilisci la connessione per aprire la rete Wi‑Fi" - - + "Collegati alla rete Wi-Fi dell\'operatore" "Connessione per aprire la rete Wi‑Fi" "Connessione alla rete Wi-Fi stabilita" "Impossibile connettersi alla rete Wi-Fi" @@ -1213,13 +1211,23 @@ "Nessuna autorizzazione richiesta" "potrebbe comportare dei costi" "OK" - "Dispositivo in carica tramite USB" - "Dispositivo collegato alimentato tramite USB" - "USB per il trasferimento di file" - "USB per il trasferimento di foto" - "USB per la modalità MIDI" - "Collegato a un accessorio USB" + + + + + + + + + + + + + + "Tocca per altre opzioni." + + "Accessorio audio analogico rilevato" "Il dispositivo collegato non è compatibile con questo telefono. Tocca per avere ulteriori informazioni." "Debug USB collegato" @@ -1658,9 +1666,6 @@ "%1$s lavoro" "%1$s di lavoro (2°)" "%1$s di lavoro (3°)" - "Per sganciare la schermata, tieni premuti i pulsanti Indietro e Panoramica" - "Schermata fissata" - "Schermata sganciata" "Richiedi il PIN per lo sblocco" "Richiedi sequenza di sblocco prima di sbloccare" "Richiedi password prima di sbloccare" @@ -1757,10 +1762,8 @@ "Attivare il profilo di lavoro?" "Le tue app di lavoro, le notifiche, i dati e altri elementi del profilo di lavoro saranno attivati." "Attiva" - - - - + "Questa app è stata realizzata per una versione precedente di Android e potrebbe non funzionare correttamente. Prova a verificare la disponibilità di aggiornamenti o contatta lo sviluppatore." + "Verifica la presenza di aggiornamenti" "Hai nuovi messaggi" "Apri l\'app SMS per la visualizzazione" "Funzioni potenzial. limitate" @@ -1827,17 +1830,15 @@ "Telefono non consentito per la voce" "Finestra popup" "+ %1$d" - "Per questa scorciatoia è necessaria l\'app più recente" + + "Impossibile ripristinare la scorciatoia perché l\'app non supporta il backup e il ripristino" "Impossibile ripristinare la scorciatoia perché la firma dell\'app non corrisponde" "Impossibile ripristinare la scorciatoia" "La scorciatoia è disattivata" - - - - - - + "DISINSTALLA" + "APRI COMUNQUE" + "App dannosa rilevata" "L\'app %1$s vuole mostrare porzioni dell\'app %2$s" "Modifica" diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index ee690b549421d9b9642fcb28a14138b865c09154..14c295f4c59963844da8ea370f7b71f0892e2634 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "ಸುರಕ್ಷಿತ ಮೋಡ್" "Android ಸಿಸ್ಟಂ" - - - - + "ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್‌ಗೆ ಬದಲಾಯಿಸಿ" + "ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ಗೆ ಬದಲಿಸಿ" "ಸಂಪರ್ಕಗಳು" "ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು" "ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <b>%1$s</b> ಗೆ ಅನುಮತಿಸಿ" @@ -419,10 +417,8 @@ "ಸಾಧನದ ಫೋನ್ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಫೋನ್ ಸಂಖ್ಯೆ ಮತ್ತು ಸಾಧನದ ID ಗಳನ್ನು ನಿರ್ಧರಿಸಲು, ಕರೆಯು ಸಕ್ರಿಯವಾಗಿದೆಯೇ ಮತ್ತು ಕರೆಯ ಮೂಲಕ ರಿಮೋಟ್ ಸಂಖ್ಯೆಯು ಸಂಪರ್ಕಗೊಂಡಿವೆಯೇ ಎಂಬುದನ್ನೂ ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸುತ್ತದೆ." "ಕರೆಗಳನ್ನು ಸಿಸ್ಟಂ ಮೂಲಕ ರವಾನಿಸಿ" "ಕರೆಯ ಅನುಭವವನ್ನು ಸುಧಾರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ನ ಕರೆಗಳನ್ನು ಸಿಸ್ಟಂ ಮೂಲಕ ರವಾನಿಸಲು ಅನುಮತಿಸುತ್ತದೆ." - - - - + "ಮತ್ತೊಂದು ಅಪ್ಲಿಕೇಶನ್‌ ಮೂಲಕ ಕರೆಯನ್ನು ಮುಂದುವರಿಸಿ" + "ಮತ್ತೊಂದು ಅಪ್ಲಿಕೇಶನ್‌ನಲ್ಲಿ ಪ್ರಾರಂಭವಾದ ಕರೆಯನ್ನು ಮುಂದುವರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡಿ." "ಫೋನ್‌ ಸಂಖ್ಯೆಗಳನ್ನು ಓದಿ" "ಸಾಧನದ ಫೋನ್ ಸಂಖ್ಯೆಗಳಿಗೆ ಪ್ರವೇಶ ಪಡೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ." "ಟ್ಯಾಬ್ಲೆಟ್ ನಿದ್ರಾವಸ್ಥೆಯನ್ನು ತಡೆಯಿರಿ" @@ -497,11 +493,14 @@ "ಬೆರಳಚ್ಚು ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಬೆರಳಚ್ಚು ತೆಗೆದುಹಾಕಿ." "ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ." "ಬೆರಳಚ್ಚು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ." - - + "ಬಳಕೆದಾರರಿಂದ ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಲಾಗಿದೆ." "ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ." "ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಸೆನ್ಸಾರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ." "ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ." + + + + "ಫಿಂಗರ್ %d" @@ -1000,12 +999,9 @@ "ತೆರೆ" "ಸಂದೇಶ" "ಸೇರಿಸಿ" - - - - - - + "ವೀಕ್ಷಿಸಿ" + "ಅವಧಿ" + "ಟ್ರ್ಯಾಕ್" "ಸಂಗ್ರಹಣೆ ಸ್ಥಳವು ತುಂಬಿದೆ" "ಕೆಲವು ಸಿಸ್ಟಂ ಕಾರ್ಯವಿಧಾನಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸದೇ ಇರಬಹುದು" "ಸಿಸ್ಟಂನಲ್ಲಿ ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆಯಿಲ್ಲ. ನೀವು 250MB ನಷ್ಟು ಖಾಲಿ ಸ್ಥಳವನ್ನು ಹೊಂದಿರುವಿರಾ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ ಹಾಗೂ ಮರುಪ್ರಾರಂಭಿಸಿ." @@ -1131,8 +1127,7 @@ ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ "ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ" - - + "ವಾಹಕ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ" "ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗುತ್ತಿದೆ" "ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ" "ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ" @@ -1217,13 +1212,23 @@ "ಯಾವುದೇ ಅನುಮತಿಗಳ ಅಗತ್ಯವಿಲ್ಲ" "ಇದು ನಿಮ್ಮ ಹಣವನ್ನು ವ್ಯಯಿಸಬಹುದು" "ಸರಿ" - "ಈ ಸಾಧನಕ್ಕೆ USB ಅನ್ನು ಚಾರ್ಜ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ" - "USB, ಲಗತ್ತಿಸಲಾದ ಸಾಧನಕ್ಕೆ ಪವರ್‌ ಪೂರೈಸುತ್ತಿದೆ" - "ಫೈಲ್‌ ವರ್ಗಾವಣೆಗೆ USB" - "ಫೋಟೋ ವರ್ಗಾವಣೆಗೆ USB" - "MIDI ಗೆ USB" - "USB ಪರಿಕರಕ್ಕೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ" + + + + + + + + + + + + + + "ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ." + + "ಅನ್‌ಲಾಗ್ ಆಡಿಯೋ ಪರಿಕರ ಪತ್ತೆಯಾಗಿದೆ" "ಲಗತ್ತಿಸಲಾದ ಸಾಧನವು ಈ ಫೋನಿನೊಂದಿಗೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ." "USB ಡೀಬಗಿಂಗ್‌‌ ಸಂಪರ್ಕ" @@ -1662,9 +1667,6 @@ "ಕೆಲಸ %1$s" "2 ನೇ ಕೆಲಸದ %1$s" "3 ನೇ ಕೆಲಸದ %1$s" - "ಈ ಪರದೆಯನ್ನು ಅನ್‌ಪಿನ್ ಮಾಡಲು, ಹಿಂದಕ್ಕೆ ಮತ್ತು ಸಮಗ್ರ ನೋಟ ಬಟನ್‌ಗಳನ್ನು ಸ್ಪರ್ಶಿಸಿ ಒತ್ತಿಹಿಡಿಯಿರಿ" - "ಸ್ಕ್ರೀನ್‌ ಪಿನ್‌ ಮಾಡಲಾಗಿದೆ" - "ಸ್ಕ್ರೀನ್‌ ಅನ್‌ಪಿನ್‌ ಮಾಡಲಾಗಿದೆ" "ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು" "ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ" "ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು" @@ -1758,15 +1760,11 @@ "ಎಲ್ಲಾ ಭಾಷೆಗಳು" "ಎಲ್ಲಾ ಪ್ರದೇಶಗಳು" "ಹುಡುಕಿ" - - - - + "ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ಆನ್ ಮಾಡುವುದೇ?" + "ನಿಮ್ಮ ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಅಧಿಸೂಚನೆಗಳು, ಡೇಟಾ ಮತ್ತು ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನ ಇತರ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡಲಾಗುತ್ತದೆ" "ಆನ್‌ ಮಾಡಿ" - - - - + "ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು Android ನ ಹಳೆಯ ಆವೃತ್ತಿಗೆ ರಚಿಸಲಾಗಿದೆ ಮತ್ತು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿರಬಹುದು. ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಡೆವಲಪರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸಿ." + "ಅಪ್‌ಡೇಟ್‌ಗಾಗಿ ಪರಿಶೀಲಿಸಿ" "ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ" "ವೀಕ್ಷಿಸಲು SMS ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ" "ಕೆಲವು ಕಾರ್ಯನಿರ್ವಹಣೆಗಳು ಸೀಮಿತವಾಗಿರಬಹುದು" @@ -1833,17 +1831,15 @@ "ಧ್ವನಿಗಾಗಿ ಫೋನ್ ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ" "ಪಾಪ್‌ಅಪ್ ವಿಂಡೋ" "+ %1$d" - "ಈ ಶಾರ್ಟ್‌ಕಟ್‌ಗೆ ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ ಅಗತ್ಯವಿದೆ" + + "ಅಪ್ಲಿಕೇಶನ್‌ ಬ್ಯಾಕಪ್ ಮತ್ತು ಪುನಃಸ್ಥಾಪನೆಯನ್ನು ಬೆಂಬಲಿಸದಿರುವುದರಿಂದ ಶಾರ್ಟ್‌ಕಟ್‌ ಅನ್ನು ಪುನಃಸ್ಥಾಪನೆ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ" "ಅಪ್ಲಿಕೇಶನ್‌ ಸಹಿ ಹೊಂದಿಕೆಯಾಗದ ಕಾರಣದಿಂದ ಶಾರ್ಟ್‌ಕಟ್‌ ಅನ್ನು ಪುನಃಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ" "ಶಾರ್ಟ್‌ಕಟ್‌ ಅನ್ನು ಪುನಃ ಸ್ಥಾಪನೆ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ" "ಶಾರ್ಟ್‌ಕಟ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" - - - - - - + "ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" + "ಹೇಗಿದ್ದರೂ ತೆರೆಯಿರಿ" + "ಅಪಾಯಕಾರಿ ಅಪ್ಲಿಕೇಶನ್ ಕಂಡುಬಂದಿದೆ" "%2$s ಸ್ಲೈಸ್‌ಗಳನ್ನು %1$s ತೋರಿಸಲು ಬಯಸಿದೆ" "ಎಡಿಟ್" diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 088d44f931bc35dff6e723c7c72fa5b2169061cf..cc568d388960a34dcd270a22f8de5a1aceb1d569 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Safe mode" "ລະບົບ Android" - - - - + "ສະຫຼັບໄປໂປຣໄຟລ໌ສ່ວນຕົວ" + "ສະຫຼັບໄປໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ" "ລາຍຊື່" "ເຂົ້າ​ຫາ​ລາຍ​ຊື່​ຂອງ​ທ່ານ" "ອະນຸຍາດ <b>%1$s</b> ໃຫ້ເຂົ້າເຖິງລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ" @@ -419,10 +417,8 @@ "ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງຄວາມສາມາດການໂທລະສັບຂອງອຸປະກອນ. ການກຳນົດສິດນີ້ເຮັດໃຫ້ແອັບຯສາມາດກວດສອບເບີໂທລະສັບ ແລະ ID ຂອງອຸປະກອນ, ບໍ່ວ່າການໂທຈະຍັງດຳເນີນຢູ່ ແລະເບີປາຍທາງເຊື່ອມຕໍ່ຢູ່ຫຼືບໍ່ກໍຕາມ." "route calls through the system" "Allows the app to route its calls through the system in order to improve the calling experience." - - - - + "ສືບຕໍ່ການໂທຈາກແອັບອື່ນ" + "ອະນຸຍາດໃຫ້ແອັບສືບຕໍ່ການໂທເຊິ່ງອາດຖືກເລີ່ມຕົ້ນໃນແອັບອື່ນ." "ອ່ານເບີໂທລະສັບ" "ອະນຸຍາດໃຫ້ແອັບເຂົ້າເຖິງເບີໂທລະສັບຂອງອຸປະກອນໄດ້." "ຂັດຂວາງບໍ່ໃຫ້ປິດໜ້າຈໍແທັບເລັດ" @@ -497,11 +493,14 @@ "ບໍ່​ສາ​ມາດ​ເກັບ​ຮັກ​ສາ​ລາຍ​ນີ້ວ​ມື​ໄວ້​ໄດ້. ກະ​ລຸ​ນາ​ເອົາ​ລາຍ​ນີ້ວ​ມື​ທີ່​ມີ​ຢູ່​ອອກ​ໄປ." "ເວ​ລາ​ລາຍ​ນີ້ວ​ມື​ບໍ່​ເຂົ້າ​ເຖິງ​ໄດ້. ລອງ​ໃໝ່​ອີກ." "ຍົກ​ເລີກ​ການ​ດຳ​ເນີນ​ການ​ລາຍ​ນີ້ວ​ມື​ແລ້ວ." - - + "ຜູ້ໃຊ້ໄດ້ຍົກເລີກຄຳສັ່ງລາຍນິ້ວມືແລ້ວ." "ມີ​ຄວາມ​ພະ​ຍາ​ຍາມ​ຫຼາຍ​ຄັ້ງ​ເກີນ​ໄປ. ລອງ​ໃໝ່​ພາຍ​ຫຼັງ." "ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ລະບົບປິດການເຮັດວຽກຂອງເຊັນເຊີລາຍນິ້ວມືແລ້ວ." "ລອງໃໝ່ອີກຄັ້ງ." + + + + "ນີ້ວ​ມື %d" @@ -1000,12 +999,9 @@ "ເປີດ" "ຂໍ້ຄວາມ" "ເພີ່ມ" - - - - - - + "ເບິ່ງ" + "ຕັ້ງເວລາ" + "ແທຣັກ" "ພື້ນທີ່ຈັດເກັບຂໍ້ມູນກຳລັງຈະເຕັມ" "ການເຮັດວຽກບາງຢ່າງຂອງລະບົບບາງອາດຈະໃຊ້ບໍ່ໄດ້" "​ບໍ່​ມີ​ບ່ອນ​ເກັບ​ຂໍ້​ມູນ​ພຽງ​ພໍ​ສຳ​ລັບ​ລະ​ບົບ. ກວດ​ສອບ​ໃຫ້​ແນ່​ໃຈ​ວ່າ​ທ່ານ​ມີ​ພື້ນ​ທີ່​ຫວ່າງ​ຢ່າງ​ໜ້ອຍ 250MB ​ແລ້ວລອງ​ໃໝ່." @@ -1131,8 +1127,7 @@ ເປີດເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້ "ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແບບເປີດ" - - + "ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ຜູ້ໃຫ້ບໍລິການ" "ກຳລັງເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi" "ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແລ້ວ" "ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ໄດ້" @@ -1216,13 +1211,23 @@ "ບໍ່ຕ້ອງການການອະນຸຍາດ" "ລາຍການນີ້ອາດມີການເກັບເງິນ" "ຕົກລົງ" - "ກຳລັງສາກໄຟ USB ອຸປະກອນນີ້" - "USB ກຳລັງສະໜອງໄຟໃຫ້ກັບອຸປະກອນທີ່ເຊື່ອມຕໍ່ກັນ" - "USB ສຳ​ລັບ​ການ​ໂອ​ນ​ໄຟ​ລ໌" - "USB ສຳ​ລັບ​ການ​ໂອນ​ໄຟ​ລ໌" - "USB ສຳ​ລັບ MIDI" - "ເຊື່ອມຕໍ່ກັບອຸປະກອນເສີມ USB ແລ້ວ" + + + + + + + + + + + + + + "ແຕະເພື່ອເບິ່ງຕົວເລືອກເພີ່ມເຕີມ." + + "ກວດພົບອຸປະກອນເສີມສຽງ" "ອຸປະກອນທີ່ເຊື່ອມຕໍ່ນັ້ນບໍ່ສາມາດໃຊ້ຮ່ວມກັບໂທລະສັບນີ້ໄດ້. ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ." "ເຊື່ອມຕໍ່ການດີບັກຜ່ານ USB ແລ້ວ" @@ -1661,9 +1666,6 @@ "​ບ່ອນ​ເຮັດ​ວຽກ %1$s" "ບ່ອນເຮັດວຽກທີ 2 %1$s" "ບ່ອນເຮັດວຽກທີ 3 %1$s" - "ເພື່ອຍົກເລີກການປັກໝຸດໜ້າຈໍນີ້, ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້" - "​ປັກ​ໝຸດ​ໜ້າ​ຈໍ​ແລ້ວ" - "ຍົກ​ເລີກ​ການ​ປັກ​ໝຸນ​​ຫນ້າ​ຈໍ​ແລ້ວ" "​ຖາມ​ຫາ PIN ກ່ອນ​ຍົກ​ເລີກ​ການປັກ​ໝຸດ" "​ຖາມ​ຫາ​ຮູບ​ແບບ​ປົດ​ລັອກ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ" "​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ" @@ -1757,15 +1759,11 @@ "ທຸກພາ​ສາ​" "ທຸກຂົງເຂດ" "ຄົ້ນຫາ" - - - - + "ເປີດໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກບໍ?" + "ແອັບວຽກຂອງທ່ານ, ການແຈ້ງເຕືອນ, ຂໍ້ມູນ ແລະ ຄຸນສົມບັດໂປຣໄຟລ໌ວຽກຈະຖືກເປີດໃຊ້" "ເປີດ​" - - - - + "ແອັບນີ້ຖືກສ້າງຂຶ້ນສຳລັບ Android ເວີຊັນທີ່ເກົ່າກວ່າ ແລະ ອາດເຮັດວຽກໄດ້ບໍ່ປົກກະຕິ. ໃຫ້ລອງກວດສອບເບິ່ງອັບເດດ ຫຼື ຕິດຕໍ່ຜູ້ພັດທະນາ." + "ກວດເບິ່ງອັບເດດ" "ທ່ານມີຂໍ້ຄວາມໃໝ່" "ເປີດແອັບ SMS ເພື່ອເບິ່ງ" "ບາງຄວາມສາມາດນຳໃຊ້ອາດຈະຖືກຈຳກັດ" @@ -1832,17 +1830,15 @@ "ບໍ່ອະນຸຍາດໃຫ້ໃຊ້ໂທລະສັບສຳລັບການໂທສຽງ" "ໜ້າຈໍປັອບອັບ" "+ %1$d" - "ທາງລັດນີ້ຕ້ອງໃຊ້ແອັບເວີຊັນຫຼ້າສຸດ" + + "ບໍ່ສາມາດກູ້ທາງລັດຂຶ້ນມາໄດ້ເນື່ອງຈາກແອັບບໍ່ຮອງຮັບການສຳຮອງ ແລະ ກູ້ຂໍ້ມູນ" "ບໍ່ສາມາດກູ້ທາງລັດຄືນມາໄດ້ເນື່ອງຈາກລາຍເຊັນແອັບບໍ່ກົງກັນ" "ບໍ່ສາມາດກູ້ທາງລັດຄືນມາໄດ້" "ທາງລັດຖືກປິດການນຳໃຊ້" - - - - - - + "ຖອນການຕິດຕັ້ງ" + "ຢືນຢັນການເປີດ" + "ກວດສອບແອັບທີ່ເປັນອັນຕະລາຍ" "%1$s ຕ້ອງການສະແດງ %2$s ສະໄລ້" "ແກ້ໄຂ" diff --git a/core/res/res/values-mcc405/config.xml b/core/res/res/values-mcc405/config.xml index 6b77e9c1663a5c2483220bcee2e00074f0ea7e18..cc2b9ea1195233e70541631b27189473dfe24aa0 100644 --- a/core/res/res/values-mcc405/config.xml +++ b/core/res/res/values-mcc405/config.xml @@ -20,4 +20,6 @@ true + + true diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 746ac524c25d24f5130ee57ea08c47b179655039..7c6f7f017c73b6e9febcfb5e2dd3b4730512a242 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -417,10 +417,8 @@ "Овозможува апликацијата да пристапи кон карактеристиките на телефонот на уредот. Оваа дозвола овозможува апликацијата да ги утврди телефонскиот број и ID на уредот, дали повикот е активен и далечинскиот број поврзан со повикот." "пренасочи повици преку системот" "Дозволете ѝ на апликацијата да ги пренасочи повиците преку системот за да го подобри искуството при јавувањето." - - - - + "продолжување повик од друга апликација" + "Овозможува апликацијата да продолжи повик започнат на друга апликација." "да чита телефонски броеви" "Ѝ дозволува на апликацијата да пристапи до телефонските броеви на уредот." "спречи режим на штедење кај таблет" @@ -499,6 +497,10 @@ "Премногу обиди. Обидете се повторно подоцна." "Премногу обиди. Сензорот за отпечатоци е оневозможен." "Обидете се повторно." + + + + "Прст %d" @@ -997,12 +999,9 @@ "Отвори" "Порака" "Додај" - - - - - - + "Прикажи" + "Распоред" + "Песна" "Капацитетот е речиси полн" "Некои системски функции може да не работат" "Нема доволно меморија во системот. Проверете дали има слободен простор од 250 МБ и рестартирајте." @@ -1128,8 +1127,7 @@ Отворени Wi-Fi мрежи се достапни "Поврзете се на отворена Wi‑Fi-мрежа" - - + "Поврзете се на Wi‑Fi-мрежа на оператор" "Поврзување на отворена Wi‑Fi-мрежа" "Се поврзавте на Wi‑Fi-мрежа" "Не можеше да се поврзе на Wi‑Fi-мрежа" @@ -1214,13 +1212,23 @@ "Не се потребни дозволи" "ова може да ве чини пари" "Во ред" - "Уредов се полни преку USB" - "Прикачениот уред се напојува преку USB" - "USB за пренос на датотеки" - "USB за пренос на фотографии" - "USB за МИДИ" - "Поврзан со USB додаток" + + + + + + + + + + + + + + "Допрете за повеќе опции." + + "Откриен е аналоген аудиододаток" "Приложениот уред не е компатибилен со телефонов. Допрете за да дознаете повеќе." "Поврзано е отстранување грешки преку USB" @@ -1661,9 +1669,6 @@ "Работа %1$s" "Втора деловна %1$s" "Трета деловна %1$s" - "За откачување на екранов, допрете и задржете ги копчињата „Назад“ и „Краток преглед“." - "Екранот е закачен" - "Екранот е откачен" "Прашај за PIN пред откачување" "Побарај шема за откл. пред откачување" "Прашај за лозинка пред откачување" @@ -1760,10 +1765,8 @@ "Да се вклучи работниот профил?" "Вашите работни апликации, известувања, податоци и други функции на работниот профил ќе бидат вклучени" "Вклучи" - - - - + "Апликацијава е создадена за постара верзија на Android и може да не функционира правилно. Проверете за ажурирања или контактирајте со програмерот." + "Проверка за ажурирање" "Имате нови пораки" "Отворете ја апликацијата за SMS за приказ" "Некои функции се ограничени" @@ -1830,17 +1833,15 @@ "Не е дозволен телефон за глас" "Појавен прозорец" "+ %1$d" - "За кратенкава е потребна најновата апликација" + + "Не можеше да се врати кратенката бидејќи апликацијата не поддржува бекап и враќање" "Не можеше да се врати кратенката бидејќи потписот на апликацијата не се совпаѓа" "Не можеше да се врати кратенката" "Кратенката е оневозможена" - - - - - - + "ДЕИНСТАЛИРАЈ" + "СЕПАК ОТВОРИ" + "Откриена е штетна апликација" "%1$s сака да прикажува делови од %2$s" "Измени" diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 022e07776d1e0e9c572b23a1e440a0de0d7619ce..cfde3c6df8db2ffd6a11f11d211c4c5d70552b3e 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "സുരക്ഷിത മോഡ്" "Android സിസ്റ്റം" - - - - + "വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക" + "ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക" "കോൺടാക്റ്റുകൾ" "നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്‌സസ്സ് ചെയ്യുക" "നിങ്ങളുടെ കോണ്‍ടാക്റ്റുകള്‍ ആക്‌സസ് ചെയ്യാൻ <b>%1$s</b> ആപ്പിനെ അനുവദിക്കുക" @@ -419,10 +417,8 @@ "ഉപകരണത്തിന്റെ ഫോൺ സവിശേഷതകൾ ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഈ അനുമതി ഫോൺ നമ്പർ, ഉപകരണ ഐഡികൾ, ഒരു കോൾ സജീവമാണോയെന്നത്, ഒരു കോൾ കണക്റ്റുചെയ്‌ത വിദൂര നമ്പർ എന്നിവ നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "കോളുകൾ സിസ്റ്റത്തിലൂടെ വിടുക" "കോളിംഗ് അനുഭവം ‌മെച്ചപ്പെടുത്തുന്നതിനായി തങ്ങളുടെ ‌കോളുകൾ സിസ്റ്റത്തിലേയ്ക്ക് വഴിതിരിച്ചുവിടാൻ ആപ്പുകളെ അനുവദിക്കുന്നു." - - - - + "മറ്റൊരു ആപ്പിൽ നിന്നുള്ള കോൾ തുടരുക" + "മറ്റൊരു ആപ്പിൽ ആരംഭിച്ച കോൾ തുടരാൻ ആപ്പിനെ അനുവദിക്കുന്നു." "ഫോൺ നമ്പറുകൾ റീഡുചെയ്യൽ" "ഉപകരണത്തിന്റെ ഫോൺ നമ്പറുകൾ ആക്‌സസ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു." "സുഷുപ്‌തിയിലാകുന്നതിൽ നിന്ന് ടാബ്‌ലെറ്റിനെ തടയുക" @@ -497,11 +493,14 @@ "വിരലടയാളം സംഭരിക്കാനാവില്ല. നിലവിലുള്ള വിരലടയാളം നീക്കംചെയ്യുക." "വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക." "ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി." - - + "ഉപയോക്താവ് റദ്ദാക്കിയ ഫിംഗർപ്രിന്‍റ് പ്രവർത്തനം." "നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക." "നിരവധി തവണ ശ്രമിച്ചതിനാൽ, വിരലടയാള സെൻസർ പ്രവർത്തനരഹിതമായി." "വീണ്ടും ശ്രമിക്കൂ." + + + + "കൈവിരൽ %d" @@ -1000,12 +999,9 @@ "തുറക്കുക" "സന്ദേശം" "ചേർക്കുക" - - - - - - + "കാണുക" + "ഷെഡ്യൂള്‍‌" + "ട്രാക്ക്" "സംഭരണയിടം കഴിഞ്ഞു" "ചില സിസ്റ്റം പ്രവർത്തനങ്ങൾ പ്രവർത്തിക്കണമെന്നില്ല." "സിസ്‌റ്റത്തിനായി മതിയായ സംഭരണമില്ല. 250MB സൗജന്യ സംഭരണമുണ്ടെന്ന് ഉറപ്പുവരുത്തി പുനരാരംഭിക്കുക." @@ -1131,8 +1127,7 @@ ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്ക് തുറക്കുക "ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക" - - + "കാരിയർ വൈഫൈ നെറ്റ്‍വര്‍ക്കിലേക്ക് കണക്റ്റ് ചെയ്യുക" "ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്റ്റുചെയ്യുന്നു" "വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്റ്റു‌ചെയ്‌‌തു" "വൈ-ഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്‌റ്റുചെയ്യാനായില്ല" @@ -1217,13 +1212,23 @@ "അനുമതികളൊന്നും ആവശ്യമില്ല" "ഇത് നിങ്ങൾക്ക് പണച്ചെലവിനിടയാക്കാം" "ശരി" - "USB ഈ ഉപകരണം ചാർജജ് ചെയ്യുന്നു" - "ഘടിപ്പിച്ചിട്ടുള്ള ഉപകരണത്തിന് USB വൈദ്യുതി നൽകുന്നു" - "ഫയൽ കൈമാറ്റത്തിനുള്ള USB" - "ഫോട്ടോ കൈമാറ്റത്തിനായുള്ള USB" - "MIDI-യ്‌ക്കായുള്ള USB" - "ഒരു USB ആക്‌സസ്സറി കണക്റ്റുചെയ്‌തു" + + + + + + + + + + + + + + "കൂടുതൽ ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക." + + "അനലോഗ് ഓഡിയോ ആക്‌സസറി കണ്ടെത്തി" "അറ്റാച്ചുചെയ്‌ത ഉപകരണം ഈ ഫോണിന് അനുയോജ്യമല്ല. കൂടുതലറിയാൻ ടാപ്പുചെയ്യുക." "USB ഡീബഗ്ഗിംഗ് കണക്റ്റ് ചെയ്തു" @@ -1662,9 +1667,6 @@ "ഔദ്യോഗികം %1$s" "രണ്ടാമത്തെ ഔദ്യോഗിക %1$s" "മൂന്നാമത്തെ ഔദ്യോഗിക %1$s" - "ഈ സ്‌ക്രീൻ അൺപിൻ ചെയ്യാൻ, ബാക്ക്, ചുരുക്കവിവരണം എന്നീ ബട്ടണുകൾ സ്‌പർശിച്ച് പിടിക്കുക" - "സ്ക്രീൻ പിൻ ചെയ്തു" - "സ്ക്രീൻ അൺപിൻ ചെയ്തു" "ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ" "അൺപിന്നിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടൂ" "അൺപിന്നിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടൂ" @@ -1758,15 +1760,11 @@ "എല്ലാ ഭാഷകളും" "എല്ലാ പ്രദേശങ്ങളും" "തിരയുക" - - - - + "ഔദ്യോഗിക പ്രൊഫൈൽ ഓണാക്കണോ?" + "നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകൾ, അറിയിപ്പുകൾ, ഡാറ്റ, മറ്റ് ഔദ്യോഗിക പ്രൊഫൈൽ ഫീച്ചറുകൾ എന്നിവ ഓണാക്കും" "ഓണാക്കുക" - - - - + "ഈ ആപ്പ് Android-ന്റെ പഴയ പതിപ്പിനായി നിർമ്മിച്ചിരിക്കുന്നതിനാൽ ശരിയായി പ്രവർത്തിച്ചേക്കില്ല. അപ്‌ഡേറ്റിനായി പരിശോധിക്കുക, അല്ലെങ്കിൽ ഡെവലപ്പറുമായി ബന്ധപ്പെടുക." + "അപ്‌ഡേറ്റിനായി പരിശോധിക്കുക" "നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്" "കാണുന്നതിന് SMS ആപ്പ് തുറക്കുക" "ചില പ്രവർത്തനക്ഷമതകൾ പരിമിതപ്പെടാം" @@ -1833,17 +1831,15 @@ "ഫോൺ വോയ്‌സിന് അനുവദനീയമല്ല" "പോപ്പ് അപ്പ് വിൻഡോ" "+ %1$d" - "ഈ കുറുക്കുവഴിക്ക് ഏറ്റവും പുതിയ ആപ്പ് ആവശ്യമാണ്" + + "ആപ്പ് \'ബാക്കപ്പും പുനഃസ്ഥാപിക്കലും\' പിന്തുണയ്ക്കാത്തതിനാൽ കുറുക്കുവഴി പുനഃസ്ഥാപിക്കാനായില്ല" "ആപ്പ് സിഗ്നേച്ചർ പൊരുത്തപ്പെടാത്തതിനാൽ കുറുക്കുവഴി പുനഃസ്ഥാപിക്കാനായില്ല" "കുറുക്കുവഴി പുനഃസ്ഥാപിക്കാനായില്ല" "കുറുക്കുവഴി പ്രവർത്തനരഹിതമാണ്" - - - - - - + "അൺഇൻസ്‌റ്റാള്‍ ചെയ്യുക" + "എന്തായാലും തുറക്കുക" + "ദോഷകരമായ ആപ്പ് കണ്ടെത്തി" "%2$s സ്ലൈസുകൾ കാണിക്കാൻ %1$s താൽപ്പര്യപ്പെടുന്നു" "എഡിറ്റ് ചെയ്യുക" diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 0da8708d9311ff6e9f4240d1de32daf5de8ac7f9..d1a5455b6775397fed5554b8a3b00eaca893a9a5 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "सुरक्षित मोड" "Android सिस्‍टम" - - - - + "वैयक्तिक प्रोफाइलवर स्विच करा" + "कार्य प्रोफाइलवर स्विच करा" "संपर्क" "आपल्या संपर्कांवर प्रवेश" "<b>%1$s</b> ला तुमचे संपर्क अॅक्सेस करू द्या" @@ -419,10 +417,8 @@ "डिव्हाइस च्या फोन वैशिष्ट्यांवर अॅक्सेस करण्यास अॅपला अनुमती देते. ही परवानगी कॉल अॅक्टिव्हेट असला किंवा नसला तरीही, फोन नंबर आणि डिव्हाइस आयडी आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅपला अनुमती देते." "प्रणालीच्या माध्यमातून कॉल रूट करा" "कॉल करण्याचा अनुभव सुधारण्यासाठी अॅपला त्याचे कॉल प्रणालीच्या माध्यमातून रूट करू देते." - - - - + "दुसऱ्या अॅपवरून कॉल करणे सुरू ठेवा" + "दुसऱ्या अॅपमध्ये सुरू झालेल्या कॉलला पुढे सुरू ठेवण्याची अॅपला अनुमती देते." "फोन नंबर वाचा" "अॅपला डिव्हाइसच्या फोन नंबरमध्ये प्रवेश करण्याची अनुमती देते." "टॅबलेट निष्क्रिय होण्यापासून प्रतिबंधित करा" @@ -497,11 +493,14 @@ "फिंगरप्रिंट स्टोअर केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा." "फिंगरप्रिंट टाइमआउट झाले. पुन्हा प्रयत्न करा." "फिंगरप्रिंट ऑपरेशन रद्द झाले." - - + "वापरकर्त्याने फिंगरप्रिंट ऑपरेशन रद्द केले." "खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा." "खूप प्रयत्न करून झाले. फिंगरप्रिंट सेंसर बंद आहे." "पुन्हा प्रयत्न करा." + + + + "%d बोट" @@ -1000,12 +999,9 @@ "उघडा" "संदेश" "जोडा" - - - - - - + "पहा" + "शेड्यूल" + "ट्रॅक" "संचयन स्थान संपत आहे" "काही सिस्टम कार्ये कार्य करू शकत नाहीत" "सिस्टीमसाठी पुरेसे संचयन नाही. आपल्याकडे 250MB मोकळे स्थान असल्याचे सुनिश्चित करा आणि रीस्टार्ट करा." @@ -1131,8 +1127,7 @@ खुले वाय-फाय नेटवर्क उपलब्ध "खुल्या वाय-फाय नेटवर्कशी कनेक्ट करा" - - + "वाहक वाय-फाय नेटवर्कशी कनेक्ट करा" "खुल्या वाय-फाय नेटवर्कशी कनेक्ट करत आहे" "वाय-फाय नेटवर्कशी कनेक्ट केले" "वाय-फाय नेटवर्कशी कनेक्ट करू शकत नाही" @@ -1217,13 +1212,23 @@ "परवानग्या आवश्यक नाहीत" "यासाठी आपले पैसे खर्च होऊ शकतात" "ठीक" - "USB हे डिव्हाइस चार्ज करत आहे" - "USB संलग्न केलेल्या डिव्हाइसला पॉवरचा पुरवठा करत आहे" - "स्थानांतरणासाठी USB" - "फोटो स्थानांतरणासाठी USB" - "MIDI साठी USB" - "USB उपसाधनावर कनेक्ट केले" + + + + + + + + + + + + + + "अधिक पर्यायांसाठी टॅप करा." + + "अॅनालॉग ऑडिओ अॅक्‍सेसरी आढळली" "या फोनसह संलग्‍न केलेले डीव्‍हाइस सुसंगत नाही. अधिक जाणून घेण्‍यासाठी टॅप करा." "USB डीबग करणे कनेक्‍ट केले" @@ -1662,9 +1667,6 @@ "कार्य %1$s" "2 रे कार्य %1$s" "3 रे कार्य %1$s" - "हा स्क्रीन अनपिन करण्यासाठी, मागे आणि अवलोकन बटणांना स्पर्श करून धरून ठेवा" - "स्क्रीन पिन केली" - "स्क्रीन अनपिन केली" "अनपिन करण्‍यापूर्वी पिन साठी विचारा" "अनपिन करण्‍यापूर्वी अनलॉक नमुन्यासाठी विचारा" "अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा" @@ -1758,15 +1760,11 @@ "सर्व भाषा" "सर्व प्रदेश" "शोध" - - - - + "कार्य प्रोफाइल चालू ठेवायची?" + "तुमची कार्य अ‍ॅप्स, सूचना, डेटा आणि अन्य कार्य प्रोफाइल वैशिष्ट्ये चालू केली जातील" "चालू करा" - - - - + "हे अॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पाहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा." + "अपडेट आहे का ते तपासा" "आपल्याकडे नवीन संदेश आहेत" "पाहण्‍यासाठी SMS अॅप उघडा" "काही कार्यक्षमता मर्यादित असू शकतात" @@ -1833,17 +1831,15 @@ "व्‍हॉइसची फोनला अनुमती नाही" "पॉपअप विंडो" "+ %1$d" - "या शॉर्टकटला नवीनतम अॅपची आवश्यकता आहे" + + "अॅप बॅकअप आणि रिस्‍टोअर करण्यास सपोर्ट देत नसल्यामुळे शॉर्टकट रिस्‍टोअर करू शकलो नाही" "अॅप स्वाक्षरी न जुळल्यामुळे शॉर्टकट रिस्‍टोअर करू शकलो नाही" "शॉर्टकट रिस्‍टोअर करू शकलो नाही" "शॉर्टकट बंद केलेला आहे" - - - - - - + "अनइंस्टॉल करा" + "तरीही उघडा" + "हानिकारक अॅप आढळला" "%1$s ला %2$s चे तुकडे दाखवायचे आहेत" "संपादित करा" diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index afccd7975c0b79b4dbc0619ad6cf50352bc6d985..4c757df93e74880ed7e9005377a0426c472bb976 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -417,10 +417,8 @@ "အပလီကေးရှင်းအား ဖုန်းရဲ့ စွမ်းဆောင်ချက်များအား သုံးခွင့်ပြုပါ။ အပလီကေးရှင်းအနေဖြင့် ဖုန်းနံပါတ်၊ စက်နံပါတ်၊ ဖုန်းခေါ်နေမှု ရှိမရှိနှင့် တဖက်မှ ဖုန်းနံပါတ် များအား သိရှိနိုင်ပါသည်" "ခေါ်ဆိုမှုများကို စနစ်မှတစ်ဆင့် ဖြတ်သန်းခွင့်ပြုပါ" "ခေါ်ဆိုမှု အတွေ့အကြုံ ပိုမိုကောင်းမွန်လာစေရန်အတွက် အက်ပ်၏ ခေါ်ဆိုမှုအား စနစ်မှတစ်ဆင့် ဖြတ်သန်းရန် ခွင့်ပြုပါသည်။" - - - - + "အခြားအက်ပ်မှ ဖုန်းခေါ်ဆိုမှုကို ဆက်လက်ပြုလုပ်ပါ" + "အခြားအက်ပ်တွင် စတင်ထားသည့် ဖုန်းခေါ်ဆိုမှုကို ဆက်လက်ပြုလုပ်ရန် ဤအက်ပ်ကို ခွင့်ပြုသည်။" "ဖုန်းနံပါတ်များကို ဖတ်ရန်" "အက်ပ်ကို စက်ပစ္စည်း၏ ဖုန်းနံပါတ်များအား အသုံးပြုခွင့်ပေးပါ။" "တက်ပလက်အား ပိတ်ခြင်းမှ ကာကွယ်ခြင်း" @@ -499,6 +497,10 @@ "ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။" "အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေဖတ်စနစ်ကို ပိတ်ထားပါသည်။" "ပြန်ကြိုးစားပါ" + + + + "လက်ချောင်း %d" @@ -997,12 +999,9 @@ "ဖွင့်ရန်" "စာပို့ရန်" "ထည့်ရန်" - - - - - - + "ကြည့်ရန်" + "အချိန်ဇယား" + "ရှာရန်" "သိမ်းဆည်သော နေရာ နည်းနေပါသည်" "တချို့ စနစ်လုပ်ငန်းများ အလုပ် မလုပ်ခြင်း ဖြစ်နိုင်ပါသည်" "စနစ်အတွက် သိုလှောင်ခန်း မလုံလောက်ပါ။ သင့်ဆီမှာ နေရာလွတ် ၂၅၀ MB ရှိတာ စစ်ကြည့်ပြီး စတင်ပါ။" @@ -1128,8 +1127,7 @@ Wi-Fi ကွန်ယက်ရရှိနိုင်သည်အား ဖွင့်ပါ "အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပါ" - - + "ဝန်ဆောင်မှုပေးသူ Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပါ" "အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်နေသည်" "Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပြီးပါပြီ" "Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်၍ မရပါ" @@ -1214,13 +1212,23 @@ "ခွင့်ပြုချက်မလိုအပ်ပါ" "သင့်အတွက် ပိုက်ဆံကုန်ကျနိုင်ပါသည်" "အိုကေ" - "ဤစက်ကို USB ဖြင့် အားသွင်းနေသည်" - "ချိတ်ဆက်ထားသည့် စက်ပစ္စည်းကို USB မှတစ်ဆင့် အားသွင်းနေသည်" - "ဖိုင်လွှဲပြောင်းရန်အတွက် USB" - "ဓာတ်ပုံလွှဲပြောင်းရန်အတွက် USB" - "MIDI အတွက် USB" - "USBတွဲဖက်ပစ္စည်းအား ချိတ်ဆက်ထားသည်" + + + + + + + + + + + + + + "နောက်ထပ်ရွေးချယ်စရာများအတွက် တို့ပါ။" + + "အန်နာလော့ အသံကိရိယာကို တွေ့ထားပါသည်" "တပ်ဆင်ထားသော ကိရိယာကို ဤဖုန်းနှင့် တွဲသုံး၍မရပါ။ ပိုမိုလေ့လာရန် တို့ပါ။" "USB အမှားရှာပြင်စနစ် ချိတ်ဆက်ထားသည်" @@ -1659,9 +1667,6 @@ "အလုပ် %1$s" "ဒုတိယအလုပ် %1$s" "တတိယအလုပ် %1$s" - "ဤမျက်နှာပြင်ကို ပင်ဖြုတ်ရန်အတွက် \'နောက်သို့\' နှင့် \'အနှစ်ချုပ်\' ခလုတ်များကို အတူတို့၍ ထိထားပါ" - "မျက်နှာပြင်ကို ပင်ထိုးထား" - "မျက်နှာပြင် ပင်ထိုးမှု ဖြတ်လိုက်ပြီ" "ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်" "ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်" "ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်" @@ -1758,10 +1763,8 @@ "အလုပ်ပရိုဖိုင် ဖွင့်လိုသလား။" "သင်၏ အလုပ်အက်ပ်၊ အကြောင်းကြားချက်၊ ဒေတာနှင့် အခြားအလုပ်ပရိုဖိုင် ဝန်ဆောင်မှုများကို ဖွင့်လိုက်ပါမည်" "ဖွင့်ပါ" - - - - + "ဤအက်ပ်ကို Android ဗားရှင်းဟောင်းအတွက် ပြုလုပ်ထားခြင်းဖြစ်ပြီး ပုံမှန်အလုပ်မလုပ်နိုင်ပါ။ အပ်ဒိတ်များအတွက် ရှာကြည့်ပါ သို့မဟုတ် ဆော့ဖ်ဝဲအင်ဂျင်နီယာကို ဆက်သွယ်ပါ။" + "အပ်ဒိတ်အတွက် စစ်ကြည့်ရန်" "သင့်ထံတွင် စာအသစ်များရောက်နေသည်" "ကြည့်ရှုရန် SMS အက်ပ်ကိုဖွင့်ပါ" "အချို့လုပ်ဆောင်ချက်များ ကန့်သတ်ချက်ရှိနိုင်သည်" @@ -1828,17 +1831,15 @@ "စကားသံအတွက် ဖုန်းကို ခွင့်မပြုပါ" "ပေါ့ပ်အပ် ဝင်းဒိုး" "+ %1$d" - "ဤဖြတ်လမ်းလင့်ခ်ကို အသုံးပြုနိုင်ရန် နောက်ဆုံးထွက်အက်ပ် လိုအပ်ပါသည်" + + "အက်ပ်သည် မိတ္တူကူးခြင်းနှင့် ပြန်ယူခြင်းကို ပံ့ပိုးခြင်းမရှိသည့်အတွက် ဖြတ်လမ်းလင့်ခ်ကို ပြန်ယူ၍မရပါ" "အက်ပ်လက်မှတ် မတူညီသည့်အတွက် ဖြတ်လမ်းလင့်ခ်များကို ပြန်ယူ၍မရပါ" "ဖြတ်လမ်းလင့်ခ်ကို ပြန်ယူ၍မရပါ" "ဖြတ်လမ်းလင့်ခ် ပိတ်ထားသည်" - - - - - - + "ဖြုတ်ရန်" + "ဘာဖြစ်ဖြစ် ဖွင့်ရန်" + "အန္တရာယ်ရှိသော အက်ပ်ကို တွေ့ရှိထားသည်" "%1$s သည် %2$s ၏အချပ်များကို ပြသလိုသည်" "တည်းဖြတ်ရန်" diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 4cbdd17a1b34fbf75735943ab8e46c68a399e42d..1b73237e261989ee6394d902207d169d3b4d7895 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Sikkermodus" "Android-system" - - - - + "Bytt til personlig profil" + "Bytt til jobbprofil" "Kontakter" "se kontaktene dine" "Gi <b>%1$s</b> tilgang til kontaktene dine" @@ -419,10 +417,8 @@ "Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing." "send anrop gjennom systemet" "Lar appen sende anrop gjennom systemet for å forbedre anropsopplevelsen." - - - - + "fortsette et anrop fra en annen app" + "Lar appen fortsette et anrop som ble startet i en annen app." "les telefonnumre" "Gir appen tilgang til telefonnumrene til enheten." "hindre nettbrettet fra å gå over til sovemodus" @@ -497,11 +493,14 @@ "Fingeravtrykket kan ikke lagres. Fjern et eksisterende fingeravtrykk." "Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt." "Fingeravtrykk-operasjonen ble avbrutt." - - + "Fingeravtrykk-operasjonen ble avbrutt av brukeren." "For mange forsøk. Prøve på nytt senere." "For mange forsøk. Fingeravtrykkssensoren er slått av." "Prøv igjen." + + + + "Finger %d" @@ -1000,12 +999,9 @@ "Åpne" "Melding" "Legg til" - - - - - - + "Se" + "Oversikt" + "Spor" "Lite ledig lagringsplass" "Enkelte systemfunksjoner fungerer muligens ikke slik de skal" "Det er ikke nok lagringsplass for systemet. Kontrollér at du har 250 MB ledig plass, og start på nytt." @@ -1131,8 +1127,7 @@ Åpent Wi-Fi-nettverk er tilgjengelig "Koble til et åpent Wi‑Fi-nettverk" - - + "Koble til operatørens Wi-Fi-nettverk" "Kobler til åpent Wi-Fi-nettverk" "Koblet til Wi-Fi-nettverk" "Kunne ikke koble til Wi-Fi-nettverket" @@ -1216,13 +1211,23 @@ "Trenger ingen rettigheter" "dette kan koste deg penger" "OK" - "Enheten lades via USB" - "Den tilkoblede enheten får strøm via USB" - "USB for filoverføring" - "USB for bildeoverføring" - "USB for MIDI" - "Koblet til et USB-tilbehør" + + + + + + + + + + + + + + "Trykk for å få flere alternativ." + + "Analogt lydtilbehør ble oppdaget" "Den tilkoblede enheten er ikke kompatibel med denne telefonen. Trykk for å finne ut mer." "USB-feilsøking tilkoblet" @@ -1661,9 +1666,6 @@ "Jobb-%1$s" "Andre %1$s for jobben" "Tredje %1$s for jobben" - "For å løsne denne skjermen, trykk på og hold inne Tilbake- og Oversikt-knappene" - "Skjermen er festet" - "Skjermen er løsnet" "PIN-kode for å løsne apper" "Krev opplåsingsmønster for å løsne apper" "Krev passord for å løsne apper" @@ -1757,15 +1759,11 @@ "Alle språk" "Alle områder" "Søk" - - - - + "Vil du slå på jobbprofilen?" + "Jobbappene dine samt varsler, data og andre funksjoner i jobbprofilen din blir slått på" "Slå på" - - - - + "Denne appen er utviklet for en eldre versjon av Android og fungerer kanskje ikke som den skal. Prøv å se etter oppdateringer, eller kontakt utvikleren." + "Se etter oppdatering" "Du har nye meldinger" "Åpne SMS-appen for å se" "Enkelte funksjoner kan være begrenset" @@ -1832,17 +1830,15 @@ "Telefonen har ikke tillatelse til tale" "Forgrunnsvindu" "+ %1$d" - "Denne snarveien krever den nyeste appen" + + "Kunne ikke gjenopprette snarveien fordi appen ikke støtter sikkerhetskopiering og gjenoppretting" "Kunne ikke gjenopprette snarveien på grunn av manglende samsvar for appsignaturen" "Kunne ikke gjenopprette snarveien" "Snarveien er slått av" - - - - - - + "AVINSTALLER" + "ÅPNE LIKEVEL" + "En skadelig app ble oppdaget" "%1$s vil vise %2$s-utsnitt" "Endre" diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 014d4f2ba9d3e552bec2238d5187479f9f8266ff..4a2aad61085aba09ae200d1540343d538d4baea7 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -235,7 +235,7 @@ "हवाइजहाज मोड" "हवाइजहाज मोड खुला छ" "हवाइजहाज मोड बन्द छ" - "सेटिङ्हरू" + "सेटिङहरू" "सहायता दिनुहोस्" "आवाज सहायता" "लकडाउन प्रविष्ट गर्नुहोस्" @@ -264,10 +264,8 @@ "%1$s, %2$s" "सुरक्षित मोड" "एन्ड्रोइड प्रणाली" - - - - + "व्यक्तिगत प्रोफाइलमा बदल्नुहोस्" + "कार्य प्रोफाइलमा बदल्नुहोस्" "सम्पर्कहरू" "तपाईँको सम्पर्कमाथि पहुँच गर्नुहोस्" "<b>%1$s</b> लाई आफ्ना सम्पर्क ठेगानाहरूमाथि पहुँच राख्न दिनुहोस्" @@ -402,7 +400,7 @@ "यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको TV मा उपलब्ध हुनुपर्छ।" "यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनुपर्छ।" "तपाईँका अडियो सेटिङहरू परिवर्तन गर्नुहोस्" - "अनुप्रयोगलाई ग्लोबल अडियो सेटिङ्हरू परिमार्जन गर्न अनुमति दिन्छ, जस्तै आवाजको मात्रा र आउटपुटको लागि कुन स्पिकर प्रयोग गर्ने।" + "अनुप्रयोगलाई ग्लोबल अडियो सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ, जस्तै आवाजको मात्रा र आउटपुटको लागि कुन स्पिकर प्रयोग गर्ने।" "अडियो रेकर्ड गर्नुहोस्" "यस अनुप्रयोगले जुनसुकै समय माइक्रोफोनको प्रयोग गरी अडियो रेकर्ड गर्न सक्छ।" "SIM मा आदेशहरू पठाउन दिनुहोस्" @@ -419,10 +417,8 @@ "उपकरणको फोन विशेषताहरूको पहुँच गर्न अनुप्रयोगलाई अनुमति दिन्छ। यस अनुमतिले फोन नम्बर र उपकरणको IDs, कल सक्षम छ कि छैन र कलद्वारा जोडिएको टाढाको नम्बर निर्धारण गर्न अनुमति दिन्छ।" "प्रणाली मार्फत कल गर्न दिनुहोस्‌" "कल गर्दाको अनुभवलाई सुधार्न यस अनुप्रयोगलाई प्रणाली मार्फत कलहरू गर्न अनुमति दिन्छ।" - - - - + "अर्को अनुप्रयोगमा सुरु गरिएको कल जारी राख्नुहोस्" + "यस अनुप्रयोगलाई अर्को अनुप्रयोगमा सुरु गरिएको कल जारी राख्ने अनुमति दिन्छ।" "फोन नम्बरहरू पढ्ने" "उक्त अनुप्रयोगलाई यस यन्त्रको फोन नम्बरहरूमाथि पहुँच राख्न दिनुहोस्।" "ट्याब्लेटलाई निन्द्रामा जानबाट रोक्नुहोस्" @@ -497,11 +493,14 @@ "औँठाछाप भण्डारण गर्न सकिँदैन। कृपया अवस्थित औठाछाप हटाउनुहोस्।" "औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।" "औँठाछाप सञ्चालन रद्द गरियो।" - - + "प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो।" "धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला" "अत्यन्त धेरै प्रयासहरू। फिंगरप्रिन्ट सेन्सरलाई असक्षम पारियो।" "पुन: प्रयास गर्नुहोला।" + + + + "औंला %d" @@ -1000,12 +999,9 @@ "खोल्नुहोस्" "सन्देश" "थप्नुहोस्" - - - - - - + "हेर्नुहोस्" + "समयतालिका" + "ट्र्याक गर्नुहोस्" "भण्डारण ठाउँ सकिँदै छ" "सायद केही प्रणाली कार्यक्रमहरूले काम गर्दैनन्" "प्रणालीको लागि पर्याप्त भण्डारण छैन। तपाईँसँग २५० मेगा बाइट ठाउँ खाली भएको निश्चित गर्नुहोस् र फेरि सुरु गर्नुहोस्।" @@ -1024,7 +1020,7 @@ "पूर्ण कारबाही" - "साथमा खोल्नुहोस्" + "निम्नमार्फत खोल्नुहोस्" @@ -1137,8 +1133,7 @@ खुल्ला Wi-Fi सञ्जाल उपलब्ध छ "खुला Wi‑Fi नेटवर्कमा जडान गर्नुहोस्" - - + "सेवा प्रदायकको Wi‑Fi नेटवर्कमा जडान गर्नुहोस्" "खुला Wi‑Fi नेटवर्कमा जडान गर्दै" "Wi‑Fi नेटवर्कमा जडान गरियो" "Wi‑Fi नेटवर्कमा जडान गर्न सकिएन" @@ -1222,13 +1217,23 @@ "कुनै अनुमति आवश्यक छैन" "सायद तपाईँलाई पैसा पर्न सक्छ।" "ठीक छ" - "यस यन्त्रलाई USB मार्फत चार्ज गर्दै" - "संलग्न गरिएको यन्त्रमा USB मार्फत पावर आपूर्ति गरिँदै" - "फाइल स्थानान्तरणको लागि USB" - "तस्बिर स्थानान्तरणको लागि USB" - "MIDI को लागि USB" - "USB सहायकमा जोडिएको छ" + + + + + + + + + + + + + + "थप विकल्पहरूका लागि ट्याप गर्नुहोस्।" + + "एनालग अडियोको सहायक उपकरण पत्ता लाग्यो" "संलग्न गरिएको यन्त्र यो फोनसँग कम्प्याटिबल छैन। थप जान्न ट्याप गर्नुहोस्।" "USB डिबग गर्ने सुविधा सुचारू छ" @@ -1459,7 +1464,7 @@ "ब्राउजर सुरु गर्ने हो?" "कल स्वीकार गर्नुहुन्छ?" "सधैँ" - "एउटा मात्र" + "एक पटक मात्र" "%1$s कार्य प्रोफाइल समर्थन गर्दैन" "ट्याब्लेट" "TV" @@ -1667,9 +1672,6 @@ "कार्य %1$s" "कार्यालयको दोस्रो %1$s" "कार्यालयको तेस्रो %1$s" - "यस स्क्रिनलाई अनपनि गर्न पछाडि जाने र परिदृश्य बटनहरूलाई छोएर थिची राख्नुहोस्" - "स्क्रिन पिन गरियो" - "स्क्रिन अनपिन गरियो" "पिन निकाल्नुअघि PIN सोध्नुहोस्" "पिन निकाल्नुअघि खोल्ने ढाँचा सोध्नुहोस्" "पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्" @@ -1763,15 +1765,11 @@ "सम्पूर्ण भाषाहरू" "सबै क्षेत्रहरू" "खोज" - - - - + "कार्य प्रोफाइल सक्रिय गर्ने?" + "तपाईंका कार्यसम्बन्धी अनुप्रयोग, सूचना, डेटा र कार्य प्रोफाइलका अन्य सुविधाहरू सक्रिय गरिने छन्‌" "सक्रिय गर्नुहोस्" - - - - + "यो अनुप्रयोग Android को पुरानो संस्करणका लागि बनाइएको हुनाले यसले सही ढङ्गले काम नगर्न सक्छ। अद्यावधिकहरू उपलब्ध छन् वा छैनन् भनी जाँच गरी हेर्नुहोस् वा यसको विकासकर्तालाई सम्पर्क गर्नुहोस्।" + "अद्यावधिक उपलब्ध छ वा छैन भनी जाँच गर्नुहोस्" "तपाईंलाई नयाँ सन्देश आएको छ" "हेर्नका लागि SMS अनुप्रयोग खोल्नुहोस्" "केही कार्य सीमित हुनसक्छ" @@ -1791,7 +1789,7 @@ "सम्मेलन कल" "उपकरणको वर्णन" "खेलहरू" - "संगीत तथा अडियो" + "सङ्गीत तथा अडियो" "चलचित्र तथा भिडियो" "तस्बिर तथा छविहरू" "सामाजिक तथा सञ्चार" @@ -1838,17 +1836,15 @@ "फोनमार्फत भ्वाइस कल गर्न मिल्दैन" "पपअप विन्डो" "+ %1$d" - "यो सर्टकटलाई पछिल्लो अनुप्रयोग आवश्यक हुन्छ" + + "अनुप्रयोगले ब्याकअप तथा पुनर्स्थापनालाई समर्थन नगर्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन" "अनुप्रयोगमा प्रयोग गरिने हस्ताक्षर नमिल्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन" "सर्टकट पुनर्स्थापित गर्न सकिएन" "सर्टकट असक्षम पारिएको छ" - - - - - - + "स्थापना रद्द गर्नु…" + "जे भए पनि खोल्नुहोस्" + "हानिकारक अनुप्रयोग भेटियो" "%1$s ले %2$s का स्लाइसहरू देखाउन चाहन्छ" "सम्पादन गर्नुहोस्" diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 5412d47d06c2f4a09747e6cdcd8311e937b3e156..ae3014d2906bb00a45a54e6493a425af7b3e0931 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "ਸੁਰੱਖਿਅਤ ਮੋਡ" "Android System" - - - - + "ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ ਵਰਤੋ" + "ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਰਤੋ" "ਸੰਪਰਕ" "ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ" "<b>%1$s</b> ਨੂੰ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦਿਓ" @@ -419,10 +417,8 @@ "ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫ਼ੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ਆਈ.ਡੀ. ਨਿਰਧਾਰਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਕਿਰਿਆਸ਼ੀਲ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।" "ਸਿਸਟਮ ਰਾਹੀਂ ਕਾਲਾਂ ਰੂਟ ਕਰੋ" "ਕਾਲ ਕਰਨ ਦੇ ਅਨੁਭਵ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ ਐਪ ਨੂੰ ਇਸਦੀਆਂ ਕਾਲਾਂ ਨੂੰ ਸਿਸਟਮ ਰਾਹੀਂ ਰੂਟ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀ ਹੈ।" - - - - + "ਕਿਸੇ ਹੋਰ ਐਪ ਤੋਂ ਕਾਲ ਜਾਰੀ ਰੱਖੋ" + "ਐਪ ਨੂੰ ਉਹ ਕਾਲ ਜਾਰੀ ਰੱਖਣ ਦਿਓ ਜਿਸਨੂੰ ਹੋਰ ਐਪ ਤੋਂ ਚਾਲੂ ਕੀਤਾ ਗਿਆ ਸੀ।" "ਫ਼ੋਨ ਨੰਬਰ ਪੜ੍ਹੋ" "ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੇ ਫ਼ੋਨ ਨੰਬਰਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀ ਹੈ।" "ਟੈਬਲੈੱਟ ਨੂੰ ਸਲੀਪ ਤੇ ਜਾਣ ਤੋਂ ਰੋਕੋ" @@ -497,11 +493,14 @@ "ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।" "ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" "ਫਿੰਗਰ" - - + "ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤਾ ਗਿਆ।" "ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ." "ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।" "ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ." + + + + "ਉਂਗਲ %d" @@ -1000,12 +999,9 @@ "ਖੋਲ੍ਹੋ" "ਸੁਨੇਹਾ ਭੇਜੋ" "ਸ਼ਾਮਲ ਕਰੋ" - - - - - - + "ਦੇਖੋ" + "ਸਮਾਂ-ਸੂਚੀ" + "ਟਰੈਕ ਕਰੋ" "ਸਟੋਰੇਜ ਦੀ ਜਗ੍ਹਾ ਖਤਮ ਹੋ ਰਹੀ ਹੈ" "ਕੁਝ ਸਿਸਟਮ ਫੰਕਸ਼ਨ ਕੰਮ ਨਹੀਂ ਵੀ ਕਰ ਸਕਦੇ" "ਸਿਸਟਮ ਲਈ ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਹੀਂ ਹੈ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ 250MB ਖਾਲੀ ਜਗ੍ਹਾ ਹੈ ਅਤੇ ਮੁੜ-ਚਾਲੂ ਕਰੋ।" @@ -1131,8 +1127,7 @@ ਉਪਲਬਧ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ "ਖੁੱਲ੍ਹੇ ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ" - - + "ਕੈਰੀਅਰ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ" "ਖੁੱਲ੍ਹੇ ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" "ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ" "ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" @@ -1217,13 +1212,23 @@ "ਕੋਈ ਅਨੁਮਤੀਆਂ ਲੁੜੀਂਦੀਆਂ ਨਹੀਂ" "ਇਸ ਨਾਲ ਤੁਹਾਨੂੰ ਖਰਚਾ ਪੈ ਸਕਦਾ ਹੈ" "ਠੀਕ" - "ਇਹ ਡੀਵਾਈਸ USB ਰਾਹੀਂ ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" - "ਨੱਥੀ ਕੀਤੇ ਡੀਵਾਈਸ ਨੂੰ USB ਰਾਹੀਂ ਪਾਵਰ ਮਿਲ ਰਹੀ ਹੈ" - "ਫ਼ਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB" - "ਫ਼ੋਟੋ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB" - "MIDI ਲਈ USB" - "ਇੱਕ USB ਐਕਸੈਸਰੀ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ" + + + + + + + + + + + + + + "ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ।" + + "ਐਨਾਲੌਗ ਆਡੀਓ ਉਪਸਾਧਨ ਦਾ ਪਤਾ ਲੱਗਿਆ" "ਨੱਥੀ ਕੀਤਾ ਡੀਵਾਈਸ ਇਸ ਫ਼ੋਨ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।" "USB ਡੀਬਗਿੰਗ ਕਨੈਕਟ ਕੀਤੀ" @@ -1662,9 +1667,6 @@ "ਕੰਮ %1$s" "ਦੂਸਰੀ ਕਾਰਜ-ਸਥਾਨ %1$s" "ਤੀਸਰੀ ਕਾਰਜ-ਸਥਾਨ %1$s" - "ਇਸ ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਪਿੰਨ ਕਰਨ ਲਈ, \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਬਟਨਾਂ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ" - "ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ" - "ਸਕ੍ਰੀਨ ਅਨਪਿਨ ਕੀਤੀ" "ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਿੰਨ ਮੰਗੋ" "ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਣਲਾਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ" "ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ" @@ -1758,15 +1760,11 @@ "ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ" "ਸਾਰੇ ਖੇਤਰ" "ਖੋਜੋ" - - - - + "ਕੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਚਾਲੂ ਕਰਨੀ ਹੈ?" + "ਤੁਹਾਡੀਆਂ ਕਾਰਜ-ਸਥਾਨ ਐਪਾਂ, ਸੂਚਨਾਵਾਂ, ਡਾਟਾ ਅਤੇ ਹੋਰ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚਾਲੂ ਕੀਤੀਆਂ ਜਾਣਗੀਆਂ" "ਚਾਲੂ ਕਰੋ" - - - - + "ਇਹ ਐਪ Android ਦੇ ਕਿਸੇ ਵਧੇਰੇ ਪੁਰਾਣੇ ਵਰਜਨ ਲਈ ਬਣਾਈ ਗਈ ਸੀ ਅਤੇ ਸ਼ਾਇਦ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ। ਅੱਪਡੇਟਾਂ ਲਈ ਜਾਂਚ ਕਰੋ ਜਾਂ ਵਿਕਾਸਕਾਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।" + "ਅੱਪਡੇਟ ਦੀ ਜਾਂਚ ਕਰੋ" "ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ" "ਦੇਖਣ ਲਈ SMS ਐਪ ਖੋਲ੍ਹੋ" "ਕੁਝ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਸੀਮਿਤ ਹੋ ਸਕਦੀ ਹੈ" @@ -1833,17 +1831,15 @@ "ਫ਼ੋਨ ਰਾਹੀਂ ਅਵਾਜ਼ੀ ਕਾਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ" "ਪੌਪਅੱਪ ਵਿੰਡੋ" "+ %1$d" - "ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਨਵੀਨਤਮ ਐਪ ਦੀ ਲੋੜ ਹੈ" + + "ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ ਕਿਉਂਕਿ ਐਪ \'ਬੈਕਅੱਪ ਅਤੇ ਮੁੜ-ਬਹਾਲੀ\' ਨਾਲ ਕੰਮ ਨਹੀਂ ਕਰਦੀ" "ਐਪ ਹਸਤਾਖਰ ਦਾ ਮੇਲ ਨਾ ਹੋਣ ਕਾਰਨ ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" "ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" "ਸ਼ਾਰਟਕੱਟ ਬੰਦ ਕੀਤਾ ਹੋਇਆ ਹੈ" - - - - - - + "ਅਣਸਥਾਪਤ ਕਰੋ" + "ਫਿਰ ਵੀ ਖੋਲ੍ਹੋ" + "ਹਾਨੀਕਾਰਕ ਐਪ ਦਾ ਪਤਾ ਲੱਗਿਆ" "%1$s ਦੀ %2$s ਦੇ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦੀ ਇੱਛਾ ਹੈ" "ਸੰਪਾਦਨ ਕਰੋ" diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 11fc517c03c80f137be804fe1c6f68a03cb4edd2..8fe4729d69952d234af29953b9cdc29dea61eb0c 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -417,10 +417,8 @@ "Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada." "encaminhar chamadas pelo sistema" "Permite que o app encaminhe suas chamadas por meio do sistema para melhorar a experiência com chamadas." - - - - + "continuar uma chamada de outro app" + "Permite que o app continue uma chamada que foi iniciada em outro app." "ler números de telefone" "Permite que o app acesse os número de telefone do dispositivo." "impedir modo de inatividade do tablet" @@ -499,6 +497,10 @@ "Excesso de tentativas. Tente novamente mais tarde." "Excesso de tentativas. Sensor de impressão digital desativado." "Tente novamente." + + + + "Dedo %d" @@ -997,12 +999,9 @@ "Abrir" "Mensagem" "Adicionar" - - - - - - + "Ver" + "Programar" + "Rastrear" "Pouco espaço de armazenamento" "Algumas funções do sistema podem não funcionar" "Não há armazenamento suficiente para o sistema. Certifique-se de ter 250 MB de espaço livre e reinicie." @@ -1128,8 +1127,7 @@ Abrir redes Wi-Fi disponíveis "Conectar-se a uma rede Wi‑Fi aberta" - - + "Conectar à rede Wi‑Fi da operadora" "Conectando-se a uma rede Wi‑Fi aberta" "Conectado a uma rede Wi‑Fi" "Não foi possível conectar-se à rede Wi‑Fi" @@ -1213,13 +1211,23 @@ "Nenhuma permissão necessária" "isso pode lhe custar dinheiro" "OK" - "USB carregando este dispositivo" - "USB fornecendo energia ao dispositivo conectado" - "USB para transferência de arquivos" - "USB para transferência de fotos" - "USB para MIDI" - "Conectado a um acessório USB" + + + + + + + + + + + + + + "Toque para ver mais opções." + + "Acessório de áudio analógico detectado" "O dispositivo anexo não é compatível com esse smartphone. Toque para saber mais." "Depuração USB conectada" @@ -1658,9 +1666,6 @@ "Trabalho: %1$s" "Segundo %1$s de trabalho" "Terceiro %1$s de trabalho" - "Para liberar esta tela, mantenha os botões Voltar e Visão geral pressionados" - "Tela fixada" - "Tela liberada" "Pedir PIN antes de liberar" "Pedir padrão de desbloqueio antes de liberar" "Pedir senha antes de liberar" @@ -1757,10 +1762,8 @@ "Ativar o perfil de trabalho?" "Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados" "Ativar" - - - - + "Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor." + "Procurar atualizações" "Você tem mensagens novas" "Abra o app de SMS para ver" "Algumas funcionalidades são limitadas" @@ -1827,17 +1830,15 @@ "Smartphone não autorizado para voz" "Janela pop-up" "Mais %1$d" - "Esse atalho requer o app mais recente" + + "Não foi possível restaurar o atalho porque o app não é compatível com backup e restauração" "Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps" "Não foi possível restaurar o atalho" "O atalho está desativado" - - - - - - + "DESINSTALAR" + "ABRIR MESMO ASSIM" + "App nocivo detectado" "%1$s quer mostrar partes do app %2$s" "Editar" diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index a624066aea8d4c80b22ed505219b6a214eb5b0e3..04bd394f825d28671bb1708e17509eca9613ed77 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Modo seguro" "Sistema Android" - - - - + "Mudar para o perfil pessoal" + "Mudar para o perfil de trabalho" "Contactos" "aceder aos contactos" "Permitir que a aplicação <b>%1$s</b> aceda aos seus contactos" @@ -287,7 +285,7 @@ "gravar áudio" "Permitir que a aplicação <b>%1$s</b> grave áudio" "Câmara" - "tirar fotografias e gravar vídeos" + "tirar fotos e gravar vídeos" "Permitir que a aplicação <b>%1$s</b> tire fotos e grave vídeos" "Telemóvel" "fazer e gerir chamadas" @@ -407,7 +405,7 @@ "Esta aplicação pode gravar áudio através do microfone a qualquer momento." "enviar comandos para o SIM" "Permite que a aplicação envie comandos para o SIM. Esta ação é muito perigosa." - "tirar fotografias e vídeos" + "tirar fotos e vídeos" "Esta aplicação pode tirar fotos e gravar vídeos através da câmara a qualquer momento." "controlar vibração" "Permite à aplicação controlar o vibrador." @@ -419,10 +417,8 @@ "Permite que a aplicação aceda às funcionalidades de telefone do dispositivo. Esta autorização permite que a aplicação determine o número de telefone e IDs do dispositivo, se alguma chamada está ativa e qual o número remoto ligado por uma chamada." "encaminhar chamadas através do sistema" "Permite que a aplicação encaminhe as respetivas chamadas através do sistema de modo a melhorar a experiência da chamada." - - - - + "continuar uma chamada a partir de outra aplicação" + "Permite à aplicação continuar uma chamada iniciada noutra aplicação." "ler os números de telefone" "Permite à aplicação aceder aos números de telefone do dispositivo." "impedir que o tablet entre em inactividade" @@ -497,11 +493,14 @@ "Não é possível armazenar a impressão digital. Remova uma impressão digital existente." "Foi atingido o limite de tempo da impressão digital. Tente novamente." "Operação de impressão digital cancelada." - - + "Operação de impressão digital cancelada pelo utilizador." "Demasiadas tentativas. Tente novamente mais tarde." "Demasiadas tentativas. Sensor de impressões digitais desativado." "Tente novamente." + + + + "Dedo %d" @@ -1000,12 +999,9 @@ "Abrir" "Mensagem" "Adicionar" - - - - - - + "Ver" + "Agendar" + "Monitorizar" "Está quase sem espaço de armazenamento" "Algumas funções do sistema poderão não funcionar" "Não existe armazenamento suficiente para o sistema. Certifique-se de que tem 250 MB de espaço livre e reinicie." @@ -1131,8 +1127,7 @@ Rede Wi-Fi aberta disponível "Ligar à rede Wi-Fi aberta" - - + "Estabelecer ligação à rede Wi‑Fi do operador" "A ligar à rede Wi-Fi aberta…" "Ligado à rede Wi-Fi" "Não foi possível ligar à rede Wi-Fi" @@ -1216,13 +1211,23 @@ "Não são necessárias permissões" "isto poderá estar sujeito a custos" "OK" - "Carregamento deste dispositivo por USB" - "Fornecimento de energia ao dispositivo ligado por USB" - "USB para transferência de ficheiros" - "USB para transferência de fotos" - "USB para MIDI" - "Ligado a um acessório USB" + + + + + + + + + + + + + + "Toque para obter mais opções." + + "Acessório de áudio analógico detetado" "O dispositivo ligado não é compatível com este telemóvel. Toque para saber mais." "Depuração USB ligada" @@ -1661,9 +1666,6 @@ "%1$s de trabalho" "2.º %1$s de trabalho" "3.º %1$s de trabalho" - "Para soltar este ecrã, toque sem soltar nos botões Anterior e Vista geral" - "Ecrã fixo" - "Ecrã solto" "Pedir PIN antes de soltar" "Pedir sequência de desbloqueio antes de soltar" "Pedir palavra-passe antes de soltar" @@ -1757,15 +1759,11 @@ "Todos os idiomas" "Todas as regiões" "Pesquisa" - - - - + "Ativar o perfil de trabalho?" + "As aplicações de trabalho, as notificações, os dados e outras funcionalidades do perfil de trabalho serão desativados" "Ativar" - - - - + "Esta aplicação foi concebida para uma versão mais antiga do Android e pode não funcionar corretamente. Experimente verificar se existem atualizações ou contacte o programador." + "Verificar se existem atualizações" "Tem mensagens novas" "Abra a aplicação de SMS para ver" "Algumas funcionalid. limitadas" @@ -1832,17 +1830,15 @@ "Telemóvel não permitido para voz" "Janela pop-up" "+ %1$d" - "Este atalho requer a aplicação mais recente." + + "Não foi possível restaurar o atalho porque a aplicação não é compatível com a funcionalidade de cópia de segurança e restauro." "Não foi possível restaurar o atalho devido a uma falha de correspondência entre as assinaturas das aplicações." "Não foi possível restaurar o atalho." "O atalho está desativado." - - - - - - + "DESINSTALAR" + "ABRIR MESMO ASSIM" + "Aplicação prejudicial detetada" "A aplicação %1$s pretende mostrar partes da aplicação %2$s." "Editar" diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 11fc517c03c80f137be804fe1c6f68a03cb4edd2..8fe4729d69952d234af29953b9cdc29dea61eb0c 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -417,10 +417,8 @@ "Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada." "encaminhar chamadas pelo sistema" "Permite que o app encaminhe suas chamadas por meio do sistema para melhorar a experiência com chamadas." - - - - + "continuar uma chamada de outro app" + "Permite que o app continue uma chamada que foi iniciada em outro app." "ler números de telefone" "Permite que o app acesse os número de telefone do dispositivo." "impedir modo de inatividade do tablet" @@ -499,6 +497,10 @@ "Excesso de tentativas. Tente novamente mais tarde." "Excesso de tentativas. Sensor de impressão digital desativado." "Tente novamente." + + + + "Dedo %d" @@ -997,12 +999,9 @@ "Abrir" "Mensagem" "Adicionar" - - - - - - + "Ver" + "Programar" + "Rastrear" "Pouco espaço de armazenamento" "Algumas funções do sistema podem não funcionar" "Não há armazenamento suficiente para o sistema. Certifique-se de ter 250 MB de espaço livre e reinicie." @@ -1128,8 +1127,7 @@ Abrir redes Wi-Fi disponíveis "Conectar-se a uma rede Wi‑Fi aberta" - - + "Conectar à rede Wi‑Fi da operadora" "Conectando-se a uma rede Wi‑Fi aberta" "Conectado a uma rede Wi‑Fi" "Não foi possível conectar-se à rede Wi‑Fi" @@ -1213,13 +1211,23 @@ "Nenhuma permissão necessária" "isso pode lhe custar dinheiro" "OK" - "USB carregando este dispositivo" - "USB fornecendo energia ao dispositivo conectado" - "USB para transferência de arquivos" - "USB para transferência de fotos" - "USB para MIDI" - "Conectado a um acessório USB" + + + + + + + + + + + + + + "Toque para ver mais opções." + + "Acessório de áudio analógico detectado" "O dispositivo anexo não é compatível com esse smartphone. Toque para saber mais." "Depuração USB conectada" @@ -1658,9 +1666,6 @@ "Trabalho: %1$s" "Segundo %1$s de trabalho" "Terceiro %1$s de trabalho" - "Para liberar esta tela, mantenha os botões Voltar e Visão geral pressionados" - "Tela fixada" - "Tela liberada" "Pedir PIN antes de liberar" "Pedir padrão de desbloqueio antes de liberar" "Pedir senha antes de liberar" @@ -1757,10 +1762,8 @@ "Ativar o perfil de trabalho?" "Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados" "Ativar" - - - - + "Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor." + "Procurar atualizações" "Você tem mensagens novas" "Abra o app de SMS para ver" "Algumas funcionalidades são limitadas" @@ -1827,17 +1830,15 @@ "Smartphone não autorizado para voz" "Janela pop-up" "Mais %1$d" - "Esse atalho requer o app mais recente" + + "Não foi possível restaurar o atalho porque o app não é compatível com backup e restauração" "Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps" "Não foi possível restaurar o atalho" "O atalho está desativado" - - - - - - + "DESINSTALAR" + "ABRIR MESMO ASSIM" + "App nocivo detectado" "%1$s quer mostrar partes do app %2$s" "Editar" diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 52995ae8b578b9cbd397245975446d333b9498b4..defb40bb072dab6439d22e539a8dc4ca9e5e75c6 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -420,10 +420,8 @@ "Permite aplicației să acceseze funcțiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel." "să direcționeze apelurile prin intermediul sistemului" "Permiteți aplicației să direcționeze apelurile prin intermediul sistemului pentru a îmbunătăți calitatea apelurilor." - - - - + "să continue un apel dintr-o altă aplicație" + "Permite aplicației să continue un apel care a fost inițiat dintr-o altă aplicație." "să citească numerele de telefon" "Permite aplicației să acceseze numerele de telefon ale dispozitivului." "împiedicarea computerului tablet PC să intre în repaus" @@ -502,6 +500,10 @@ "Prea multe încercări. Încercați din nou mai târziu." "Prea multe încercări. Senzorul de amprentă este dezactivat." "Încercați din nou." + + + + "Degetul %d" @@ -1017,12 +1019,9 @@ "Deschideți" "Mesaj" "Adăugați" - - - - - - + "Afișați" + "Program" + "Urmăriți" "Spațiul de stocare aproape ocupat" "Este posibil ca unele funcții de sistem să nu funcționeze" "Spațiu de stocare insuficient pentru sistem. Asigurați-vă că aveți 250 MB de spațiu liber și reporniți." @@ -1150,8 +1149,7 @@ Rețea Wi-Fi deschisă disponibilă "Conectați-vă la o rețea Wi‑Fi deschisă" - - + "Conectați-vă la rețeaua Wi-Fi a operatorului" "Se stabilește conexiunea la o rețea Wi‑Fi deschisă" "S-a realizat conexiunea la rețeaua Wi-Fi" "Nu s-a putut stabili conexiunea la rețeaua Wi-Fi" @@ -1235,13 +1233,23 @@ "Nu se solicită nicio permisiune" "aceasta poate să genereze costuri" "OK" - "Dispozitivul se încarcă prin USB" - "Dispozitivul atașat se încarcă prin USB" - "Conexiune USB pentru transferul fișierelor" - "Conexiune USB pentru transferul fotografiilor" - "Conexiune USB pentru MIDI" - "Conectat la un accesoriu USB" + + + + + + + + + + + + + + "Atingeți pentru mai multe opțiuni." + + "S-a detectat un accesoriu audio analogic" "Dispozitivul atașat nu este compatibil cu acest telefon. Atingeți pentru a afla mai multe." "Remedierea erorilor prin USB este conectată" @@ -1683,9 +1691,6 @@ "%1$s de serviciu" "%1$s pentru serviciu (2)" "%1$s pentru serviciu (3)" - "Pentru a anula fixarea acestui ecran, atingeți lung butoanele Înapoi și Recente" - "Ecran fixat" - "Fixarea ecranului anulată" "Solicită codul PIN înainte de a anula fixarea" "Solicită mai întâi modelul pentru deblocare" "Solicită parola înainte de a anula fixarea" @@ -1791,10 +1796,8 @@ "Activați profilul de serviciu?" "Se vor activa aplicațiile dvs. de serviciu, notificările, datele și alte funcții ale profilului de serviciu" "Activați" - - - - + "Această aplicație a fost creată pentru o versiune Android mai veche și este posibil să nu funcționeze corect. Încercați să căutați actualizări sau contactați dezvoltatorul." + "Căutați actualizări" "Aveți mesaje noi" "Deschideți aplicația pentru SMS-uri ca să vizualizați" "Unele funcții ar putea fi limitate" @@ -1862,17 +1865,15 @@ "Telefonul nu este permis pentru voce" "Fereastră pop-up" "+ %1$d" - "Această comandă rapidă necesită cea mai recentă aplicație" + + "Nu s-a putut restabili comanda rapidă deoarece aplicația nu acceptă backupul și restabilirea" "Nu s-a putut restabili comanda rapidă din cauza nepotrivirii semnăturii aplicației" "Nu s-a putut restabili comanda rapidă" "Comanda rapidă este dezactivată" - - - - - - + "DEZINSTALAȚI" + "Deschideți oricum" + "Aplicație dăunătoare detectată" "%1$s vrea să afișeze porțiuni din %2$s" "Editați" diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 0d62e753c268292709500e55ecf0b551f84407e0..817cbf79dfa36394c771e8b78bacede0f3a2ec69 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -270,10 +270,8 @@ "%1$s, %2$s" "Безопасный режим" "Система Android" - - - - + "Переключиться на личный профиль" + "Переключиться на рабочий профиль" "Контакты" "доступ к контактам" "Разрешите приложению <b>%1$s</b> доступ к контактам" @@ -425,10 +423,8 @@ "Приложение получит доступ к функциям телефона на устройстве. Кроме того, оно сможет определять номера телефонов и серийные номера моделей, состояние активности вызова, а также удаленные номера, с которыми установлено соединение." "перенаправлять звонки в системе" "Приложение сможет перенаправлять звонки в системе с целью улучшения качества связи." - - - - + "Продолжить вызов, начатый в другом приложении" + "Разрешает приложению продолжить вызов, начатый в другом приложении." "чтение номеров телефонов" "Разрешает приложению доступ к телефонным номерам устройства." "Отключение спящего режима" @@ -503,11 +499,14 @@ "Чтобы сохранить новый отпечаток, удалите существующий." "Превышено время ожидания. Повторите попытку." "Операция с отпечатком отменена." - - + "Операция с отпечатком пальца отменена пользователем." "Слишком много попыток. Повторите позже." "Слишком много попыток. Сканер отпечатков пальцев отключен." "Повторите попытку." + + + + "Отпечаток %d" @@ -1040,12 +1039,9 @@ "Открыть" "Написать SMS" "Добавить" - - - - - - + "Открыть" + "Расписание" + "Отследить" "Недостаточно памяти" "Некоторые функции могут не работать" "Недостаточно свободного места для системы. Освободите не менее 250 МБ дискового пространства и перезапустите устройство." @@ -1175,8 +1171,7 @@ Есть открытые сети Wi-Fi "Подключитесь к открытой сети Wi‑Fi" - - + "Подключитесь к сети Wi‑Fi оператора" "Подключение к открытой сети Wi‑Fi…" "Подключено к сети Wi-Fi" "Не удалось подключиться к сети Wi‑Fi" @@ -1260,13 +1255,23 @@ "Не требуется разрешений" "это может стоить вам денег!" "ОК" - "Зарядка через USB" - "Подача питания на подключенное устройство через USB" - "Передача файлов через USB" - "Передача фото через USB" - "MIDI через USB" - "USB-устройство подключено" + + + + + + + + + + + + + + "Нажмите, чтобы показать дополнительные параметры." + + "Обнаружено аналоговое аудиоустройство" "Подсоединенное устройство несовместимо с этим телефоном. Нажмите, чтобы узнать подробности." "Отладка по USB разрешена" @@ -1711,9 +1716,6 @@ "Рабочий %1$s" "Задача 2: %1$s" "Задача 3: %1$s" - "Чтобы открепить экран, нажмите и удерживайте кнопки \"Назад\" и \"Обзор\"" - "Блокировка включена" - "Блокировка выключена" "PIN-код для отключения" "Запрашивать графический ключ для отключения блокировки" "Запрашивать пароль для отключения блокировки" @@ -1825,15 +1827,11 @@ "Все языки" "Все регионы" "Поиск" - - - - + "Включить рабочий профиль?" + "Будут включены корпоративные приложения, уведомления, данные и другие функции рабочего профиля." "Включить" - - - - + "Это приложение было создано для более ранней версии Android и может работать со сбоями. Проверьте наличие обновлений или свяжитесь с разработчиком." + "Проверить обновления" "Новые сообщения" "Чтобы просмотреть, откройте приложение для обмена SMS" "Некоторые функции недоступны" @@ -1902,17 +1900,15 @@ "Для телефона недоступны голосовые вызовы" "Всплывающее окно" "+ %1$d" - "Требуется последняя версия приложения" + + "Не удалось восстановить ярлык: приложение не поддерживает резервное копирование" "Не удалось восстановить ярлык: некорректная подпись приложения" "Не удалось восстановить ярлык" "Ярлык отключен" - - - - - - + "УДАЛИТЬ" + "ОТКРЫТЬ" + "Обнаружено вредоносное приложение" "Приложение \"%1$s\" запрашивает разрешение на показ фрагментов приложения \"%2$s\"." "Изменить" diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 846b0ee5b83ccf565c9561c2926668c5835d1bd6..ab6924293f28a223d8a5894ba821dec95415c41f 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -417,10 +417,8 @@ "උපාංගයේ දුරකථන විශේෂාංග වෙත ප්‍රවේශයට යෙදුමට ඉඩ දෙයි. ඇමතුම සක්‍රිය වුවත්, සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට ඉඩ දෙයි." "පද්ධතිය හරහා ඇමතුම් මාර්ගගත කරන්න" "ඇමතුම් අත්දැකීම වැඩිදියුණු කිරීම සඳහා යෙදුමට පද්ධතිය හරහා එහි ඇමතුම් මාර්ගගත කිරීමට ඉඩ දෙයි." - - - - + "වෙනත් යෙදුමක් වෙතින් වන ඇමතුමක් දිගටම කරගෙන යන්න" + "වෙනත් යෙදුමක ආරම්භ කරන ලද ඇමතුමක් දිගටම කරගෙන යාමට යෙදුමට ඉඩ දෙයි." "දුරකථන අංක කියවන්න" "උපාංගයේ දුරකථන අංක වෙත ප්‍රවේශයට යෙදුමට ඉඩ දෙයි." "ටැබ්ලටය නින්දෙන් වැළක්වීම" @@ -499,6 +497,10 @@ "උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න." "උත්සාහයන් ඉතා වැඩි ගණනකි. ඇඟිලි සලකුණු සංවේදකය අබල කරන ලදී." "නැවත උත්සාහ කරන්න." + + + + "ඇඟිලි %d" @@ -999,12 +1001,9 @@ "විවෘත කරන්න" "පණිවිඩය" "එක් කරන්න" - - - - - - + "බලන්න" + "කාල සටහන" + "ශ්‍රව්‍ය ඛණ්ඩය" "ආචයනය ඉඩ ප්‍රමාණය අඩු වී ඇත" "සමහර පද්ධති කාර්යයන් ක්‍රියා නොකරනු ඇත" "පද්ධතිය සඳහා ප්‍රමාණවත් ඉඩ නොමැත. ඔබට 250MB නිදහස් ඉඩක් තිබෙන ඔබට තිබෙන බව සහතික කරගෙන නැවත උත්සාහ කරන්න." @@ -1130,8 +1129,7 @@ විවෘත Wi-Fi ජාල තිබේ "විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙන්න" - - + "වාහක Wi-Fi ජාලයට සම්බන්ධ වන්න" "විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙමින්" "Wi-Fi ජාලයක් වෙත සම්බන්ධ විය" "Wi-Fi ජාලයක් වෙත සම්බන්ධ විය නොහැකි විය" @@ -1215,13 +1213,23 @@ "අවසර අවශ්‍ය නොමැත" "මෙමඟින් ඔබට මුදල් වැය විය හැක" "හරි" - "මෙම උපාංගය USB වෙතින් ආරෝපණය" - "අමුණා ඇති උපාංගයට USB මඟින් බලය සපයමින්" - "ගොනු හුවමාරුව සඳහා USB" - "ඡායාරූප හුවමාරුව සඳහා USB" - "MIDI සඳහා USB" - "USB මෙවලමකට සම්බන්ධිතයි" + + + + + + + + + + + + + + "තවත් විකල්ප සඳහා තට්ටු කරන්න." + + "ප්‍රතිසම ශ්‍රව්‍ය උපාංගය අනාවරණය කර ගන්නා ලදී" "මෙම දුරකථනය සමඟ සම්බන්ධිත උපාංගය නොගැළපෙයි. තව දැන ගැනීමට තට්ටු කරන්න." "USB නිදොස්කරණය සම්බන්ධිතයි" @@ -1660,9 +1668,6 @@ "වැඩ %1$s" "2වන වැඩ %1$s" "3වන වැඩ %1$s" - "මෙම තිර ඇමුණුම ගැලවීමට, දළ විශ්ලේෂණය බොත්තම් ස්පර්ශ කර අල්ලා ගෙන සිටින්න" - "තිරය අගුළු දමා ඇත" - "තිරයේ අගුළු ඇර ඇත" "ගැලවීමට පෙර PIN විමසන්න" "ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න" "ගැලවීමට පෙර මුරපදය විමසන්න" @@ -1759,10 +1764,8 @@ "කාර්යාල පැතිකඩ ක්‍රියාත්මක කරන්නද?" "ඔබගේ වැඩ යෙදුම්, දැනුම්දීම්, දත්ත සහ වෙනත් කාර්යාල පැතිකඩ විශේෂාංග ක්‍රියාත්මක කරනු ඇත" "ක්‍රියාත්මක කරන්න" - - - - + "මෙම යෙදුම Android හි පැරණි අනුවාදයක් සඳහා තනා ඇති අතර නිසියාකාරව ක්‍රියා නොකරනු ඇත. යාවත්කාලීන සඳහා පරික්ෂා කිරීම උත්සාහ කරන්න, නැතහොත් සංවර්ධක අමතන්න." + "යාවත්කාලීන සඳහා පරික්ෂා කරන්න" "ඔබට නව පණිවිඩ තිබේ" "බැලීමට විවෘත SMS යෙදුම විවෘත කරන්න" "ඇතැම් ක්‍රියාකාරිත්ව සීමිත විය හැකිය" @@ -1829,17 +1832,15 @@ "දුරකථනය හඬ සඳහා ඉඩ නොදේ" "උත්පතන කවුළුව" "+ %1$d" - "මෙම කෙටි මගට නවතම යෙදුම අවශ්‍යයි" + + "යෙදුම උපස්ථ සහ ප්‍රතිසාධනය සඳහා සහාය නොදක්වන බැවින් කෙටි මග ප්‍රතිසාධනය කළ නොහැකි විය" "යෙදුම් අත්සන නොගැළපෙන බැවින් කෙටි මග ප්‍රතිසාධනය කළ නොහැකි විය" "කෙටි මග ප්‍රතිසාධනය කළ නොහැකි විය" "කෙටි මග අබල කර ඇත" - - - - - - + "අස්ථාපනය කරන්න" + "කෙසේ වුවත් විවෘත කරන්න" + "හානිකර යෙදුමක් අනාවරණය කර ගන්නා ලදී" "%1$s හට කොටස් %2$sක් පෙන්වීමට අවශ්‍යයි" "සංස්කරණය" diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 32d91ea939d5d790a56cf908d93ba7eaaa099fd6..66baaf4ecd364a28b775dff04131cec1107904f4 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -262,10 +262,8 @@ "%1$s, %2$s" "Mtindo salama" "Mfumo wa Android" - - - - + "Tumia wasifu wa binafsi" + "Tumia wasifu wa kazini" "Anwani" "ifikie anwani zako" "Ruhusu <b>%1$s</b> ifikie anwani zako" @@ -417,10 +415,8 @@ "Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu." "elekeza simu kupitia mfumo" "Huruhusu programu kuelekeza simu zake kupitia mfumo ili kuboresha hali ya kupiga simu." - - - - + "endelea na simu kutoka programu nyingine" + "Huruhusu programu kuendelea na simu ambayo ilianzishwa katika programu nyingine." "kusoma nambari za simu" "Inaruhusu programu kufikia nambari za simu zilizo kwenye kifaa." "zuia kompyuta ndogo dhidi ya kulala" @@ -495,11 +491,14 @@ "Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo." "Muda wa kitambulisho umekwisha. Jaribu tena." "Utendaji wa kitambulisho imeghairiwa." - - + "Mtumiaji ameghairi uthibitishaji wa alama ya kidole." "Majaribio mengi mno. Jaribu tena baadaye." "Majaribio mengi mno. Kitambua alama ya kidole kimezimwa." "Jaribu tena." + + + + "Kitambulisho %d" @@ -998,12 +997,9 @@ "Fungua" "Ujumbe" "Ongeza" - - - - - - + "Angalia" + "Ratiba" + "Toleo" "Nafasi ya kuhifadhi inakaribia kujaa" "Baadhi ya vipengee vya mfumo huenda visifanye kazi" "Hifadhi haitoshi kwa ajili ya mfumo. Hakikisha una MB 250 za nafasi ya hifadhi isiyotumika na uanzishe upya." @@ -1129,8 +1125,7 @@ Fungua mtandao wa Wi-Fi unaopatikana "Unganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote" - - + "Unganisha kwenye mtandao wa mtoa huduma ya Wi‑Fi" "Inaunganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote" "Imeunganisha kwenye mtandao wa Wi-Fi" "Imeshindwa kuunganisha kwenye mtandao wa Wi‑Fi" @@ -1214,13 +1209,23 @@ "Hakuna vibali vinavyohitajika" "huenda hii ikakugharimu pesa" "Sawa" - "Unachaji kifaa hiki ukitumia USB" - "USB inachaji kifaa ulichounganisha" - "USB kwa ajili ya kuhamisha faili" - "USB kwa ajili ya kuhamisha picha" - "USB kwa ajili ya MIDI" - "Imeunganishwa kwa kifuasi cha USB" + + + + + + + + + + + + + + "Gusa ili upate chaguo zaidi." + + "Imetambua kifaa cha sauti ya analogi" "Kifaa ulichoambatisha hakitumiki kwenye simu hii. Gusa ili upate maelezo zaidi." "Utatuaji wa USB umeunganishwa" @@ -1659,9 +1664,6 @@ "Ya kazini %1$s" "%1$s ya 2 ya Kazini" "%1$s ya 3 ya Kazini" - "Ili kubandua skrini hii, gusa na ushikilie vitufe vya Nyuma na Muhtasari" - "Skrini imebandikwa" - "Skrini imebanduliwa" "Itisha PIN kabla hujabandua" "Omba mchoro wa kufungua kabla hujabandua" "Omba nenosiri kabla hujabandua" @@ -1755,15 +1757,11 @@ "Lugha zote" "Maeneo yote" "Tafuta" - - - - + "Ungependa kuwasha wasifu wa kazini?" + "Hatua hii itawasha data, arifa, programu za kazini, arifa na vipengele vingine vya wasifu wa kazini" "Washa" - - - - + "Programu hii iliundwa kwa ajili ya toleo la zamani la Android na huenda isifanye kazi vizuri. Jaribu kuangalia masasisho au uwasiliane na msanidi programu." + "Angalia masasisho" "Una ujumbe mpya" "Fungua programu ya SMS ili uweze kuangalia" "Huenda baadhi ya vipengele havifanyi kazi" @@ -1830,17 +1828,15 @@ "Simu hairuhusiwi katika huduma ya sauti" "Dirisha Ibukizi" "+ %1$d" - "Njia hii ya mkato inahitaji toleo jipya la programu" + + "Imeshindwa kurejesha njia ya mkato kwa sababu programu haitumii kipengele cha hifadhi rudufu na kurejesha upya" "Imeshindwa kurejesha njia ya mkato kwa sababu ufunguo wako wa kuambatisha cheti kwenye programu haulingani" "Imeshindwa kurejesha njia ya mkato" "Njia ya mkato imezimwa" - - - - - - + "ONDOA" + "FUNGUA TU" + "Imetambua programu hatari" "%1$s inataka kuonyesha vipengee %2$s" "Badilisha" diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 3afdebd61607d93c95ea098a575843e15388c876..5afa711861411546ddd23748dda3ef32a830b6de 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "பாதுகாப்பு பயன்முறை" "Android அமைப்பு" - - - - + "தனிப்பட்ட சுயவிவரத்திற்கு மாற்றவும்" + "பணிச் சுயவிவரத்திற்கு மாற்றவும்" "தொடர்புகள்" "தொடர்புகளை அணுக வேண்டும்" "தொடர்புகளை அணுக, <b>%1$s</b>க்கு அனுமதி வழங்கவும்" @@ -419,10 +417,8 @@ "சாதனத்தின் மொபைல் அம்சங்களை அணுகப் பயன்பாட்டை அனுமதிக்கிறது. மொபைல் மற்றும் சாதன ஐடிகள், அழைப்பு செயலில் உள்ளதா மற்றும் அழைப்பு மூலம் இணைக்கப்பட்ட தொலைக் கட்டுப்பாட்டு எண் ஆகியவற்றைத் தீர்மானிக்க இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது." "சிஸ்டம் மூலம் அழைப்புகளை ரூட் செய்தல்" "அழைக்கும் அனுபவத்தை மேம்படுத்தும் பொருட்டு, சிஸ்டம் மூலம் தனது அழைப்புகளை ரூட் செய்ய பயன்பாட்டை அனுமதிக்கும்." - - - - + "மற்றொரு பயன்பாட்டிலிருந்து அழைப்பைத் தொடருதல்" + "மற்றொரு பயன்பாட்டில் தொடங்கப்பட்ட அழைப்பைத் தொடருவதற்கு, பயன்பாட்டை அனுமதிக்கிறது." "ஃபோன் எண்களைப் படித்தல்" "சாதனத்தின் ஃபோன் எண்களை அணுக, பயன்பாட்டை அனுமதிக்கும்." "டேப்லெட் உறக்க நிலைக்குச் செல்வதைத் தடுத்தல்" @@ -497,11 +493,14 @@ "கைரேகையைச் சேமிக்க முடியவில்லை. ஏற்கனவே உள்ள கைரேகையை அகற்றவும்." "கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்." "கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது." - - + "பயனர், கைரேகை உறுதிப்படுத்துதலை ரத்துசெய்தார்." "அதிகமான முயற்சிகள். பிறகு முயற்சிக்கவும்." "பலமுறை முயன்றுவிட்டீர்கள். கைரேகை சென்சார் முடக்கப்பட்டது." "மீண்டும் முயற்சிக்கவும்." + + + + "கைரேகை %d" @@ -1000,12 +999,9 @@ "திற" "செய்தி" "சேர்" - - - - - - + "காண்பி" + "திட்டமிடுதல்" + "கண்கானி" "சேமிப்பிடம் குறைகிறது" "சில அமைப்பு செயல்பாடுகள் வேலை செய்யாமல் போகலாம்" "முறைமையில் போதுமான சேமிப்பகம் இல்லை. 250மெ.பை. அளவு காலி இடவசதி இருப்பதை உறுதிசெய்து மீண்டும் தொடங்கவும்." @@ -1131,8 +1127,7 @@ பொது வைஃபை நெட்வொர்க் உள்ளது "திறந்த வைஃபை நெட்வொர்க்குடன் இணைக்கவும்" - - + "தொலைத்தொடர்பு சேவை வழங்கும் நிறுவனத்தின் வைஃபை நெட்வொர்க்குடன் இணைக்கிறது" "திறந்த வைஃபை நெட்வொர்க்குடன் இணைக்கிறது" "வைஃபை நெட்வொர்க்குடன் இணைக்கப்பட்டது" "வைஃபை நெட்வொர்க்குடன் இணைக்க முடியவில்லை" @@ -1217,13 +1212,23 @@ "அனுமதிகள் தேவையில்லை" "இதனால் நீங்கள் கட்டணம் செலுத்த வேண்டியிருக்கலாம்" "சரி" - "சாதனம் USB சார்ஜிங் செய்யப்படுகிறது" - "இணைத்துள்ள சாதனத்திற்கு USB சக்தி அளிக்கிறது" - "USB, கோப்புப் பரிமாற்றத்துக்கு மட்டும்" - "USB, படப் பரிமாற்றத்துக்கு மட்டும்" - "USB, MIDIக்கு மட்டும்" - "USB துணைக்கருவியுடன் இணைக்கப்பட்டுள்ளது" + + + + + + + + + + + + + + "மேலும் விருப்பங்களுக்கு, தட்டவும்." + + "அனலாக் ஆடியோ துணைக்கருவி கண்டறியப்பட்டது" "இணைத்துள்ள சாதனமானது இந்த மொபைலுடன் இணங்கவில்லை. மேலும் அறிய, தட்டவும்." "USB பிழைத் திருத்தம் இணைக்கப்பட்டது" @@ -1662,9 +1667,6 @@ "பணியிடம் %1$s" "2வது பணி %1$s" "3வது பணி %1$s" - "இந்தத் திரையை அகற்ற, முந்தையது, மேலோட்டப் பார்வை ஆகிய இரண்டு பொத்தானையும் தொட்டுப் பிடித்திருக்கவும்" - "திரை பின் செய்யப்பட்டது" - "திரையின் பின் அகற்றப்பட்டது" "அகற்றும் முன் PINஐக் கேள்" "அகற்றும் முன் திறத்தல் வடிவத்தைக் கேள்" "அகற்றும் முன் கடவுச்சொல்லைக் கேள்" @@ -1758,15 +1760,11 @@ "எல்லா மொழிகளும்" "எல்லா மண்டலங்களும்" "தேடு" - - - - + "பணிச் சுயவிவரத்தை ஆன் செய்யவா?" + "பணி ஆப்ஸ், அறிவிப்புகள், தரவு மற்றும் பிற பணிச் சுயவிவர அம்சங்கள் ஆன் செய்யப்படும்" "இயக்கு" - - - - + "இந்தப் பயன்பாடு Android இன் பழைய பதிப்புக்காக உருவாக்கப்பட்டதால், சரியாக வேலை செய்யாமல் போகலாம். புதுப்பிப்புகள் ஏதேனும் உள்ளதா எனப் பார்க்கவும் அல்லது டெவெலப்பரைத் தொடர்புகொள்ளவும்." + "புதுப்பிப்பு உள்ளதா எனப் பார்" "புதிய செய்திகள் வந்துள்ளன" "பார்க்க, SMS பயன்பாட்டைத் திறக்கவும்" "சில செயல்பாடு வரம்பிடப்பட்டிருக்கலாம்" @@ -1833,17 +1831,15 @@ "குரல் அழைப்பை மேற்கொள்ள இந்த ஃபோனுக்கு அனுமதி இல்லை" "பாப்அப் சாளரம்" "+ %1$d" - "இந்த ஷார்ட்கட்டைப் பயன்படுத்த, சமீபத்திய பயன்பாடு வேண்டும்" + + "காப்புப் பிரதி மற்றும் மீட்டமைவைப் பயன்பாடு ஆதரிக்காத காரணத்தால், ஷார்ட்கட்டை மீட்டமைக்க முடியவில்லை" "பயன்பாட்டுச் சான்றுகள் பொருந்தாத காரணத்தினால், ஷார்ட்கட்டை மீட்டமைக்க முடியவில்லை" "ஷார்ட்கட்டை மீட்டமைக்க முடியவில்லை" "குறுக்குவழி முடக்கப்பட்டுள்ளது" - - - - - - + "நிறுவல் நீக்கு" + "பரவாயில்லை, திற" + "தீங்கிழைக்கும் பயன்பாடு உள்ளது" "%2$s பயன்பாட்டின் விழிப்பூட்டல்களைக் காண்பிக்க, %1$s அனுமதி கேட்கிறது" "திருத்து" diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 183b3a23442bf897b9e84033943ca3cd9bf80bb3..a08c483eee2a080187ec4b0d314ab4a74ce2f9a0 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "సురక్షిత మోడ్" "Android సిస్టమ్" - - - - + "వ్యక్తిగత ప్రొఫైల్‌కి మార్చు" + "కార్యాలయ ప్రొఫైల్‌కి మార్చు" "పరిచయాలు" "మీ పరిచయాలను యాక్సెస్ చేయడానికి" "<b>%1$s</b>ని ఉపయోగించి, మీ పరిచయాలను యాక్సెస్ చేయండి" @@ -419,10 +417,8 @@ "పరికరం యొక్క ఫోన్ ఫీచర్‌లను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్‌ను కనుగొనడానికి యాప్‌ను అనుమతిస్తుంది." "కాల్‌లను సిస్టమ్ ద్వారా వెళ్లేలా చేయి" "కాలింగ్ అనుభవాన్ని మెరుగుపరచడం కోసం తన కాల్‌లను సిస్టమ్ ద్వారా వెళ్లేలా చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." - - - - + "మరో యాప్ నుండి కాల్‌ని కొనసాగించండి" + "మరో యాప్‌లో ప్రారంభించిన కాల్‌ని కొనసాగించడానికి యాప్‌ని అనుమతిస్తుంది." "ఫోన్ నంబర్‌లను చదువు" "పరికరం యొక్క ఫోన్ నంబర్‌లను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది." "టాబ్లెట్‌ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం" @@ -497,11 +493,14 @@ "వేలిముద్రను నిల్వ చేయడం సాధ్యపడదు. దయచేసి ఇప్పటికే ఉన్న వేలిముద్రను తీసివేయండి." "వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి." "వేలిముద్ర కార్యకలాపం రద్దయింది." - - + "వేలిముద్ర చర్యని వినియోగదారు రద్దు చేసారు." "చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి." "అనేకసార్లు ప్రయత్నించారు. వేలిముద్ర సెన్సార్ నిలిపివేయబడింది." "మళ్లీ ప్రయత్నించండి." + + + + "వేలు %d" @@ -1000,12 +999,9 @@ "తెరవండి" "సందేశం" "జోడించండి" - - - - - - + "చూడండి" + "షెడ్యూల్" + "ట్రాక్ చేయండి" "నిల్వ ఖాళీ అయిపోతోంది" "కొన్ని సిస్టమ్ కార్యాచరణలు పని చేయకపోవచ్చు" "సిస్టమ్ కోసం తగినంత నిల్వ లేదు. మీకు 250MB ఖాళీ స్థలం ఉందని నిర్ధారించుకుని, పునఃప్రారంభించండి." @@ -1131,8 +1127,7 @@ ఓపెన్ Wi-Fi నెట్‌వర్క్ అందుబాటులో ఉంది "బహిరంగ Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయండి" - - + "క్యారియర్ Wi‑Fi నెట్‌వర్క్‌కి కనెక్ట్ చేయండి" "బహిరంగ Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేస్తోంది" "Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయబడింది" "Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయడం సాధ్యపడలేదు" @@ -1217,13 +1212,23 @@ "అనుమతులు అవసరం లేదు" "దీనికి మీకు డబ్బు ఖర్చు కావచ్చు" "సరే" - "ఈ పరికరం USB మోడ్‌లో ఛార్జ్ అవుతోంది" - "జోడించిన పరికరానికి USB ద్వారా పవర్ సరఫరా అవుతోంది" - "ఫైల్ బదిలీ కోసం USB" - "ఫోటో బదిలీ కోసం USB" - "MIDI కోసం USB" - "USB ఉపకరణానికి కనెక్ట్ చేయబడింది" + + + + + + + + + + + + + + "మరిన్ని ఎంపికల కోసం నొక్కండి." + + "అనలాగ్ ఆడియో ఉపకరణం కనుగొనబడింది" "జోడించిన పరికరం ఈ ఫోన్‌కు అనుకూలంగా లేదు. మరింత తెలుసుకోవడానికి నొక్కండి." "USB డీబగ్గింగ్ కనెక్ట్ చేయబడింది" @@ -1662,9 +1667,6 @@ "కార్యాలయం %1$s" "2వ కార్యాలయం %1$s" "3వ కార్యాలయం %1$s" - "ఈ స్క్రీన్‌ను అన్‌పిన్ చేయడానికి, వెనుకకు మరియు స్థూలదృష్టి బటన్‌లను నొక్కి & పట్టుకోండి" - "స్క్రీన్ పిన్ చేయబడింది" - "స్క్రీన్ అన్‌పిన్ చేయబడింది" "అన్‌పిన్ చేయడానికి ముందు పిన్‌ కోసం అడుగు" "అన్‌పిన్ చేయడానికి ముందు అన్‌లాక్ ఆకృతి కోసం అడుగు" "అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు" @@ -1758,15 +1760,11 @@ "అన్ని భాషలు" "అన్ని ప్రాంతాలు" "వెతుకు" - - - - + "కార్యాలయ ప్రొఫైల్‌ని ఆన్ చేయాలా?" + "మీ కార్యాలయ యాప్‌లు, నోటిఫికేషన్‌లు, డేటా మరియు ఇతర కార్యాలయ ప్రొఫైల్ ఫీచర్‌లు ఆన్ చేయబడతాయి" "ఆన్ చేయి" - - - - + "ఈ యాప్ పాత వెర్షన్ Android కోసం రూపొందించబడింది మరియు అది సరిగ్గా పని చేయకపోవచ్చు. అప్‌డేట్‌ల కోసం తనిఖీ చేయడానికి ప్రయత్నించండి లేదా డెవలపర్‌ని సంప్రదించండి." + "అప్‌డేట్ కోసం తనిఖీ చేయండి" "మీకు కొత్త సందేశాలు ఉన్నాయి" "వీక్షించడానికి SMS అనువర్తనాన్ని తెరవండి" "కొంత పనితనం పరిమితం కావచ్చు" @@ -1833,17 +1831,15 @@ "వాయిస్ కోసం ఫోన్ అనుమతించబడదు" "పాప్అప్ విండో" "+ %1$d" - "ఈ సత్వరమార్గానికి తాజా యాప్ అవసరం" + + "బ్యాకప్ మరియు పునరుద్ధరణకు యాప్ మద్దతు ఇవ్వని కారణంగా సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు" "యాప్ సంతకం సరిపోలని కారణంగా సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు" "సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు" "షార్ట్‌కట్ నిలిపివేయబడింది" - - - - - - + "అన్ఇన్‌స్టాల్ చేయండి" + "ఏదేమైనా తెరువు" + "హానికరమైన యాప్ గుర్తించబడింది" "%1$s %2$s స్లైస్‌లను చూపించాలనుకుంటోంది" "సవరించు" diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 929991f46e06c034181fb527f6fc58266ae84102..9fea248e0048e977ac71d2aadba540e113b9e55d 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Güvenli mod" "Android Sistemi" - - - - + "Kişisel profile geçiş yap" + "İş profiline geç" "Kişiler" "kişilerinize erişme" "<b>%1$s</b> uygulamasının kişilerinize erişmesine izin verin" @@ -419,10 +417,8 @@ "Uygulamaya cihazdaki telefon özelliklerine erişme izni verir. Bu izin, uygulamanın telefon numarasını ve cihaz kimliğini, etkin bir çağrı olup olmadığını ve çağrıda bağlanılan karşı tarafın numarasını öğrenmesine olanak sağlar." "çağrıları sistem üzerinden yönlendir" "Uygulamanın, çağrı deneyimini iyileştirmek için çağrılarını sistem üzerinden yönlendirmesine olanak tanır." - - - - + "başka bir uygulamadaki çağrıya devam etme" + "Uygulamanın, başka bir uygulamada başlatılan çağrıya devam etmesine izin verir." "telefon numaralarını oku" "Uygulamaya, cihazınızın telefon numaralarına erişme izni verir." "tabletin uykuya geçmesini önle" @@ -497,11 +493,14 @@ "Parmak izi depolanamıyor. Lütfen mevcut parmak izlerinden birini kaldırın." "Parmak izi için zaman aşımı oluştu. Tekrar deneyin." "Parmak izi işlemi iptal edildi." - - + "Parmak izi işlemi kullanıcı tarafından iptal edildi." "Çok fazla deneme yapıldı. Daha sonra tekrar deneyin." "Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bıraıldı." "Tekrar deneyin." + + + + "%d. parmak" @@ -1000,12 +999,9 @@ "Aç" "Mesaj" "Ekle" - - - - - - + "Göster" + "Program yap" + "İzle" "Depolama alanı bitiyor" "Bazı sistem işlevleri çalışmayabilir" "Sistem için yeterli depolama alanı yok. 250 MB boş alanınızın bulunduğundan emin olun ve yeniden başlatın." @@ -1131,8 +1127,7 @@ Kullanılabilir Kablosuz ağı aç "Açık kablosuz ağa bağlanın" - - + "Operatöre ait kablosuz ağa bağlanın" "Açık kablosuz ağa bağlandı" "Kablosuz ağa bağlanıldı" "Kablosuz ağa bağlanamadı" @@ -1216,13 +1211,23 @@ "İzin gerektirmez" "bunun için sizden ücret alınabilir" "Tamam" - "Bu cihaz USB\'den şarj oluyor" - "USB, bağlı cihaza güç sağlıyor" - "Dosya aktarımı için USB" - "Fotoğraf aktarımı için USB" - "MIDI için USB" - "USB aksesuarına bağlandı" + + + + + + + + + + + + + + "Diğer seçenekler için dokunun." + + "Analog ses aksesuarı algılandı" "Takılan cihaz bu telefonla uyumlu değil. Daha fazla bilgi edinmek için dokunun." "USB hata ayıklaması bağlandı" @@ -1661,9 +1666,6 @@ "%1$s (İş)" "İş için 2. %1$s" "İş için 3. %1$s" - "Bu ekranın sabitlemesini kaldırmak için Geri\'ye ve Genel Bakış\'a dokunup basılı tutun" - "Ekran sabitlendi" - "Ekran sabitlemesi kaldırıldı" "Sabitlemeyi kaldırmadan önce PIN\'i sor" "Sabitlemeyi kaldırmadan önce kilit açma desenini sor" "Sabitlemeyi kaldırmadan önce şifre sor" @@ -1757,15 +1759,11 @@ "Tüm diller" "Tüm bölgeler" "Ara" - - - - + "İş profili açılsın mı?" + "İş uygulamalarınız, bildirimleriniz, verileriniz ve diğer iş profili özellikleriniz açılacak" "Aç" - - - - + "Bu uygulama Android\'in daha eski bir sürümü için oluşturuldu ve düzgün çalışmayabilir. Güncellemeleri kontrol etmeyi deneyin veya geliştiriciyle iletişime geçin." + "Güncellemeleri denetle" "Yeni mesajlarınız var" "Görüntülemek için SMS uygulamasını açın" "Bazı işlevler sınırlı olabilir" @@ -1832,17 +1830,15 @@ "Ses için telefona izin verilmiyor" "Pop-up Pencere" "+ %1$d" - "Bu kısayol, en son uygulamayı gerektiriyor" + + "Uygulama, yedekleme ve geri yüklemeyi desteklemediğinden kısayol geri yüklenemedi" "Uygulama imzası eşleşmediğinden kısayol geri yüklenemedi" "Kısayol geri yüklenemedi" "Kısayol devre dışı" - - - - - - + "YÜKLEMEYİ KALDIR" + "YİNE DE AÇ" + "Zararlı uygulama tespit edildi" "%1$s uygulaması, %2$s dilimlerini göstermek istiyor" "Düzenle" diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index b028b367288159ec9d8b9c4a09d0b2f704c16336..4ed3790a7f6ea47b290aec8a9f966885cc4b4614 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -270,10 +270,8 @@ "%1$s, %2$s" "Безпечний режим" "Система Android" - - - - + "Перейти в особистий профіль" + "Перейти в робочий профіль" "Контакти" "отримувати доступ до контактів" "Надати додатку <b>%1$s</b> доступ до контактів" @@ -425,10 +423,8 @@ "Дозволяє програмі отримувати доступ до телефонних функцій пристрою. Такий дозвіл дає програмі змогу визначати номер телефону й ідентифікатори пристрою, активність виклику, а також віддалений номер, на який здійснюється виклик." "маршрутизувати виклики через систему" "Дозволяє додатку маршрутизувати виклики через систему, щоб було зручніше телефонувати." - - - - + "продовжувати виклик з іншого додатка" + "Додаток може продовжувати виклик, початий в іншому додатку." "переглядати номери телефону" "Надає додаткам доступ до номерів телефону на пристрої." "не доп.перехід пристр.в реж.сну" @@ -503,11 +499,14 @@ "Не вдалося зберегти відбиток. Видаліть наявний відбиток." "Час очікування відбитка минув. Повторіть спробу." "Дію з відбитком скасовано." - - + "Користувач скасував дію з відбитком пальця." "Забагато спроб. Спробуйте пізніше." "Забагато спроб. Сканер відбитків пальців вимкнено." "Повторіть спробу." + + + + "Відбиток пальця %d" @@ -1040,12 +1039,9 @@ "Відкрити" "Повідомлення" "Додати" - - - - - - + "Переглянути" + "Запланувати" + "Відстежити" "Закінчується пам’ять" "Деякі системні функції можуть не працювати" "Недостатньо місця для системи. Переконайтесь, що на пристрої є 250 МБ вільного місця, і повторіть спробу." @@ -1175,8 +1171,7 @@ Відкриті мережі Wi-Fi доступні "Під’єднайтеся до відкритої мережі Wi-Fi" - - + "Під’єднайтеся до мережі Wi-Fi оператора" "Під’єднання до відкритої мережі Wi-Fi" "Під’єднано до мережі Wi-Fi" "Не вдалося під’єднатися до мережі Wi-Fi" @@ -1260,13 +1255,23 @@ "Дозвіл не потрібний" "це платна послуга" "OK" - "USB-кабель, через який заряджається цей пристрій" - "USB-кабель, через який живиться під’єднаний пристрій" - "USB для перенесення файлів" - "USB для перенесення фотографій" - "USB для режиму MIDI" - "Під’єднано до аксесуара USB" + + + + + + + + + + + + + + "Торкніться, щоб переглянути більше опцій." + + "Виявлено аналоговий аксесуар для аудіо" "Під’єднаний пристрій несумісний із цим телефоном. Торкніться, щоб дізнатися більше." "Налагодження USB завершено" @@ -1711,9 +1716,6 @@ "Робоча %1$s" "2-а робота: %1$s" "3-я робота: %1$s" - "Щоб відкріпити цей екран, натисніть і втримуйте кнопки \"Назад\" та \"Огляд\"" - "Екран закріплено" - "Екран відкріплено" "PIN-код для відкріплення" "Запитувати ключ розблокування перед відкріпленням" "Запитувати пароль перед відкріпленням" @@ -1825,15 +1827,11 @@ "Усі мови" "Усі регіони" "Пошук" - - - - + "Увімкнути робочий профіль?" + "Додатки, сповіщення, дані й інші функції робочого профілю буде ввімкнено" "Увімкнути" - - - - + "Цей додаток створений для старішої версії Android і може працювати неналежним чином. Спробуйте знайти оновлення або зв’яжіться з розробником." + "Шукати оновлення" "У вас є нові повідомлення" "Щоб переглянути, відкрийте додаток для SMS" "Деякі функції можуть не працювати" @@ -1902,17 +1900,15 @@ "Голосові дзвінки з телефона заборонено" "Спливаюче вікно" "+ %1$d" - "Для цього ярлика потрібна найновіша версія додатка" + + "Не вдалося відновити ярлик, оскільки додаток не підтримує резервне копіювання та відновлення" "Не вдалося відновити ярлик, оскільки підписи додатків не збігаються" "Не вдалося відновити ярлик" "Ярлик вимкнено" - - - - - - + "ВИДАЛИТИ" + "УСЕ ОДНО ВІДКРИТИ" + "Виявлено шкідливий додаток" "%1$s хоче показати фрагменти додатка %2$s" "Редагувати" diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index c241214f97d89c4d82fb1b2b2614d15df7ea5abf..bfaaba2be7a9018f3f8ed86b08a22daa1804c0fb 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -264,10 +264,8 @@ "%1$s، %2$s" "حفاظتی وضع" "‏Android سسٹم" - - - - + "ذاتی پروفائل پر سوئچ کریں" + "دفتری پروفائل پر سوئچ کریں" "رابطے" "اپنے رابطوں تک رسائی حاصل کریں" "‏<b>%1$s</b> کو اپنے رابطوں تک رسائی کی اجازت دیں" @@ -419,10 +417,8 @@ "‏ایپ کو آلے کی فون والی خصوصیات تک رسائی حاصل کرنے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو فون نمبر اور آلے کے IDs کا تعین کرنے، آیا کوئی کال فعال ہے، اور کال کے ذریعہ مربوط ریموٹ نمبر کا تعین کرنے دیتی ہے۔" "سسٹم کے ذریعہ کالز روٹ کریں" "کالںگ کا تجربہ بہتر بنانے کے لیے سسٹم کے ذریعہ ایپ کو کالز روٹ کرنے کی اجازت دیتا ہے۔" - - - - + "دوسری ایپ کی کال جاری رکھیں" + "ایپ کو دوسری ایپ میں شروع کردہ کال کو جاری رکھنے کی اجازت ملتی ہے۔" "فون نمبرز پڑھیں" "ایپ کو آلہ کے فون نمبرز تک رسائی کرنے دیتا ہے۔" "ٹیبلیٹ کو سلیپ وضع میں جانے سے روکیں" @@ -497,11 +493,14 @@ "فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔" "فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔" "فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔" - - + "صارف نے فنگر پرنٹ کی کارروائی منسوخ کر دی۔" "کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔" "کافی زیادہ کوششیں۔ فنگر پرنٹ سینسر غیر فعال ہو گیا۔" "دوبارہ کوشش کریں۔" + + + + "انگلی %d" @@ -1000,12 +999,9 @@ "کھولیں" "پیغام" "شامل کریں" - - - - - - + "دیکھیں" + "شیڈول کریں" + "پتہ لگائیں" "اسٹوریج کی جگہ ختم ہو رہی ہے" "ممکن ہے سسٹم کے کچھ فنکشنز کام نہ کریں" "‏سسٹم کیلئے کافی اسٹوریج نہیں ہے۔ اس بات کو یقینی بنائیں کہ آپ کے پاس 250MB خالی جگہ ہے اور دوبارہ شروع کریں۔" @@ -1131,8 +1127,7 @@ ‏عوامی Wi-Fi نیٹ ورک دستیاب ہے "‏عوامی Wi‑Fi نیٹ ورک سے منسلک ہوں" - - + "‏کیریئر Wi‑Fi نیٹ ورک سے منسلک ہوں" "‏عوامی Wi‑Fi نیٹ ورک سے منسلک ہو رہا ہے" "‏عوامی Wi‑Fi نیٹ ورک سے منسلک ہو گيا" "‏Wi‑Fi نیٹ ورک سے منسلک نہیں ہو سکا" @@ -1217,13 +1212,23 @@ "کوئی اجازتیں درکار نہیں ہیں" "اس میں آپ کا پیسہ خرچ ہو سکتا ہے" "ٹھیک ہے" - "‏USB اس آلے کو چارج کر رہی ہے" - "‏منسلکہ آلے کو USB پاور سپلائی کر رہی ہے" - "‏فائل کی منتقلی کیلئے USB" - "‏تصویر کی منتقلی کیلئے USB" - "‏MIDI کیلئے USB" - "‏ایک USB لوازم سے مربوط ہے" + + + + + + + + + + + + + + "مزید اختیارات کیلئے تھپتھپائیں۔" + + "اینالاگ آڈیو کے لوازم کا پتہ چلا" "منسلک آلہ اس فون کے موافق نہیں ہے۔ مزید جاننے کے لیے تھپتھپائیں۔" "‏USB ڈیبگ کرنا مربوط ہو گیا" @@ -1662,9 +1667,6 @@ "دفتر %1$s" "دوسرا کام %1$s" "تیسرا کام %1$s" - "اس اسکرین سے پن ہٹانے کیلئے، ٹچ کریں اور مجموعی جائزہ اور واپس جائیں بٹنز کو دبائے رکھیں" - "اسکرین کو پن کر دیا گیا" - "اسکرین کا پن ہٹا دیا گیا" "‏پن ہٹانے سے پہلے PIN طلب کریں" "پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں" "پن ہٹانے سے پہلے پاس ورڈ طلب کریں" @@ -1758,15 +1760,11 @@ "سبھی زبانیں" "تمام علاقے" "تلاش" - - - - + "دفتری پروفائل آن کریں؟" + "آپ کی دفتری ایپس، اطلاعات، ڈیٹا اور دفتری پروفائل کی دیگر خصوصیات آن کر دی جائیں گی" "آن کریں" - - - - + "‏یہ ایپ Android کے پرانے ورژن کے لئے بنائی گئی ہے اور ہو سکتا ہے صحیح طور پر کام نہ کرے۔ اپ ڈیٹس چیک کر کے آزمائیں یا ڈیولپر سے رابطہ کریں۔" + "اپ ڈیٹ چیک کریں" "آپ کے پاس نئے پیغامات ہیں" "‏دیکھنے کیلئے SMS ایپ کھولیں" "کچھ فعالیت محدود ہو سکتی ہے" @@ -1833,17 +1831,15 @@ "آواز کیلئے فون کو اجازت نہیں ہے" "پاپ اپ ونڈو" "‎‎‎‎‎+ %1$d‎‎" - "اس شارٹ کٹ کیلئے جدید ترین ایپ درکار ہے" + + "شارٹ کٹ کو بحال نہیں کیا جا سکا، کیونکہ ایپ بیک اپ اور بحالی کو سپورٹ نہیں کرتی ہے" "ایپ دستخط غیر مماثل ہونے کی وجہ سے شارٹ کٹ کو بحال نہیں کیا جا سکا" "شارٹ کٹ کو بحال نہیں کیا جا سکا" "شارٹ کٹ غیر فعال ہے" - - - - - - + "اَن انسٹال کریں" + "بہر صورت کھولیں" + "ضرر رساں ایپ کا پتہ چلا" "%1$s %2$s کے سلائسز دکھانا چاہتی ہے" "ترمیم کریں" diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 2329a415a297bb3d6076c1da30cad4911c08d687..c9076ca57fe6c0bd3ac9e62776d12e046f847ce7 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Xavfsiz usul" "Android tizimi" - - - - + "Shaxsiy profilga almashtirish" + "Ishchi profilga almashtirish" "Kontaktlar" "kontaktlarga kirish" "<b>%1$s</b> uchun kontaktlaringizga ruxsat berish" @@ -419,10 +417,8 @@ "Ilovaga qurilmangizdagi telefon xususiyatlariga kirishga ruxsat beradi. Bu ruxsat ilovaga telefon raqami va qurilma nomlari, qo‘ng‘iroq faol yoki faolsizligi va masofadagi raqam qo‘ng‘rioq orqali bog‘langanligini aniqlashga imkon beradi." "chaqiruvlarni tizim orqali yo‘naltirish" "Ilova aloqa sifatini yaxshilash maqsadida chaqiruvlarni tizim orqali yo‘naltirishi mumkin." - - - - + "chaqiruvni boshqa ilovada davom ettirish" + "Ilovaga boshqa ilovada boshlangan chaqiruvni davom ettirish imkon beradi" "telefon raqamlarini o‘qish" "Ilovaga qurilmaning telefon raqamlaridan foydalanishiga ruxsat beradi." "planshetni uyquga ketishiga yo‘l qo‘ymaslik" @@ -497,11 +493,14 @@ "Barmoq izini saqlab bo‘lmadi. Mavjud barmoq izlaridan birini o‘chirib tashlang." "Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring." "Barmoq izi tekshiruvi bekor qilindi." - - + "Barmoq izi amali foydalanuvchi tomonidan bekor qilindi" "Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring." "Urinishlar soni ko‘payib ketdi. Barmoq izi skaneri bloklandi." "Qayta urinib ko‘ring." + + + + "Barmoq izi %d" @@ -1000,12 +999,9 @@ "Ochish" "Xabar" "Qo‘shish" - - - - - - + "Ochish" + "Jadval" + "Trek" "Xotirada bo‘sh joy tugamoqda" "Ba‘zi tizim funksiyalari ishlamasligi mumkin" "Tizim uchun xotirada joy yetarli emas. Avval 250 megabayt joy bo‘shatib, keyin qurilmani o‘chirib yoqing." @@ -1131,8 +1127,7 @@ Ochiq Wi-Fi tarmog‘i aniqlandi "Ochiq Wi‑Fi tarmoqqa ulaning" - - + "Aloqa operatori Wi-Fi tarmog‘iga ulanish" "Ochiq Wi‑Fi tarmoqqa ulanilmoqda" "Wi‑Fi tarmoqqa ulanildi" "Wi-Fi tarmoqqa ulanib bo‘lmadi" @@ -1217,13 +1212,23 @@ "Hech qanday ruxsat talab qilinmaydi" "buning uchun sizdan haq olinishi mumkin" "OK" - "USB orqali quvvatlash" - "USB orqali ulangan qurilma quvvatlanmoqda" - "USB orqali fayl o‘tkazish" - "USB orqali surat o‘tkazish" - "USB orqali MIDI" - "USB jihozga ulangan" + + + + + + + + + + + + + + "Boshqa parametrlarini ko‘rish uchun bosing." + + "Analogli audio uskuna aniqlandi" "Biriktirilgan qurilma mazkur telefon bilan mos emas. Batafsil axborot olish uchun bu yerga bosing." "USB orqali nosozliklarni tuzatish" @@ -1662,9 +1667,6 @@ "Ish %1$s" "2-ishxona %1$s" "3-ishxona %1$s" - "Bu ekrandan chiqish uchun Orqaga va Menyu tugmalarini bosib turing" - "Ekran qadab qo‘yildi" - "Ekran bo‘shatildi" "Yechishda PIN-kod so‘ralsin" "Yechishdan oldin grafik kalit so‘ralsin" "Bo‘shatishdan oldin parol so‘ralsin" @@ -1709,7 +1711,7 @@ "%1$s gacha" "%1$s gacha (keyingi signal)" - "O‘chirib qo‘ymagunimcha" + "O‘chirmaguningizcha" "“Bezovta qilinmasin” rejimi o‘chirilmaguncha" "%1$s / %2$s" "Yig‘ish" @@ -1758,15 +1760,11 @@ "Barcha tillar" "Barcha hududlar" "Qidiruv" - - - - + "Ishchi profil yoqilsinmi?" + "Ishchi ilovalar, bildirishnomalar, ma’lumotlar va boshqa ishchi profil imkoniyatlari yoqiladi" "Yoqish" - - - - + "Bu ilova eskiroq Android versiyalariga chiqarilgan va xato ishlashi mumkin. Yangilanishlarini tekshiring yoki dasturchi bilan bog‘laning." + "Yangilanish borligini tekshirish" "Sizga yangi SMS keldi" "Ko‘rish uchun SMS ilovasini oching" "Ba’zi funksiyalar cheklanishi m-n" @@ -1833,17 +1831,15 @@ "Ovoz uchun telefon taqiqlangan" "Qalqib chiquvchi oyna" "+ %1$d" - "Bu yorliq uchun eng oxirgi versiyadagi ilova zarur" + + "Ilovada zaxiralash va tiklash ishlamagani uchun yorliq tiklanmadi" "Ilova imzosi mos kelmagani uchun yorliq tiklanmadi" "Yorliq tiklanmadi" "Yorliq faolsizlantirildi" - - - - - - + "O‘CHIRIB TASHLASH" + "BARIBIR OCHILSIN" + "Zararli ilova aniqlandi" "%1$s ilovasi %2$s ilovasidan fragmentlar ko‘rsatish uchun ruxsat so‘ramoqda" "Tahrirlash" diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 2b4f6cb66482afb9a484149c1af7078ee315a91b..b781f3e8f34892836ca67de28816dbb2b254aa69 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -264,10 +264,8 @@ "%1$s%2$s" "安全模式" "Android 系統" - - - - + "切換至個人設定檔" + "切換至 Work 設定檔" "聯絡人" "存取你的聯絡人" "允許「%1$s」存取你的聯絡人" @@ -419,10 +417,8 @@ "允許應用程式使用裝置的電話功能。這項權限可讓應用程式判讀手機號碼和裝置 ID、是否正在通話中,以及所撥打的對方號碼。" "透過系統接通來電" "允許應用程式透過系統接通來電,以改善通話品質。" - - - - + "繼續進行來自其他應用程式的通話" + "允許應用程式繼續進行在其他應用程式中發起的通話。" "讀取電話號碼" "允許應用程式存取裝置上的電話號碼資料。" "防止平板電腦進入休眠狀態" @@ -497,11 +493,14 @@ "無法儲存指紋,請先移除現有指紋。" "指紋處理作業逾時,請再試一次。" "指紋作業已取消。" - - + "使用者已取消指紋驗證作業。" "嘗試次數過多,請稍後再試。" "嘗試次數過多,指紋感應器已停用。" "請再試一次。" + + + + "手指 %d" @@ -1000,12 +999,9 @@ "開啟" "訊息" "新增" - - - - - - + "查看" + "時間表" + "追蹤" "儲存空間即將用盡" "部分系統功能可能無法運作" "系統儲存空間不足。請確定你已釋出 250MB 的可用空間,然後重新啟動。" @@ -1131,8 +1127,7 @@ 有多個可用的開放 Wi-Fi 網路 "連線至開放的 Wi‑Fi 網路" - - + "連上電信業者的 Wi‑Fi 網路" "正在連線至開放的 Wi‑Fi 網路" "已連線至 Wi-Fi 網路" "無法連線至 Wi‑Fi 網路" @@ -1216,13 +1211,23 @@ "無須許可" "這可能需要付費" "確定" - "正在透過 USB 為這個裝置充電" - "正在透過 USB 為連接的裝置供電" - "USB 檔案傳輸" - "USB 相片傳輸" - "USB MIDI" - "已連接 USB 配件" + + + + + + + + + + + + + + "輕觸即可查看更多選項。" + + "偵測到類比音訊配件" "此外接裝置與這支手機不相容。輕觸即可瞭解詳情。" "已連接 USB 偵錯工具" @@ -1661,9 +1666,6 @@ "公司%1$s" "第 2 項工作:%1$s" "第 3 項工作:%1$s" - "如要取消固定這個畫面,請按住「返回」按鈕和「總覽」按鈕" - "已固定螢幕" - "已取消固定螢幕" "取消固定時必須輸入 PIN" "取消固定時必須畫出解鎖圖案" "取消固定時必須輸入密碼" @@ -1757,15 +1759,11 @@ "所有語言" "所有地區" "搜尋" - - - - + "要開啟 Work 設定檔嗎?" + "系統將開啟你的辦公應用程式、通知、資料和其他 Work 設定檔功能" "開啟" - - - - + "這個應用程式是專為舊版 Android 所打造,因此可能無法正常運作。請嘗試檢查更新,或是與開發人員聯絡。" + "檢查更新" "你有新訊息" "開啟簡訊應用程式來查看內容" "部分功能可能受到鎖定" @@ -1832,17 +1830,15 @@ "手機不支援語音" "彈出式視窗" "+ %1$d" - "你必須擁有最新版的應用程式,才能使用這個捷徑" + + "應用程式不支援備份與還原功能,因此無法還原捷徑" "應用程式簽署不相符,因此無法還原捷徑" "無法還原捷徑" "捷徑已停用" - - - - - - + "解除安裝" + "仍要開啟" + "偵測到有害應用程式" "「%1$s」想要顯示「%2$s」的區塊" "編輯" diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 3f5d2b143170e6597ea32094e755b185f450b104..9c48610337492bc2d9f74586801745af35360be8 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -264,10 +264,8 @@ "%1$s, %2$s" "Imodi ephephile" "Uhlelo lwe-Android" - - - - + "Shintshela kuphrofayela yomuntu siqu" + "Shintshela kuphrofayela yomsebenzi" "Oxhumana nabo" "finyelela koxhumana nabo" "Vumela i-<b>%1$s</b> ukuthi ithole ukufinyelela koxhumana nabo" @@ -419,10 +417,8 @@ "Ivumela uhlelo lokusebenza ukufinyelela izici zefoni zedivayisi. Le mvume ivumela uhlelo lokusebenza ukucacisa inombolo yefoni nobunikazi bedivayisi, ukuthi noma ikholi iyasebenza, futhi nenombolo yesilawuli kude zixhunywe ngekholi." "yanza imizila yamakholi ngesistimu" "Ivumela uhlelo lokusebenza ukwenza imizila yamakholi ngesistimu ukuze ithuthukise umuzwa wokushaya." - - - - + "qhuba ikholi kusukela kolunye uhlelo lokusebenza" + "Ivumela uhlelo lokusebenza ukuze luqhube ikholi eqalwe kolunye uhlelo lokusebenza." "funda izinombolo zefoni" "Ivumela uhlelo lokusebenza ukufinyelela izinombolo zefoni zedivayisi." "gwema ithebhulethi ukuba ingalali" @@ -497,11 +493,14 @@ "Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona." "Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi" "Ukusebenza kwezingxivizo zeminwe kukhanseliwe." - - + "Umsebenzi wesigxivizo somunwe sikhanselwe umsebenzisi." "Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi." "Imizamo eminingi kakhulu. Inzwa yezigxivizo zeminwe ikhutshaziwe." "Zama futhi." + + + + "Umunwe ongu-%d" @@ -1000,12 +999,9 @@ "Vula" "Umlayezo" "Engeza" - - - - - - + "Buka" + "Ishejuli" + "Landelela" "Isikhala sokulondoloza siyaphela" "Eminye imisebenzi yohlelo ingahle ingasebenzi" "Akusona isitoreji esanele sesistimu. Qiniseka ukuthi unesikhala esikhululekile esingu-250MB uphinde uqalise kabusha." @@ -1131,8 +1127,7 @@ Vula amanethiwekhi we-Wi-Fi atholakalayo "Xhuma kunethiwekhi evulekile ye-Wi‑Fi" - - + "Xhumeka kunethiwekhi yenkampani yenethiwekhi ye-Wi-Fi" "Ixhuma kunethiwekhi evulekile ye-Wi‑Fi" "Kuxhumeke kunethiwekhi ye-Wi‑Fi" "Ayikwazanga ukuxhumeka kunethiwekhi ye-Wi-Fi" @@ -1216,13 +1211,23 @@ "Ayikho imvume edingekayo" "lokhu kungakudlela imali" "KULUNGILE" - "I-USB ishaja le divayisi" - "I-USB inikeza amandla kudivayisi enamathiselwe" - "I-USB yokudluliswa kwefayela" - "I-USB yokudluliswa kwesithombe" - "I-USB ye-MIDI" - "Ixhunywe ku-accessory ye-USB" + + + + + + + + + + + + + + "Thepha ngezinketho eziningi." + + "Kutholwe isisetshenziswa se-analog yomsindo" "Idivayisi enamathiselwe kwi-imeyili ayihambisani nale foni. Thepha ukuze ufunde kabanzi." "Ukulungisa iphutha le-USB kuxhunyiwe" @@ -1661,9 +1666,6 @@ "Umsebenzi %1$s" "Umsebenzi wesibili %1$s" "Umsebenzi wesithathu %1$s" - "Ukuze ususe ukuphina lesi sikrini, thinta uphinde ubambe izinkinobho zokubuyela emuva nezokubuka konke" - "Isikrini siphiniwe" - "Isikrini sisuswe ukuphina" "Cela iphinikhodi ngaphambi kokuphina" "Cela iphethini yokuvula ngaphambi kokususa ukuphina" "Cela iphasiwedi ngaphambi kokususa ukuphina" @@ -1757,15 +1759,11 @@ "Zonke izilimi" "Zonke izifunda" "Sesha" - - - - + "Vula iphrofayela yomsebenzi?" + "Izinhlelo zakho zokusebenza zomsebenzi, izaziso, idatha, nezinye izici zephrofayela yomsebenzi kuzovulwa" "Vula" - - - - + "Lolu hlelo lokusebenza belakhelwe inguqulo endala ye-Android futhi kungenzeka lungasebenzi kahle. Zama ukuhlolela izibuyekezo, noma uxhumane nonjiniyela." + "Hlola izibuyekezo" "Unemilayezo emisha" "Vula uhlelo lokusebenza lwe-SMS ukuze ubuke" "Okunye ukusebenza kungakhawulelwe" @@ -1832,17 +1830,15 @@ "Ifoni ayivunyelwe izwi" "Iwindi lesigelekeqe" "+ %1$d" - "Lesi sinqamuleli sidinga uhlelo lokusebenza lwakamuva" + + "Ayikwazanga ukubuyisa isinqamuleli ngoba uhlelo lokusebenza alusekeli isipele nokubuyisa" "Ayikwazanga ukubuyisa isinqamuleli ngoba isignisha yohlelo lokusebenza ayifani" "Ayikwazanga ukubuyisa isinqamuleli" "Isinqamuleli sikhutshaziwe" - - - - - - + "KHIPHA" + "VULA NOMA KUNJALO" + "Uhlelo lokusebenza oluyingozi lutholakele" "I-%1$s ifuna ukubonisa izingcezu ze-%2$s" "Hlela" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 5184dda702527960513e73314bbcfc45d04d12ce..005d07dc008a825980e09af03946bdfa384c4a28 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3036,6 +3036,28 @@ + + + + + + @@ -7881,6 +7903,23 @@ + + + + + + + + @@ -8773,6 +8812,16 @@ + + + + + + + + + + diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index a22ca8726dcae8014254301e700a1d1fcda02b8b..c8032a276659bcd260a5c2cf531b616a1bb0d293 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -363,6 +363,23 @@ eth\\d + + + + + + + com.android.settings/.wifi.tether.TetherService - - 1 - - @null + @null @@ -1431,7 +1442,7 @@ permission. [This is only used if config_enableUpdateableTimeZoneRules and config_timeZoneRulesUpdateTrackingEnabled are true.] --> - com.android.timezone.updater + com.android.timezone.updater - + false + + com.android.phone + + + + true + + + true @@ -3249,7 +3277,7 @@ - com.android.systemui/com.android.systemui.media.MediaProjectionPermissionActivity + com.android.systemui/com.android.systemui.media.MediaProjectionPermissionActivity 2dp @@ -3266,4 +3294,13 @@ android.ext.services true + + true + + + com.android.phone + + + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 30586d17cf3c7e8ed08db9c0098d2a916bdf6829..93f22f25d7d3e375a8e5f8b040a5866a0ad7a5bc 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2866,6 +2866,9 @@ + + + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 3cde765e04cbbe00e57e09fafa4e1ae2d85f9cdc..ec81df7b89e214a0fc5b057d5a45cfdcc586640b 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1351,6 +1351,10 @@ Too many attempts. Fingerprint sensor disabled. Try again. + + No fingerprints enrolled. + + This device does not have a fingerprint sensor Finger %d @@ -3222,19 +3226,23 @@ OK - USB charging this device + Charging this device via USB - USB supplying power to attached device + Charging connected device via USB - USB for file transfer + USB file transfer turned on - USB for photo transfer + PTP via USB turned on + + USB tethering turned on - USB for MIDI + MIDI via USB turned on - Connected to a USB accessory + USB accessory mode turned on Tap for more options. + + Charging connected device. Tap for more options. Analog audio accessory detected @@ -4419,15 +4427,6 @@ sans-serif-medium - - To unpin this screen, touch & hold Back and Overview - buttons - - - Screen pinned - - Screen unpinned - Ask for PIN before unpinning @@ -4811,7 +4810,7 @@ A toast message shown when an app shortcut that was restored from a previous device is clicked, but it cannot be started because the shortcut was created by a newer version of the app. --> - This shortcut requires latest app + App version downgraded, or isn\u2019t compatible with this shortcut @@ -2700,9 +2705,6 @@ - - - @@ -3101,6 +3103,7 @@ + @@ -3150,6 +3153,7 @@ + @@ -3240,4 +3244,6 @@ + + diff --git a/core/res/res/xml/autofill_compat_accessibility_service.xml b/core/res/res/xml/autofill_compat_accessibility_service.xml new file mode 100644 index 0000000000000000000000000000000000000000..327afbee65c997806c672c6a735b3918b82c06c9 --- /dev/null +++ b/core/res/res/xml/autofill_compat_accessibility_service.xml @@ -0,0 +1,22 @@ + + + + + diff --git a/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java b/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java new file mode 100644 index 0000000000000000000000000000000000000000..5989da7af6552d8263bc580ae591dc895e3789e8 --- /dev/null +++ b/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.os; + +import static android.os.FileUtils.copyInternalSendfile; +import static android.os.FileUtils.copyInternalSplice; +import static android.os.FileUtils.copyInternalUserspace; + +import android.os.FileUtils.MemoryPipe; + +import com.google.caliper.BeforeExperiment; +import com.google.caliper.Param; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +public class FileUtilsBenchmark { + @Param({"32", "32000", "32000000"}) + private int mSize; + + private File mSrc; + private File mDest; + + private byte[] mData; + + @BeforeExperiment + protected void setUp() throws Exception { + mSrc = new File("/data/local/tmp/src"); + mDest = new File("/data/local/tmp/dest"); + + mData = new byte[mSize]; + + try (FileOutputStream os = new FileOutputStream(mSrc)) { + os.write(mData); + } + } + + public void timeRegularUserspace(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + try (FileInputStream in = new FileInputStream(mSrc); + FileOutputStream out = new FileOutputStream(mDest)) { + copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + } + } + } + + public void timeRegularSendfile(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + try (FileInputStream in = new FileInputStream(mSrc); + FileOutputStream out = new FileOutputStream(mDest)) { + copyInternalSendfile(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + } + } + } + + public void timePipeSourceUserspace(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + try (MemoryPipe in = MemoryPipe.createSource(mData); + FileOutputStream out = new FileOutputStream(mDest)) { + copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + } + } + } + + public void timePipeSourceSplice(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + try (MemoryPipe in = MemoryPipe.createSource(mData); + FileOutputStream out = new FileOutputStream(mDest)) { + copyInternalSplice(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + } + } + } + + public void timePipeSinkUserspace(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + try (FileInputStream in = new FileInputStream(mSrc); + MemoryPipe out = MemoryPipe.createSink(mData)) { + copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + } + } + } + + public void timePipeSinkSplice(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + try (FileInputStream in = new FileInputStream(mSrc); + MemoryPipe out = MemoryPipe.createSink(mData)) { + copyInternalSplice(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + } + } + } +} diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk index 66731df3f1b9c2773019b0f6a6201c0b216b86db..2ea1b46ad208c336a4bc032a3b4bb35c81bee699 100644 --- a/core/tests/coretests/Android.mk +++ b/core/tests/coretests/Android.mk @@ -53,6 +53,7 @@ LOCAL_JAVA_LIBRARIES := \ android.test.base \ android.test.mock \ framework-oahl-backward-compatibility \ + framework-atb-backward-compatibility \ LOCAL_PACKAGE_NAME := FrameworksCoreTests LOCAL_COMPATIBILITY_SUITE := device-tests diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index e4de5263bb7cf10d20bfa11297bac138b142dddc..77aaa2d7f9eaa0da59559fd12cce87924da7280f 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -389,8 +389,8 @@ public class TransactionParcelTests { Bundle bundle, IInstrumentationWatcher iInstrumentationWatcher, IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1, boolean b2, boolean b3, Configuration configuration, - CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1) - throws RemoteException { + CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1, + boolean autofillCompatEnabled) throws RemoteException { } @Override diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..dce22ce6a6f28ea05f4a4aa57a0497d4743a9086 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.content.pm; + +import static android.content.pm.PackageBuilder.builder; +import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; + +import android.os.Build; +import android.support.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test for {@link AndroidTestBaseUpdater} + */ +@SmallTest +@RunWith(OptionalClassRunner.class) +@OptionalClassRunner.OptionalClass("android.content.pm.AndroidTestBaseUpdater") +public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_O() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O); + + // Should add org.apache.http.legacy. + PackageBuilder after = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .requiredLibraries(ANDROID_TEST_BASE); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_not_empty_usesLibraries() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .requiredLibraries(OTHER_LIBRARY); + + // The org.apache.http.legacy jar should be added at the start of the list because it + // is not on the bootclasspath and the package targets pre-P. + PackageBuilder after = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .requiredLibraries(ANDROID_TEST_BASE, OTHER_LIBRARY); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesLibraries() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .requiredLibraries(ANDROID_TEST_BASE); + + // No change is required because although org.apache.http.legacy has been removed from + // the bootclasspath the package explicitly requests it. + checkBackwardsCompatibility(before, before); + } + + @Test + public void targeted_at_O_in_usesOptionalLibraries() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .optionalLibraries(ANDROID_TEST_BASE); + + // No change is required because although org.apache.http.legacy has been removed from + // the bootclasspath the package explicitly requests it. + checkBackwardsCompatibility(before, before); + } + + @Test + public void in_usesLibraries() { + PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE); + + // No change is required because the package explicitly requests org.apache.http.legacy + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, before); + } + + @Test + public void in_usesOptionalLibraries() { + PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE); + + // No change is required because the package explicitly requests org.apache.http.legacy + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, before); + } + + private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { + checkBackwardsCompatibility(before, after, AndroidTestBaseUpdater::new); + } +} diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java index a305261890f45ddaeee976af21def74d93015448..866de93c07fe8134a2c2968437b1da3eab26d060 100644 --- a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java +++ b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java @@ -38,7 +38,7 @@ public class AndroidTestRunnerSplitUpdaterTest extends PackageSharedLibraryUpdat PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_RUNNER); PackageBuilder after = builder() - .optionalLibraries(ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK); + .optionalLibraries(ANDROID_TEST_MOCK, ANDROID_TEST_RUNNER); checkBackwardsCompatibility(before, after); } diff --git a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java index b26fc48d8d5b1087c4e9e549e62dda612b64577e..c64d5202e1fd23bc89bb3c3beef78ec41ef76729 100644 --- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java +++ b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java @@ -17,10 +17,12 @@ package android.content.pm; import static android.content.pm.PackageBuilder.builder; +import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK; import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; +import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary; import android.os.Build; import android.support.test.filters.SmallTest; @@ -55,9 +57,20 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsOAHL()); } + /** + * Detect when the android.test.base is not on the bootclasspath. + * + *

    This test will be ignored when org.apache.http.legacy is not on the bootclasspath and + * succeed otherwise. This allows a developer to ensure that the tests are being + */ + @Test + public void detectWhenATBisOnBCP() { + Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsATB()); + } + /** * Ensures that the {@link PackageBackwardCompatibility} uses {@link OrgApacheHttpLegacyUpdater} - * when necessary. + * and {@link AndroidTestBaseUpdater} when necessary. * *

    More comprehensive tests for that class can be found in * {@link OrgApacheHttpLegacyUpdaterTest}. @@ -68,6 +81,9 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate .targetSdkVersion(Build.VERSION_CODES.O); List expected = new ArrayList<>(); + if (!PackageBackwardCompatibility.bootClassPathContainsATB()) { + expected.add(ANDROID_TEST_BASE); + } if (!PackageBackwardCompatibility.bootClassPathContainsOAHL()) { expected.add(ORG_APACHE_HTTP_LEGACY); } @@ -103,6 +119,30 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate checkBackwardsCompatibility(before, after); } + /** + * Ensures that the {@link PackageBackwardCompatibility} uses + * {@link RemoveUnnecessaryAndroidTestBaseLibrary} + * when necessary. + * + *

    More comprehensive tests for that class can be found in + * {@link RemoveUnnecessaryAndroidTestBaseLibraryTest}. + */ + @Test + public void android_test_base_in_usesLibraries() { + Assume.assumeTrue("Test requires that " + + ANDROID_TEST_BASE + " is on the bootclasspath", + PackageBackwardCompatibility.bootClassPathContainsATB()); + + PackageBuilder before = builder() + .requiredLibraries(ANDROID_TEST_BASE); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + PackageBuilder after = builder(); + + checkBackwardsCompatibility(before, after); + } + /** * Ensures that the {@link PackageBackwardCompatibility} uses a * {@link PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater}. @@ -114,8 +154,15 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate public void android_test_runner_in_usesLibraries() { PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_RUNNER); + List expected = new ArrayList<>(); + if (!PackageBackwardCompatibility.bootClassPathContainsATB()) { + expected.add(ANDROID_TEST_BASE); + } + expected.add(ANDROID_TEST_MOCK); + expected.add(ANDROID_TEST_RUNNER); + PackageBuilder after = builder() - .requiredLibraries(ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK); + .requiredLibraries(expected); checkBackwardsCompatibility(before, after); } diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3dba4406de475bc94bec773d67ab2a8459bbb209 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.content.pm; + +import static android.content.pm.PackageBuilder.builder; +import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; + +import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary; +import android.os.Build; +import android.support.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link RemoveUnnecessaryAndroidTestBaseLibrary} + */ +@SmallTest +@RunWith(JUnit4.class) +public class RemoveUnnecessaryAndroidTestBaseLibraryTest + extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_O() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O); + + // No change required. + checkBackwardsCompatibility(before, before); + } + + @Test + public void targeted_at_O_not_empty_usesLibraries() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .requiredLibraries(OTHER_LIBRARY); + + // No change required. + checkBackwardsCompatibility(before, before); + } + + @Test + public void targeted_at_O_in_usesLibraries() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .requiredLibraries(ANDROID_TEST_BASE); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + PackageBuilder after = builder() + .targetSdkVersion(Build.VERSION_CODES.O); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesOptionalLibraries() { + PackageBuilder before = builder() + .targetSdkVersion(Build.VERSION_CODES.O) + .optionalLibraries(ANDROID_TEST_BASE); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + PackageBuilder after = builder() + .targetSdkVersion(Build.VERSION_CODES.O); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + PackageBuilder after = builder(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + PackageBuilder after = builder(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_bothLibraries() { + PackageBuilder before = builder() + .requiredLibraries(ANDROID_TEST_BASE) + .optionalLibraries(ANDROID_TEST_BASE); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + PackageBuilder after = builder(); + + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { + // TODO(b/72538146) - Cannot use constructor reference here because it is also used in + // PackageBackwardCompatibility and that seems to create a package-private lambda in + // android.content.pm which this then tries to reuse but fails because it cannot access + // package-private classes/members because the test is loaded by a different ClassLoader + // than the lambda. + checkBackwardsCompatibility(before, after, + () -> new RemoveUnnecessaryAndroidTestBaseLibrary()); + } + +} diff --git a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f90ae340b2e93acf153559e3cad366033a3830bd --- /dev/null +++ b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.display; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.os.Parcel; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.LocalDate; +import java.util.Arrays; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AmbientBrightnessDayStatsTest { + + private static final LocalDate LOCAL_DATE = LocalDate.now(); + private static final float[] BUCKET_BOUNDARIES = {0, 1, 10, 100}; + private static final float[] STATS = {1.3f, 2.6f, 5.8f, 10}; + + @Test + public void testParamsMustNotBeNull() { + assertThrows(NullPointerException.class, + () -> new AmbientBrightnessDayStats(null, BUCKET_BOUNDARIES)); + + assertThrows(NullPointerException.class, + () -> new AmbientBrightnessDayStats(LOCAL_DATE, null)); + + assertThrows(NullPointerException.class, + () -> new AmbientBrightnessDayStats(null, BUCKET_BOUNDARIES, STATS)); + + assertThrows(NullPointerException.class, + () -> new AmbientBrightnessDayStats(LOCAL_DATE, null, STATS)); + } + + @Test(expected = IllegalArgumentException.class) + public void testBucketBoundariesMustNotBeEmpty() { + new AmbientBrightnessDayStats(LocalDate.now(), new float[]{}); + } + + @Test(expected = IllegalArgumentException.class) + public void testStatsAndBoundariesMustHaveSameLength() { + float[] stats = Arrays.copyOf(STATS, STATS.length + 1); + stats[stats.length - 1] = 0; + new AmbientBrightnessDayStats(LOCAL_DATE, BUCKET_BOUNDARIES, stats); + } + + @Test + public void testAmbientBrightnessDayStatsAdd() { + AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES); + dayStats.log(0, 1); + dayStats.log(0.5f, 1.5f); + dayStats.log(50, 12.5f); + dayStats.log(2000, 1.24f); + dayStats.log(-10, 0.5f); + assertEquals(4, dayStats.getStats().length); + assertEquals(2.5f, dayStats.getStats()[0], 0); + assertEquals(0, dayStats.getStats()[1], 0); + assertEquals(12.5f, dayStats.getStats()[2], 0); + assertEquals(1.24f, dayStats.getStats()[3], 0); + } + + @Test + public void testGetters() { + AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES, STATS); + assertEquals(LOCAL_DATE, dayStats.getLocalDate()); + assertArrayEquals(BUCKET_BOUNDARIES, dayStats.getBucketBoundaries(), 0); + assertArrayEquals(STATS, dayStats.getStats(), 0); + } + + @Test + public void testParcelUnparcelAmbientBrightnessDayStats() { + LocalDate today = LocalDate.now(); + AmbientBrightnessDayStats stats = new AmbientBrightnessDayStats(today, + new float[]{0, 1, 10, 100}, new float[]{1.3f, 2.6f, 5.8f, 10}); + // Parcel the data + Parcel parcel = Parcel.obtain(); + stats.writeToParcel(parcel, 0); + byte[] parceled = parcel.marshall(); + parcel.recycle(); + // Unparcel and check that it has not changed + parcel = Parcel.obtain(); + parcel.unmarshall(parceled, 0, parceled.length); + parcel.setDataPosition(0); + AmbientBrightnessDayStats statsAgain = AmbientBrightnessDayStats.CREATOR.createFromParcel( + parcel); + assertEquals(stats, statsAgain); + } + + @Test + public void testAmbientBrightnessDayStatsEquals() { + AmbientBrightnessDayStats emptyDayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES); + AmbientBrightnessDayStats identicalEmptyDayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES, new float[BUCKET_BOUNDARIES.length]); + assertEquals(emptyDayStats, identicalEmptyDayStats); + assertEquals(emptyDayStats.hashCode(), identicalEmptyDayStats.hashCode()); + + AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES, STATS); + AmbientBrightnessDayStats identicalDayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES, STATS); + assertEquals(dayStats, identicalDayStats); + assertEquals(dayStats.hashCode(), identicalDayStats.hashCode()); + + assertNotEquals(emptyDayStats, dayStats); + assertNotEquals(emptyDayStats.hashCode(), dayStats.hashCode()); + + AmbientBrightnessDayStats differentDateDayStats = new AmbientBrightnessDayStats( + LOCAL_DATE.plusDays(1), BUCKET_BOUNDARIES, STATS); + assertNotEquals(dayStats, differentDateDayStats); + assertNotEquals(dayStats.hashCode(), differentDateDayStats.hashCode()); + + float[] differentStats = Arrays.copyOf(STATS, STATS.length); + differentStats[differentStats.length - 1] += 5f; + AmbientBrightnessDayStats differentStatsDayStats = new AmbientBrightnessDayStats(LOCAL_DATE, + BUCKET_BOUNDARIES, differentStats); + assertNotEquals(dayStats, differentDateDayStats); + assertNotEquals(dayStats.hashCode(), differentStatsDayStats.hashCode()); + + float[] differentBucketBoundaries = Arrays.copyOf(BUCKET_BOUNDARIES, + BUCKET_BOUNDARIES.length); + differentBucketBoundaries[differentBucketBoundaries.length - 1] += 100f; + AmbientBrightnessDayStats differentBoundariesDayStats = new AmbientBrightnessDayStats( + LOCAL_DATE, differentBucketBoundaries, STATS); + assertNotEquals(dayStats, differentBoundariesDayStats); + assertNotEquals(dayStats.hashCode(), differentBoundariesDayStats.hashCode()); + } + + private interface ExceptionRunnable { + void run() throws Exception; + } + + private static void assertThrows(Class exceptionClass, + ExceptionRunnable r) { + try { + r.run(); + } catch (Throwable e) { + assertTrue("Expected exception type " + exceptionClass.getName() + " but got " + + e.getClass().getName(), exceptionClass.isAssignableFrom(e.getClass())); + return; + } + fail("Expected exception type " + exceptionClass.getName() + + ", but no exception was thrown"); + } + +} diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java index 27b7f9e185bb60290d2caca11a73e445d60d1be5..ea0347d67ad7414c64470f4400284ea1f7046258 100644 --- a/core/tests/coretests/src/android/net/UriTest.java +++ b/core/tests/coretests/src/android/net/UriTest.java @@ -192,6 +192,12 @@ public class UriTest extends TestCase { assertEquals("a:a@example.com:a@example2.com", uri.getAuthority()); assertEquals("example2.com", uri.getHost()); assertEquals(-1, uri.getPort()); + assertEquals("/path", uri.getPath()); + + uri = Uri.parse("http://a.foo.com\\.example.com/path"); + assertEquals("a.foo.com", uri.getHost()); + assertEquals(-1, uri.getPort()); + assertEquals("\\.example.com/path", uri.getPath()); } @SmallTest diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java index cd20192edfd644b7698385c61bbca8d3bc6396bc..0bc3a2d879ab532a9d3b5c95481f3b0f71599a44 100644 --- a/core/tests/coretests/src/android/os/FileUtilsTest.java +++ b/core/tests/coretests/src/android/os/FileUtilsTest.java @@ -21,16 +21,19 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.content.Context; +import android.os.FileUtils.MemoryPipe; import android.provider.DocumentsContract.Document; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import libcore.io.IoUtils; +import libcore.io.Streams; import com.google.android.collect.Sets; @@ -40,11 +43,13 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileWriter; import java.util.Arrays; import java.util.HashSet; +import java.util.Random; @RunWith(AndroidJUnit4.class) public class FileUtilsTest { @@ -56,6 +61,8 @@ public class FileUtilsTest { private File mCopyFile; private File mTarget; + private final int[] DATA_SIZES = { 32, 32_000, 32_000_000 }; + private Context getContext() { return InstrumentationRegistry.getContext(); } @@ -80,7 +87,7 @@ public class FileUtilsTest { @Test public void testCopyFile() throws Exception { - stageFile(mTestFile, TEST_DATA); + writeFile(mTestFile, TEST_DATA); assertFalse(mCopyFile.exists()); FileUtils.copyFile(mTestFile, mCopyFile); assertTrue(mCopyFile.exists()); @@ -96,6 +103,104 @@ public class FileUtilsTest { assertEquals(s, FileUtils.readTextFile(mCopyFile, 0, null)); } + @Test + public void testCopy_FileToFile() throws Exception { + for (int size : DATA_SIZES) { + final File src = new File(mTarget, "src"); + final File dest = new File(mTarget, "dest"); + + byte[] expected = new byte[size]; + byte[] actual = new byte[size]; + new Random().nextBytes(expected); + writeFile(src, expected); + + try (FileInputStream in = new FileInputStream(src); + FileOutputStream out = new FileOutputStream(dest)) { + FileUtils.copy(in, out); + } + + actual = readFile(dest); + assertArrayEquals(expected, actual); + } + } + + @Test + public void testCopy_FileToPipe() throws Exception { + for (int size : DATA_SIZES) { + final File src = new File(mTarget, "src"); + + byte[] expected = new byte[size]; + byte[] actual = new byte[size]; + new Random().nextBytes(expected); + writeFile(src, expected); + + try (FileInputStream in = new FileInputStream(src); + MemoryPipe out = MemoryPipe.createSink(actual)) { + FileUtils.copy(in.getFD(), out.getFD()); + out.join(); + } + + assertArrayEquals(expected, actual); + } + } + + @Test + public void testCopy_PipeToFile() throws Exception { + for (int size : DATA_SIZES) { + final File dest = new File(mTarget, "dest"); + + byte[] expected = new byte[size]; + byte[] actual = new byte[size]; + new Random().nextBytes(expected); + + try (MemoryPipe in = MemoryPipe.createSource(expected); + FileOutputStream out = new FileOutputStream(dest)) { + FileUtils.copy(in.getFD(), out.getFD()); + } + + actual = readFile(dest); + assertArrayEquals(expected, actual); + } + } + + @Test + public void testCopy_PipeToPipe() throws Exception { + for (int size : DATA_SIZES) { + byte[] expected = new byte[size]; + byte[] actual = new byte[size]; + new Random().nextBytes(expected); + + try (MemoryPipe in = MemoryPipe.createSource(expected); + MemoryPipe out = MemoryPipe.createSink(actual)) { + FileUtils.copy(in.getFD(), out.getFD()); + out.join(); + } + + assertArrayEquals(expected, actual); + } + } + + @Test + public void testCopy_ShortPipeToFile() throws Exception { + byte[] source = new byte[33_000_000]; + new Random().nextBytes(source); + + for (int size : DATA_SIZES) { + final File dest = new File(mTarget, "dest"); + + byte[] expected = Arrays.copyOf(source, size); + byte[] actual = new byte[size]; + + try (MemoryPipe in = MemoryPipe.createSource(source); + FileOutputStream out = new FileOutputStream(dest)) { + FileUtils.copy(in.getFD(), out.getFD(), null, null, size); + } + + actual = readFile(dest); + assertArrayEquals(expected, actual); + } + } + @Test public void testIsFilenameSafe() throws Exception { assertTrue(FileUtils.isFilenameSafe(new File("foobar"))); @@ -106,7 +211,7 @@ public class FileUtilsTest { @Test public void testReadTextFile() throws Exception { - stageFile(mTestFile, TEST_DATA); + writeFile(mTestFile, TEST_DATA); assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 0, null)); @@ -127,7 +232,7 @@ public class FileUtilsTest { @Test public void testReadTextFileWithZeroLengthFile() throws Exception { - stageFile(mTestFile, TEST_DATA); + writeFile(mTestFile, TEST_DATA); new FileOutputStream(mTestFile).close(); // Zero out the file assertEquals("", FileUtils.readTextFile(mTestFile, 0, null)); assertEquals("", FileUtils.readTextFile(mTestFile, 1, "<>")); @@ -381,12 +486,21 @@ public class FileUtilsTest { file.setLastModified(System.currentTimeMillis() - age); } - private void stageFile(File file, String data) throws Exception { - FileWriter writer = new FileWriter(file); - try { - writer.write(data, 0, data.length()); - } finally { - writer.close(); + private void writeFile(File file, String data) throws Exception { + writeFile(file, data.getBytes()); + } + + private void writeFile(File file, byte[] data) throws Exception { + try (FileOutputStream out = new FileOutputStream(file)) { + out.write(data); + } + } + + private byte[] readFile(File file) throws Exception { + try (FileInputStream in = new FileInputStream(file); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + Streams.copy(in, out); + return out.toByteArray(); } } diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 733f7a107fa872aa3ccff49a00ba6e3fe993d1cc..32d7dddc13b8569819e2b609c92d23317a81878e 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -109,12 +109,15 @@ public class SettingsBackupTest { Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS, Settings.Global.ANIMATOR_DURATION_SCALE, Settings.Global.ANOMALY_DETECTION_CONSTANTS, + Settings.Global.ANOMALY_CONFIG, + Settings.Global.ANOMALY_CONFIG_VERSION, Settings.Global.APN_DB_UPDATE_CONTENT_URL, Settings.Global.APN_DB_UPDATE_METADATA_URL, Settings.Global.APP_IDLE_CONSTANTS, Settings.Global.APP_STANDBY_ENABLED, Settings.Global.ASSISTED_GPS_ENABLED, Settings.Global.AUDIO_SAFE_VOLUME_STATE, + Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES, Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD, Settings.Global.BATTERY_DISCHARGE_THRESHOLD, Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS, @@ -193,6 +196,7 @@ public class SettingsBackupTest { Settings.Global.DEVICE_PROVISIONED, Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD, + Settings.Global.DISPLAY_PANEL_LPM, Settings.Global.DISPLAY_SCALING_FORCE, Settings.Global.DISPLAY_SIZE_FORCED, Settings.Global.DNS_RESOLVER_MAX_SAMPLES, @@ -245,6 +249,7 @@ public class SettingsBackupTest { Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL, Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL, Settings.Global.JOB_SCHEDULER_CONSTANTS, + Settings.Global.KEEP_PROFILE_IN_BACKGROUND, Settings.Global.LANG_ID_UPDATE_CONTENT_URL, Settings.Global.LANG_ID_UPDATE_METADATA_URL, Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, @@ -435,7 +440,6 @@ public class SettingsBackupTest { Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, - Settings.Global.WIFI_WAKEUP_AVAILABLE, Settings.Global.WIFI_WATCHDOG_ON, Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON, Settings.Global.WINDOW_ANIMATION_SCALE, diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java index 8a81743c81543052b29a01050630bdb39d927ace..cf41eb89ba20e052789b2b3aad0fe7b2efe407d6 100644 --- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java @@ -86,15 +86,11 @@ public class TextClassificationTest { .setSignature(signature) .build(); - // Parcel and unparcel using ParcelableWrapper. - final TextClassification.ParcelableWrapper parcelableReference = new TextClassification - .ParcelableWrapper(reference); + // Parcel and unparcel final Parcel parcel = Parcel.obtain(); - parcelableReference.writeToParcel(parcel, parcelableReference.describeContents()); + reference.writeToParcel(parcel, reference.describeContents()); parcel.setDataPosition(0); - final TextClassification result = - TextClassification.ParcelableWrapper.CREATOR.createFromParcel( - parcel).getTextClassification(); + final TextClassification result = TextClassification.CREATOR.createFromParcel(parcel); assertEquals(text, result.getText()); assertEquals(signature, result.getSignature()); diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java index a82542cd91c556f3d8293ec60ac85ee4f3f01718..d6ac8454b86b4c315084e5c3049ffcb4436dd57f 100644 --- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java @@ -68,8 +68,8 @@ public class TextLinksTest { public void testParcel() { final String fullText = "this is just a test"; final TextLinks reference = new TextLinks.Builder(fullText) - .addLink(new TextLinks.TextLink(fullText, 0, 4, getEntityScores(0.f, 0.f, 1.f))) - .addLink(new TextLinks.TextLink(fullText, 5, 12, getEntityScores(.8f, .1f, .5f))) + .addLink(0, 4, getEntityScores(0.f, 0.f, 1.f)) + .addLink(5, 12, getEntityScores(.8f, .1f, .5f)) .build(); // Parcel and unparcel. diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java index e9202361c84ac26bac6c48d44a8a855f5e53d9c4..a6ea0211fbc03cc253d86cf4a65fd1ef6e0c12fa 100644 --- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java @@ -45,15 +45,11 @@ public class TextSelectionTest { .setSignature(signature) .build(); - // Parcel and unparcel using ParcelableWrapper. - final TextSelection.ParcelableWrapper parcelableReference = new TextSelection - .ParcelableWrapper(reference); + // Parcel and unparcel final Parcel parcel = Parcel.obtain(); - parcelableReference.writeToParcel(parcel, parcelableReference.describeContents()); + reference.writeToParcel(parcel, reference.describeContents()); parcel.setDataPosition(0); - final TextSelection result = - TextSelection.ParcelableWrapper.CREATOR.createFromParcel( - parcel).getTextSelection(); + final TextSelection result = TextSelection.CREATOR.createFromParcel(parcel); assertEquals(startIndex, result.getSelectionStartIndex()); assertEquals(endIndex, result.getSelectionEndIndex()); diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index bbca12f9d457af3b3327c1cc383cf175bc7b6906..69e5670f02d58e8d9d5389f206d48a66768ff937 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -325,9 +325,9 @@ public class TextViewActivityTest { TextClassificationManager textClassificationManager = mActivity.getSystemService(TextClassificationManager.class); TextClassifier textClassifier = textClassificationManager.getTextClassifier(); - SpannableString content = new SpannableString("Call me at +19148277737"); + Spannable content = new SpannableString("Call me at +19148277737"); TextLinks links = textClassifier.generateLinks(content); - links.apply(content, null); + links.apply(content, TextLinks.APPLY_STRATEGY_REPLACE, null); mActivityRule.runOnUiThread(() -> { textView.setText(content); diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk index 99bcd6c62b56c8639583642dc7bc3e395ab0bd4f..a6c537373f265ad17fa95f42207cc3b65db96feb 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk @@ -36,10 +36,8 @@ LOCAL_DEX_PREOPT := false include $(BUILD_PACKAGE) -ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES) $(hide) mkdir -p $(dir $@) $(MAINDEXCLASSES) $< 1>$@ $(built_dex_intermediate): $(mainDexList) -endif diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml index e30689203c1b91fd767b84709b7eea80e880b04d..7cd01e54a64e3c7c17868f77c6336a5bc737ed23 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml @@ -7,6 +7,8 @@ + + @@ -124,6 +126,6 @@ - + diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java index 7b83999d0ca91c63fcd1a560a7e876116d23316e..cb0a591559db1fc2827a24d48491869c767f4a0c 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java @@ -60,35 +60,40 @@ public abstract class AbstractService extends Service implements Runnable { // of the result file will be too big. RandomAccessFile raf = new RandomAccessFile(resultFile, "rw"); raf.seek(raf.length()); - Log.i(TAG, "Writing 0x42434445 at " + raf.length() + " in " + resultFile.getPath()); - raf.writeInt(0x42434445); + if (raf.length() == 0) { + Log.i(TAG, "Writing 0x42434445 at " + raf.length() + " in " + resultFile.getPath()); + raf.writeInt(0x42434445); + } else { + Log.w(TAG, "Service was restarted appending 0x42434445 twice at " + raf.length() + + " in " + resultFile.getPath()); + raf.writeInt(0x42434445); + raf.writeInt(0x42434445); + } raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } - MultiDex.install(applicationContext); - Log.i(TAG, "Multi dex installation done."); + MultiDex.install(applicationContext); + Log.i(TAG, "Multi dex installation done."); - int value = getValue(); - Log.i(TAG, "Saving the result (" + value + ") to " + resultFile.getPath()); - try { + int value = getValue(); + Log.i(TAG, "Saving the result (" + value + ") to " + resultFile.getPath()); // Append the check value in result file, keeping the constant values already written. - RandomAccessFile raf = new RandomAccessFile(resultFile, "rw"); + raf = new RandomAccessFile(resultFile, "rw"); raf.seek(raf.length()); Log.i(TAG, "Writing result at " + raf.length() + " in " + resultFile.getPath()); raf.writeInt(value); raf.close(); } catch (IOException e) { - e.printStackTrace(); - } - try { - // Writing end of processing flags, the existence of the file is the criteria - RandomAccessFile raf = new RandomAccessFile(new File(applicationContext.getFilesDir(), getId() + ".complete"), "rw"); - Log.i(TAG, "creating complete file " + resultFile.getPath()); - raf.writeInt(0x32333435); - raf.close(); - } catch (IOException e) { - e.printStackTrace(); + throw new AssertionError(e); + } finally { + try { + // Writing end of processing flags, the existence of the file is the criteria + RandomAccessFile raf = new RandomAccessFile( + new File(applicationContext.getFilesDir(), getId() + ".complete"), "rw"); + Log.i(TAG, "creating complete file " + resultFile.getPath()); + raf.writeInt(0x32333435); + raf.close(); + } catch (IOException e) { + e.printStackTrace(); + } } } @@ -119,9 +124,10 @@ public abstract class AbstractService extends Service implements Runnable { intermediate = ReflectIntermediateClass.get(45, 80, 20 /* 5 seems enough on a nakasi, using 20 to get some margin */); } catch (Exception e) { - e.printStackTrace(); + throw new AssertionError(e); } - int value = new com.android.framework.multidexlegacytestservices.manymethods.Big001().get1() + + int value = + new com.android.framework.multidexlegacytestservices.manymethods.Big001().get1() + new com.android.framework.multidexlegacytestservices.manymethods.Big002().get2() + new com.android.framework.multidexlegacytestservices.manymethods.Big003().get3() + new com.android.framework.multidexlegacytestservices.manymethods.Big004().get4() + diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..f3d98a88d48550855a83debc0b6dfa15cd94f238 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk @@ -0,0 +1,33 @@ +# Copyright (C) 2014 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 := tests + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := MultiDexLegacyTestServicesTests2 + +LOCAL_JAVA_LIBRARIES := android-support-multidex +LOCAL_STATIC_JAVA_LIBRARIES := android-support-test + +LOCAL_SDK_VERSION := 9 + +LOCAL_DEX_PREOPT := false + +include $(BUILD_PACKAGE) + diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..0ab29591be18f2af5abc21e6ca6519a7b77ad0a8 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java new file mode 100644 index 0000000000000000000000000000000000000000..900f20387c4937239330a8dd289dbedaf7607d83 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacytestservices.test2; + +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; +import android.util.Log; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.TimeoutException; +import junit.framework.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Run the tests with: adb shell am instrument -w + * com.android.framework.multidexlegacytestservices.test2/android.support.test.runner.AndroidJUnitRunner + * + */ +@RunWith(AndroidJUnit4.class) +public class ServicesTests { + private static final String TAG = "ServicesTests"; + + static { + Log.i(TAG, "Initializing"); + } + + private class ExtensionFilter implements FileFilter { + private final String ext; + + public ExtensionFilter(String ext) { + this.ext = ext; + } + + @Override + public boolean accept(File file) { + return file.getName().endsWith(ext); + } + } + + private class ExtractedZipFilter extends ExtensionFilter { + public ExtractedZipFilter() { + super(".zip"); + } + + @Override + public boolean accept(File file) { + return super.accept(file) && !file.getName().startsWith("tmp-"); + } + } + + private static final int ENDHDR = 22; + + private static final String SERVICE_BASE_ACTION = + "com.android.framework.multidexlegacytestservices.action.Service"; + private static final int MIN_SERVICE = 1; + private static final int MAX_SERVICE = 19; + private static final String COMPLETION_SUCCESS = "Success"; + + private File targetFilesDir; + + @Before + public void setup() throws Exception { + Log.i(TAG, "setup"); + killServices(); + + File applicationDataDir = + new File(InstrumentationRegistry.getTargetContext().getApplicationInfo().dataDir); + clearDirContent(applicationDataDir); + targetFilesDir = InstrumentationRegistry.getTargetContext().getFilesDir(); + + Log.i(TAG, "setup done"); + } + + @Test + public void testStressConcurentLaunch() throws Exception { + startServices(); + waitServicesCompletion(); + String completionStatus = getServicesCompletionStatus(); + if (completionStatus != COMPLETION_SUCCESS) { + Assert.fail(completionStatus); + } + } + + @Test + public void testRecoverFromZipCorruption() throws Exception { + int serviceId = 1; + // Ensure extraction. + initServicesWorkFiles(); + startService(serviceId); + waitServicesCompletion(serviceId); + + // Corruption of the extracted zips. + tamperAllExtractedZips(); + + killServices(); + checkRecover(); + } + + @Test + public void testRecoverFromDexCorruption() throws Exception { + int serviceId = 1; + // Ensure extraction. + initServicesWorkFiles(); + startService(serviceId); + waitServicesCompletion(serviceId); + + // Corruption of the odex files. + tamperAllOdex(); + + killServices(); + checkRecover(); + } + + @Test + public void testRecoverFromZipCorruptionStressTest() throws Exception { + Thread startServices = + new Thread() { + @Override + public void run() { + startServices(); + } + }; + + startServices.start(); + + // Start services lasts more than 80s, lets cause a few corruptions during this interval. + for (int i = 0; i < 80; i++) { + Thread.sleep(1000); + tamperAllExtractedZips(); + } + startServices.join(); + try { + waitServicesCompletion(); + } catch (TimeoutException e) { + // Can happen. + } + + killServices(); + checkRecover(); + } + + @Test + public void testRecoverFromDexCorruptionStressTest() throws Exception { + Thread startServices = + new Thread() { + @Override + public void run() { + startServices(); + } + }; + + startServices.start(); + + // Start services lasts more than 80s, lets cause a few corruptions during this interval. + for (int i = 0; i < 80; i++) { + Thread.sleep(1000); + tamperAllOdex(); + } + startServices.join(); + try { + waitServicesCompletion(); + } catch (TimeoutException e) { + // Will probably happen most of the time considering what we're doing... + } + + killServices(); + checkRecover(); + } + + private static void clearDirContent(File dir) { + for (File subElement : dir.listFiles()) { + if (subElement.isDirectory()) { + clearDirContent(subElement); + } + if (!subElement.delete()) { + throw new AssertionError("Failed to clear '" + subElement.getAbsolutePath() + "'"); + } + } + } + + private void startServices() { + Log.i(TAG, "start services"); + initServicesWorkFiles(); + for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) { + startService(i); + try { + Thread.sleep((i - 1) * (1 << (i / 5))); + } catch (InterruptedException e) { + } + } + } + + private void startService(int serviceId) { + Log.i(TAG, "start service " + serviceId); + InstrumentationRegistry.getContext().startService(new Intent(SERVICE_BASE_ACTION + serviceId)); + } + + private void initServicesWorkFiles() { + for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) { + File resultFile = new File(targetFilesDir, "Service" + i); + resultFile.delete(); + Assert.assertFalse( + "Failed to delete result file '" + resultFile.getAbsolutePath() + "'.", + resultFile.exists()); + File completeFile = new File(targetFilesDir, "Service" + i + ".complete"); + completeFile.delete(); + Assert.assertFalse( + "Failed to delete completion file '" + completeFile.getAbsolutePath() + "'.", + completeFile.exists()); + } + } + + private void waitServicesCompletion() throws TimeoutException { + Log.i(TAG, "start sleeping"); + int attempt = 0; + int maxAttempt = 50; // 10 is enough for a nexus S + do { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + attempt++; + if (attempt >= maxAttempt) { + throw new TimeoutException(); + } + } while (!areAllServicesCompleted()); + } + + private void waitServicesCompletion(int serviceId) throws TimeoutException { + Log.i(TAG, "start sleeping"); + int attempt = 0; + int maxAttempt = 50; // 10 is enough for a nexus S + do { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + attempt++; + if (attempt >= maxAttempt) { + throw new TimeoutException(); + } + } while (isServiceRunning(serviceId)); + } + + private String getServicesCompletionStatus() { + String status = COMPLETION_SUCCESS; + for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) { + File resultFile = new File(targetFilesDir, "Service" + i); + if (!resultFile.isFile()) { + status = "Service" + i + " never completed."; + break; + } + if (resultFile.length() != 8) { + status = "Service" + i + " was restarted."; + break; + } + } + Log.i(TAG, "Services completion status: " + status); + return status; + } + + private String getServiceCompletionStatus(int serviceId) { + String status = COMPLETION_SUCCESS; + File resultFile = new File(targetFilesDir, "Service" + serviceId); + if (!resultFile.isFile()) { + status = "Service" + serviceId + " never completed."; + } else if (resultFile.length() != 8) { + status = "Service" + serviceId + " was restarted."; + } + Log.i(TAG, "Service " + serviceId + " completion status: " + status); + return status; + } + + private boolean areAllServicesCompleted() { + for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) { + if (isServiceRunning(i)) { + return false; + } + } + return true; + } + + private boolean isServiceRunning(int i) { + File completeFile = new File(targetFilesDir, "Service" + i + ".complete"); + return !completeFile.exists(); + } + + private File getSecondaryFolder() { + File dir = + new File( + new File( + InstrumentationRegistry.getTargetContext().getApplicationInfo().dataDir, + "code_cache"), + "secondary-dexes"); + Assert.assertTrue(dir.getAbsolutePath(), dir.isDirectory()); + return dir; + } + + private void tamperAllExtractedZips() throws IOException { + // First attempt was to just overwrite zip entries but keep central directory, this was no + // trouble for Dalvik that was just ignoring those zip and using the odex files. + Log.i(TAG, "Tamper extracted zip files by overwriting all content by '\\0's."); + byte[] zeros = new byte[4 * 1024]; + // Do not tamper tmp zip during their extraction. + for (File zip : getSecondaryFolder().listFiles(new ExtractedZipFilter())) { + long fileLength = zip.length(); + Assert.assertTrue(fileLength > ENDHDR); + zip.setWritable(true); + RandomAccessFile raf = new RandomAccessFile(zip, "rw"); + try { + int index = 0; + while (index < fileLength) { + int length = (int) Math.min(zeros.length, fileLength - index); + raf.write(zeros, 0, length); + index += length; + } + } finally { + raf.close(); + } + } + } + + private void tamperAllOdex() throws IOException { + Log.i(TAG, "Tamper odex files by overwriting some content by '\\0's."); + byte[] zeros = new byte[4 * 1024]; + // I think max size would be 40 (u1[8] + 8 u4) but it's a test so lets take big margins. + int savedSizeForOdexHeader = 80; + for (File odex : getSecondaryFolder().listFiles(new ExtensionFilter(".dex"))) { + long fileLength = odex.length(); + Assert.assertTrue(fileLength > zeros.length + savedSizeForOdexHeader); + odex.setWritable(true); + RandomAccessFile raf = new RandomAccessFile(odex, "rw"); + try { + raf.seek(savedSizeForOdexHeader); + raf.write(zeros, 0, zeros.length); + } finally { + raf.close(); + } + } + } + + private void checkRecover() throws TimeoutException { + Log.i(TAG, "Check recover capability"); + int serviceId = 1; + // Start one service and check it was able to run correctly even if a previous run failed. + initServicesWorkFiles(); + startService(serviceId); + waitServicesCompletion(serviceId); + String completionStatus = getServiceCompletionStatus(serviceId); + if (completionStatus != COMPLETION_SUCCESS) { + Assert.fail(completionStatus); + } + } + + private void killServices() { + ((ActivityManager) + InstrumentationRegistry.getContext().getSystemService(Context.ACTIVITY_SERVICE)) + .killBackgroundProcesses("com.android.framework.multidexlegacytestservices"); + } +} diff --git a/core/tests/overlaytests/device/Android.mk b/core/tests/overlaytests/device/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..4ca3e4ce238977bd2bd09a27f398211ceaefbc18 --- /dev/null +++ b/core/tests/overlaytests/device/Android.mk @@ -0,0 +1,31 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_MODULE_TAGS := tests +LOCAL_PACKAGE_NAME := OverlayDeviceTests +LOCAL_STATIC_JAVA_LIBRARIES := android-support-test +LOCAL_COMPATIBILITY_SUITE := device-tests +LOCAL_TARGET_REQUIRED_MODULES := \ + OverlayDeviceTests_AppOverlayOne \ + OverlayDeviceTests_AppOverlayTwo \ + OverlayDeviceTests_FrameworkOverlay +include $(BUILD_PACKAGE) + +# Include to build test-apps. +include $(call all-makefiles-under,$(LOCAL_PATH)) + diff --git a/core/tests/overlaytests/device/AndroidManifest.xml b/core/tests/overlaytests/device/AndroidManifest.xml index e01caeedd8628f4f545e557270d824a9ab96bc28..d14fdf5ee819db8cc11fe6002f241286190dcafe 100644 --- a/core/tests/overlaytests/device/AndroidManifest.xml +++ b/core/tests/overlaytests/device/AndroidManifest.xml @@ -15,15 +15,15 @@ --> + package="com.android.overlaytest"> - + - + android:targetPackage="com.android.overlaytest" + android:label="Runtime resource overlay tests" /> diff --git a/core/tests/overlaytests/device/AndroidTest.xml b/core/tests/overlaytests/device/AndroidTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..f069835598308d91d6d42800236d4e94878d6f4b --- /dev/null +++ b/core/tests/overlaytests/device/AndroidTest.xml @@ -0,0 +1,47 @@ + + + + + diff --git a/core/tests/overlaytests/device/OverlayAppFiltered/Android.mk b/core/tests/overlaytests/device/OverlayAppFiltered/Android.mk deleted file mode 100644 index f76de7a93b2e0a4f9c1ff7cdcf7c8f752e8e59bc..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFiltered/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_SDK_VERSION := system_current - -LOCAL_PACKAGE_NAME := com.android.overlaytest.filtered_app_overlay - -include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/OverlayAppFiltered/AndroidManifest.xml b/core/tests/overlaytests/device/OverlayAppFiltered/AndroidManifest.xml deleted file mode 100644 index 5b7950a25fbfaa94ec54bfc6c695dc52ee11ae45..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFiltered/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/core/tests/overlaytests/device/OverlayAppFiltered/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/device/OverlayAppFiltered/res/raw/lorem_ipsum.txt deleted file mode 100644 index 0954cedeb5d53d2625107f9d8628fc8567400180..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFiltered/res/raw/lorem_ipsum.txt +++ /dev/null @@ -1 +0,0 @@ -Lorem ipsum: filtered overlays. diff --git a/core/tests/overlaytests/device/OverlayAppFiltered/res/values/config.xml b/core/tests/overlaytests/device/OverlayAppFiltered/res/values/config.xml deleted file mode 100644 index 60b94eec599416e306e2690f721e4e57adceb55e..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFiltered/res/values/config.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - filtered - diff --git a/core/tests/overlaytests/device/OverlayAppFiltered/res/xml/integer.xml b/core/tests/overlaytests/device/OverlayAppFiltered/res/xml/integer.xml deleted file mode 100644 index e2652b7e2915abae32eb90cb5c14e786dbd54b60..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFiltered/res/xml/integer.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/core/tests/overlaytests/device/OverlayAppFirst/Android.mk b/core/tests/overlaytests/device/OverlayAppFirst/Android.mk deleted file mode 100644 index bf9416c279beb543dcbf3002a6cc087e69d5f9e4..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFirst/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_SDK_VERSION := current - -LOCAL_PACKAGE_NAME := com.android.overlaytest.first_app_overlay - -include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/OverlayAppFirst/AndroidManifest.xml b/core/tests/overlaytests/device/OverlayAppFirst/AndroidManifest.xml deleted file mode 100644 index ec10bbcf752e407d6cadae2b93d071b28568c407..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppFirst/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/core/tests/overlaytests/device/OverlayAppSecond/Android.mk b/core/tests/overlaytests/device/OverlayAppSecond/Android.mk deleted file mode 100644 index bb7d142d6809124d4668245275b13b9191248489..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppSecond/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_SDK_VERSION := current - -LOCAL_PACKAGE_NAME := com.android.overlaytest.second_app_overlay - -include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/OverlayAppSecond/AndroidManifest.xml b/core/tests/overlaytests/device/OverlayAppSecond/AndroidManifest.xml deleted file mode 100644 index ed498637b454b57b5faa33da966e6f0d97c141e1..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayAppSecond/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/core/tests/overlaytests/device/OverlayTest/Android.mk b/core/tests/overlaytests/device/OverlayTest/Android.mk deleted file mode 100644 index 5fe7b917102ebc8aba03b4e5f529ad8efacffbb0..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTest/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_PACKAGE_NAME := OverlayTest - -LOCAL_DEX_PREOPT := false - -LOCAL_JAVA_LIBRARIES += android.test.base - -LOCAL_MODULE_PATH := $(TARGET_OUT)/app - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/OverlayTest/AndroidManifest.xml b/core/tests/overlaytests/device/OverlayTest/AndroidManifest.xml deleted file mode 100644 index 9edba12ffa8f048a6ad17a2fea6ad98d1fe95ecd..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTest/AndroidManifest.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java b/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java deleted file mode 100644 index e104f5a670c1c0a0e4604249f4d91edd86eaa49f..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.android.overlaytest; - -public class WithMultipleOverlaysTest extends OverlayBaseTest { - public WithMultipleOverlaysTest() { - mMode = MODE_MULTIPLE_OVERLAYS; - } -} diff --git a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java deleted file mode 100644 index 816a476e28cf1696c9b19236d2b2c1882498e91b..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.android.overlaytest; - -public class WithOverlayTest extends OverlayBaseTest { - public WithOverlayTest() { - mMode = MODE_SINGLE_OVERLAY; - } -} diff --git a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java deleted file mode 100644 index 318cccc854616315b54da6ea421af97588ec56b2..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.android.overlaytest; - -public class WithoutOverlayTest extends OverlayBaseTest { - public WithoutOverlayTest() { - mMode = MODE_NO_OVERLAY; - } -} diff --git a/core/tests/overlaytests/device/OverlayTestOverlay/Android.mk b/core/tests/overlaytests/device/OverlayTestOverlay/Android.mk deleted file mode 100644 index ed330467f68a8d86fafd3e996cb150c90c6b3d6a..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTestOverlay/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_SDK_VERSION := current - -LOCAL_PACKAGE_NAME := com.android.overlaytest.overlay - -include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/OverlayTestOverlay/AndroidManifest.xml b/core/tests/overlaytests/device/OverlayTestOverlay/AndroidManifest.xml deleted file mode 100644 index f8b6c7b888b59922b61d3f864478d31695155f0d..0000000000000000000000000000000000000000 --- a/core/tests/overlaytests/device/OverlayTestOverlay/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/core/tests/overlaytests/device/OverlayTest/res/drawable-nodpi/drawable.jpg b/core/tests/overlaytests/device/res/drawable-nodpi/drawable.jpg similarity index 100% rename from core/tests/overlaytests/device/OverlayTest/res/drawable-nodpi/drawable.jpg rename to core/tests/overlaytests/device/res/drawable-nodpi/drawable.jpg diff --git a/core/tests/overlaytests/device/OverlayTest/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/device/res/raw/lorem_ipsum.txt similarity index 100% rename from core/tests/overlaytests/device/OverlayTest/res/raw/lorem_ipsum.txt rename to core/tests/overlaytests/device/res/raw/lorem_ipsum.txt diff --git a/core/tests/overlaytests/device/OverlayTest/res/values-sv/config.xml b/core/tests/overlaytests/device/res/values-sv/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayTest/res/values-sv/config.xml rename to core/tests/overlaytests/device/res/values-sv/config.xml diff --git a/core/tests/overlaytests/device/OverlayTest/res/values/config.xml b/core/tests/overlaytests/device/res/values/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayTest/res/values/config.xml rename to core/tests/overlaytests/device/res/values/config.xml diff --git a/core/tests/overlaytests/device/OverlayTest/res/xml/integer.xml b/core/tests/overlaytests/device/res/xml/integer.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayTest/res/xml/integer.xml rename to core/tests/overlaytests/device/res/xml/integer.xml diff --git a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java similarity index 76% rename from core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java rename to core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java index e57c55ced04651d24af8632ccb0a5dc88588ace8..96ab977b799c56edf62233c9b8202e11517bb457 100644 --- a/core/tests/overlaytests/device/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java @@ -1,45 +1,80 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.overlaytest; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.app.UiAutomation; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; -import android.test.AndroidTestCase; +import android.os.LocaleList; +import android.os.ParcelFileDescriptor; +import android.support.test.InstrumentationRegistry; import android.util.AttributeSet; import android.util.Xml; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.Locale; -public abstract class OverlayBaseTest extends AndroidTestCase { +@Ignore +public abstract class OverlayBaseTest { private Resources mResources; - protected int mMode; // will be set by subclasses - static final protected int MODE_NO_OVERLAY = 0; - static final protected int MODE_SINGLE_OVERLAY = 1; - static final protected int MODE_MULTIPLE_OVERLAYS = 2; + private final int mMode; + static final int MODE_NO_OVERLAY = 0; + static final int MODE_SINGLE_OVERLAY = 1; + static final int MODE_MULTIPLE_OVERLAYS = 2; + + static final String APP_OVERLAY_ONE_PKG = "com.android.overlaytest.app_overlay_one"; + static final String APP_OVERLAY_TWO_PKG = "com.android.overlaytest.app_overlay_two"; + static final String FRAMEWORK_OVERLAY_PKG = "com.android.overlaytest.framework"; + + protected OverlayBaseTest(int mode) { + mMode = mode; + } - protected void setUp() { - mResources = getContext().getResources(); + @Before + public void setUp() { + mResources = InstrumentationRegistry.getContext().getResources(); } private int calculateRawResourceChecksum(int resId) throws Throwable { - InputStream input = null; - try { - input = mResources.openRawResource(resId); + try (InputStream input = mResources.openRawResource(resId)) { int ch, checksum = 0; while ((ch = input.read()) != -1) { checksum = (checksum + ch) % 0xffddbb00; } return checksum; - } finally { - input.close(); } } private void setLocale(Locale locale) { - Locale.setDefault(locale); + final LocaleList locales = new LocaleList(locale); + LocaleList.setDefault(locales); Configuration config = new Configuration(); - config.locale = locale; + config.setLocales(locales); mResources.updateConfiguration(config, mResources.getDisplayMetrics()); } @@ -126,6 +161,7 @@ public abstract class OverlayBaseTest extends AndroidTestCase { } } + @Test public void testFrameworkBooleanOverlay() throws Throwable { // config_annoy_dianne has the value: // - true when no overlay exists (MODE_NO_OVERLAY) @@ -135,6 +171,7 @@ public abstract class OverlayBaseTest extends AndroidTestCase { assertResource(resId, true, false, false); } + @Test public void testBooleanOverlay() throws Throwable { // usually_false has the value: // - false when no overlay exists (MODE_NO_OVERLAY) @@ -144,12 +181,14 @@ public abstract class OverlayBaseTest extends AndroidTestCase { assertResource(resId, false, true, false); } + @Test public void testBoolean() throws Throwable { // always_true has no overlay final int resId = R.bool.always_true; assertResource(resId, true, true, true); } + @Test public void testIntegerArrayOverlay() throws Throwable { // fibonacci has values: // - eight first values of Fibonacci sequence, when no overlay exists (MODE_NO_OVERLAY) @@ -162,6 +201,7 @@ public abstract class OverlayBaseTest extends AndroidTestCase { new int[]{21, 13, 8, 5, 3, 2, 1, 1}); } + @Test public void testIntegerArray() throws Throwable { // prime_numbers has no overlay final int resId = R.array.prime_numbers; @@ -169,6 +209,7 @@ public abstract class OverlayBaseTest extends AndroidTestCase { assertResource(resId, expected, expected, expected); } + @Test public void testDrawable() throws Throwable { // drawable-nodpi/drawable has overlay (default config) final int resId = R.drawable.drawable; @@ -188,16 +229,19 @@ public abstract class OverlayBaseTest extends AndroidTestCase { assertEquals(expected, actual); } + @Test public void testAppString() throws Throwable { final int resId = R.string.str; assertResource(resId, "none", "single", "multiple"); } + @Test public void testApp2() throws Throwable { final int resId = R.string.str2; // only in base package and first app overlay assertResource(resId, "none", "single", "single"); } + @Test public void testAppXml() throws Throwable { int expected = getExpected(0, 1, 2); int actual = -1; @@ -214,6 +258,7 @@ public abstract class OverlayBaseTest extends AndroidTestCase { assertEquals(expected, actual); } + @Test public void testAppRaw() throws Throwable { final int resId = R.raw.lorem_ipsum; @@ -256,10 +301,10 @@ public abstract class OverlayBaseTest extends AndroidTestCase { * SLOT PACKAGE CONFIGURATION VALUE * A target package (default) 100 * B target package -sv 200 - * C OverlayAppFirst (default) 300 - * D OverlayAppFirst -sv 400 - * E OverlayAppSecond (default) 500 - * F OverlayAppSecond -sv 600 + * C AppOverlayOne (default) 300 + * D AppOverlayOne -sv 400 + * E AppOverlayTwo (default) 500 + * F AppOverlayTwo -sv 600 * * Example: in testMatrix101110, the base package defines the * R.integer.matrix101110 resource for the default configuration (value @@ -269,195 +314,283 @@ public abstract class OverlayBaseTest extends AndroidTestCase { * are loaded, the expected value after setting the language to Swedish is * 400. */ + @Test public void testMatrix100000() throws Throwable { final int resId = R.integer.matrix_100000; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 100, 100); } + @Test public void testMatrix100001() throws Throwable { final int resId = R.integer.matrix_100001; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 100, 600); } + @Test public void testMatrix100010() throws Throwable { final int resId = R.integer.matrix_100010; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 100, 500); } + @Test public void testMatrix100011() throws Throwable { final int resId = R.integer.matrix_100011; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 100, 600); } + @Test public void testMatrix100100() throws Throwable { final int resId = R.integer.matrix_100100; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 400); } + @Test public void testMatrix100101() throws Throwable { final int resId = R.integer.matrix_100101; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 600); } + @Test public void testMatrix100110() throws Throwable { final int resId = R.integer.matrix_100110; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 400); } + @Test public void testMatrix100111() throws Throwable { final int resId = R.integer.matrix_100111; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 600); } + @Test public void testMatrix101000() throws Throwable { final int resId = R.integer.matrix_101000; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 300, 300); } + @Test public void testMatrix101001() throws Throwable { final int resId = R.integer.matrix_101001; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 300, 600); } + @Test public void testMatrix101010() throws Throwable { final int resId = R.integer.matrix_101010; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 300, 500); } + @Test public void testMatrix101011() throws Throwable { final int resId = R.integer.matrix_101011; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 300, 600); } + @Test public void testMatrix101100() throws Throwable { final int resId = R.integer.matrix_101100; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 400); } + @Test public void testMatrix101101() throws Throwable { final int resId = R.integer.matrix_101101; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 600); } + @Test public void testMatrix101110() throws Throwable { final int resId = R.integer.matrix_101110; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 400); } + @Test public void testMatrix101111() throws Throwable { final int resId = R.integer.matrix_101111; setLocale(new Locale("sv", "SE")); assertResource(resId, 100, 400, 600); } + @Test public void testMatrix110000() throws Throwable { final int resId = R.integer.matrix_110000; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 200); } + @Test public void testMatrix110001() throws Throwable { final int resId = R.integer.matrix_110001; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 600); } + @Test public void testMatrix110010() throws Throwable { final int resId = R.integer.matrix_110010; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 200); } + @Test public void testMatrix110011() throws Throwable { final int resId = R.integer.matrix_110011; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 600); } + @Test public void testMatrix110100() throws Throwable { final int resId = R.integer.matrix_110100; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 400); } + @Test public void testMatrix110101() throws Throwable { final int resId = R.integer.matrix_110101; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 600); } + @Test public void testMatrix110110() throws Throwable { final int resId = R.integer.matrix_110110; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 400); } + @Test public void testMatrix110111() throws Throwable { final int resId = R.integer.matrix_110111; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 600); } + @Test public void testMatrix111000() throws Throwable { final int resId = R.integer.matrix_111000; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 200); } + @Test public void testMatrix111001() throws Throwable { final int resId = R.integer.matrix_111001; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 600); } + @Test public void testMatrix111010() throws Throwable { final int resId = R.integer.matrix_111010; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 200); } + @Test public void testMatrix111011() throws Throwable { final int resId = R.integer.matrix_111011; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 200, 600); } + @Test public void testMatrix111100() throws Throwable { final int resId = R.integer.matrix_111100; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 400); } + @Test public void testMatrix111101() throws Throwable { final int resId = R.integer.matrix_111101; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 600); } + @Test public void testMatrix111110() throws Throwable { final int resId = R.integer.matrix_111110; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 400); } + @Test public void testMatrix111111() throws Throwable { final int resId = R.integer.matrix_111111; setLocale(new Locale("sv", "SE")); assertResource(resId, 200, 400, 600); } + + /** + * Executes the shell command and reads all the output to ensure the command ran and didn't + * get stuck buffering on output. + */ + protected static String executeShellCommand(UiAutomation automation, String command) + throws Exception { + final ParcelFileDescriptor pfd = automation.executeShellCommand(command); + try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { + final BufferedReader reader = new BufferedReader( + new InputStreamReader(in, StandardCharsets.UTF_8)); + StringBuilder str = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + str.append(line); + } + return str.toString(); + } + } + + /** + * Enables overlay packages and waits for a configuration change event before + * returning, to guarantee that Resources are up-to-date. + * @param packages the list of package names to enable. + */ + protected static void enableOverlayPackages(String... packages) throws Exception { + enableOverlayPackages(true, packages); + } + + /** + * Disables overlay packages and waits for a configuration change event before + * returning, to guarantee that Resources are up-to-date. + * @param packages the list of package names to disable. + */ + protected static void disableOverlayPackages(String... packages) throws Exception { + enableOverlayPackages(false, packages); + } + + /** + * Enables/disables overlay packages and waits for a configuration change event before + * returning, to guarantee that Resources are up-to-date. + * @param enable enables the overlays when true, disables when false. + * @param packages the list of package names to enable/disable. + */ + private static void enableOverlayPackages(boolean enable, String[] packages) + throws Exception { + final UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation() + .getUiAutomation(); + for (final String pkg : packages) { + executeShellCommand(uiAutomation, + "cmd overlay " + (enable ? "enable " : "disable ") + pkg); + } + + // Wait for the overlay change to propagate. + Thread.sleep(1000); + } } diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f35e511cdcf43ad7cf048eaeefe25c1ca318b065 --- /dev/null +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.overlaytest; + +import android.support.test.filters.MediumTest; + +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@MediumTest +public class WithMultipleOverlaysTest extends OverlayBaseTest { + public WithMultipleOverlaysTest() { + super(MODE_MULTIPLE_OVERLAYS); + } + + @BeforeClass + public static void enableOverlay() throws Exception { + enableOverlayPackages(APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG, FRAMEWORK_OVERLAY_PKG); + } +} diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java new file mode 100644 index 0000000000000000000000000000000000000000..037449fc2c05cc708dfc143794de69463267133b --- /dev/null +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.overlaytest; + +import android.support.test.filters.MediumTest; + +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@MediumTest +public class WithOverlayTest extends OverlayBaseTest { + public WithOverlayTest() { + super(MODE_SINGLE_OVERLAY); + } + + @BeforeClass + public static void enableOverlay() throws Exception { + disableOverlayPackages(APP_OVERLAY_TWO_PKG); + enableOverlayPackages(APP_OVERLAY_ONE_PKG, FRAMEWORK_OVERLAY_PKG); + } +} diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f657b5cef0e570b6e0bddaca9efd4217180792a6 --- /dev/null +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.overlaytest; + +import android.support.test.filters.MediumTest; + +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@MediumTest +public class WithoutOverlayTest extends OverlayBaseTest { + public WithoutOverlayTest() { + super(MODE_NO_OVERLAY); + } + + @BeforeClass + public static void disableOverlays() throws Exception { + disableOverlayPackages(APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG, FRAMEWORK_OVERLAY_PKG); + } +} diff --git a/core/tests/overlaytests/device/test-apps/Android.mk b/core/tests/overlaytests/device/test-apps/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..9af9f444ca592a8aa527cb8f0af9ac3be6dfaef4 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/Android.mk @@ -0,0 +1,15 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(call all-subdir-makefiles) diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..17e20eeeda851203c835b7c735718883b0f8272d --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk @@ -0,0 +1,22 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PACKAGE_NAME := OverlayDeviceTests_AppOverlayOne +LOCAL_COMPATIBILITY_SUITE := device-tests +LOCAL_CERTIFICATE := platform +include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..17191589e3f2a402ac9211e8c3405579cd35c4e3 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/core/tests/overlaytests/device/OverlayAppFirst/res/drawable-nodpi/drawable.jpg b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/drawable-nodpi/drawable.jpg similarity index 100% rename from core/tests/overlaytests/device/OverlayAppFirst/res/drawable-nodpi/drawable.jpg rename to core/tests/overlaytests/device/test-apps/AppOverlayOne/res/drawable-nodpi/drawable.jpg diff --git a/core/tests/overlaytests/device/OverlayAppFirst/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/raw/lorem_ipsum.txt similarity index 100% rename from core/tests/overlaytests/device/OverlayAppFirst/res/raw/lorem_ipsum.txt rename to core/tests/overlaytests/device/test-apps/AppOverlayOne/res/raw/lorem_ipsum.txt diff --git a/core/tests/overlaytests/device/OverlayAppFirst/res/values-sv/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values-sv/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayAppFirst/res/values-sv/config.xml rename to core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values-sv/config.xml diff --git a/core/tests/overlaytests/device/OverlayAppFirst/res/values/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayAppFirst/res/values/config.xml rename to core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml diff --git a/core/tests/overlaytests/device/OverlayAppFirst/res/xml/integer.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/integer.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayAppFirst/res/xml/integer.xml rename to core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/integer.xml diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..c24bea9e06e9db2f720e9c83d279d9742d2cad3a --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk @@ -0,0 +1,22 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PACKAGE_NAME := OverlayDeviceTests_AppOverlayTwo +LOCAL_COMPATIBILITY_SUITE := device-tests +LOCAL_CERTIFICATE := platform +include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae8307c446c1644193ba9bab9cefb36171912637 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/core/tests/overlaytests/device/OverlayAppSecond/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/raw/lorem_ipsum.txt similarity index 100% rename from core/tests/overlaytests/device/OverlayAppSecond/res/raw/lorem_ipsum.txt rename to core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/raw/lorem_ipsum.txt diff --git a/core/tests/overlaytests/device/OverlayAppSecond/res/values-sv/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/values-sv/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayAppSecond/res/values-sv/config.xml rename to core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/values-sv/config.xml diff --git a/core/tests/overlaytests/device/OverlayAppSecond/res/values/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/values/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayAppSecond/res/values/config.xml rename to core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/values/config.xml diff --git a/core/tests/overlaytests/device/OverlayAppSecond/res/xml/integer.xml b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/xml/integer.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayAppSecond/res/xml/integer.xml rename to core/tests/overlaytests/device/test-apps/AppOverlayTwo/res/xml/integer.xml diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..dc811c51e9261535e866065a2b827414963dbea4 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk @@ -0,0 +1,22 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PACKAGE_NAME := OverlayDeviceTests_FrameworkOverlay +LOCAL_COMPATIBILITY_SUITE := device-tests +LOCAL_CERTIFICATE := platform +include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..77ea16afff830273cd6ded8568a241f473f0fdc7 --- /dev/null +++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/core/tests/overlaytests/device/OverlayTestOverlay/res/values/config.xml b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/res/values/config.xml similarity index 100% rename from core/tests/overlaytests/device/OverlayTestOverlay/res/values/config.xml rename to core/tests/overlaytests/device/test-apps/FrameworkOverlay/res/values/config.xml diff --git a/core/tests/overlaytests/host/Android.mk b/core/tests/overlaytests/host/Android.mk index d8e1fc158fc10fad33ba699fe679209c288c9a4a..b48a46bbda9ab428d95a029571c06191932152cc 100644 --- a/core/tests/overlaytests/host/Android.mk +++ b/core/tests/overlaytests/host/Android.mk @@ -24,7 +24,11 @@ LOCAL_TARGET_REQUIRED_MODULES := \ OverlayHostTests_BadSignatureOverlay \ OverlayHostTests_PlatformSignatureStaticOverlay \ OverlayHostTests_PlatformSignatureOverlay \ - OverlayHostTests_PlatformSignatureOverlayV2 + OverlayHostTests_UpdateOverlay \ + OverlayHostTests_FrameworkOverlayV1 \ + OverlayHostTests_FrameworkOverlayV2 \ + OverlayHostTests_AppOverlayV1 \ + OverlayHostTests_AppOverlayV2 include $(BUILD_HOST_JAVA_LIBRARY) # Include to build test-apps. diff --git a/core/tests/overlaytests/host/AndroidTest.xml b/core/tests/overlaytests/host/AndroidTest.xml index 68846238c5f1d2e409d6661bccaf1c7a3f4e85b6..1f750a85bc133d06f32f6699265d8c7ea3aca241 100644 --- a/core/tests/overlaytests/host/AndroidTest.xml +++ b/core/tests/overlaytests/host/AndroidTest.xml @@ -18,6 +18,11 @@

    Indicates whether pixels stored in this bitmaps are stored pre-multiplied. * When a pixel is pre-multiplied, the RGB components have been multiplied by diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index d77e6012fb46dd76a785253c01b60a534f6efc3a..fe2b523410636b48ff4a3077764209119df729ec 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -160,25 +160,6 @@ public class FontFamily { isItalic); } - /** - * Allow creating unsupported FontFamily. - * - * For compatibility reasons, we still need to create a FontFamily object even if Minikin failed - * to find any usable 'cmap' table for some reasons, e.g. broken 'cmap' table, no 'cmap' table - * encoded with Unicode code points, etc. Without calling this method, the freeze() method will - * return null if Minikin fails to find any usable 'cmap' table. By calling this method, the - * freeze() won't fail and will create an empty FontFamily. This empty FontFamily is placed at - * the top of the fallback chain but is never used. if we don't create this empty FontFamily - * and put it at top, bad things (performance regressions, unexpected glyph selection) will - * happen. - */ - public void allowUnsupportedFont() { - if (mBuilderPtr == 0) { - throw new IllegalStateException("Unable to allow unsupported font."); - } - nAllowUnsupportedFont(mBuilderPtr); - } - // TODO: Remove once internal user stop using private API. private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) { return nAddFont(builderPtr, font, ttcIndex, -1, -1); @@ -189,9 +170,6 @@ public class FontFamily { @CriticalNative private static native long nCreateFamily(long mBuilderPtr); - @CriticalNative - private static native void nAllowUnsupportedFont(long builderPtr); - @CriticalNative private static native void nAbort(long mBuilderPtr); diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index bbf214559459cecff71047620754c9451b2b60d7..acefead785c4d53a44c16188f845f74ed96dcfa1 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -74,7 +74,7 @@ public final class ImageDecoder implements AutoCloseable { int getDensity() { return Bitmap.DENSITY_NONE; } /* @hide */ - int computeDstDensity() { + final int computeDstDensity() { Resources res = getResources(); if (res == null) { return Bitmap.getDefaultDensity(); @@ -122,13 +122,19 @@ public final class ImageDecoder implements AutoCloseable { } private static class ContentResolverSource extends Source { - ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri) { + ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri, + @Nullable Resources res) { mResolver = resolver; mUri = uri; + mResources = res; } private final ContentResolver mResolver; private final Uri mUri; + private final Resources mResources; + + @Nullable + Resources getResources() { return mResources; } @Override public ImageDecoder createImageDecoder() throws IOException { @@ -438,6 +444,7 @@ public final class ImageDecoder implements AutoCloseable { private boolean mPreferRamOverQuality = false; private boolean mAsAlphaMask = false; private Rect mCropRect; + private Rect mOutPaddingRect; private Source mSource; private PostProcessor mPostProcessor; @@ -511,7 +518,18 @@ public final class ImageDecoder implements AutoCloseable { @NonNull public static Source createSource(@NonNull ContentResolver cr, @NonNull Uri uri) { - return new ContentResolverSource(cr, uri); + return new ContentResolverSource(cr, uri, null); + } + + /** + * Provide Resources for density scaling. + * + * @hide + */ + @NonNull + public static Source createSource(@NonNull ContentResolver cr, + @NonNull Uri uri, @Nullable Resources res) { + return new ContentResolverSource(cr, uri, res); } /** @@ -764,6 +782,18 @@ public final class ImageDecoder implements AutoCloseable { mCropRect = subset; } + /** + * Set a Rect for retrieving nine patch padding. + * + * If the image is a nine patch, this Rect will be set to the padding + * rectangle during decode. Otherwise it will not be modified. + * + * @hide + */ + public void setOutPaddingRect(@NonNull Rect outPadding) { + mOutPaddingRect = outPadding; + } + /** * Specify whether the {@link Bitmap} should be mutable. * @@ -875,7 +905,6 @@ public final class ImageDecoder implements AutoCloseable { postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect, mMutable, mAllocator, mRequireUnpremultiplied, mPreferRamOverQuality, mAsAlphaMask); - } private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener, @@ -948,7 +977,10 @@ public final class ImageDecoder implements AutoCloseable { if (np != null && NinePatch.isNinePatchChunk(np)) { Rect opticalInsets = new Rect(); bm.getOpticalInsets(opticalInsets); - Rect padding = new Rect(); + Rect padding = decoder.mOutPaddingRect; + if (padding == null) { + padding = new Rect(); + } nGetPadding(decoder.mNativePtr, padding); return new NinePatchDrawable(res, bm, np, padding, opticalInsets, null); @@ -991,6 +1023,15 @@ public final class ImageDecoder implements AutoCloseable { final int srcDensity = computeDensity(src, decoder); Bitmap bm = decoder.decodeBitmap(); bm.setDensity(srcDensity); + + Rect padding = decoder.mOutPaddingRect; + if (padding != null) { + byte[] np = bm.getNinePatchChunk(); + if (np != null && NinePatch.isNinePatchChunk(np)) { + nGetPadding(decoder.mNativePtr, padding); + } + } + return bm; } } diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java index 08eeaff69f9b381bfdfa1770d0ad99238b5b97bf..9ac94d895a37bb797835464a5c46911691d083c3 100644 --- a/graphics/java/android/graphics/Picture.java +++ b/graphics/java/android/graphics/Picture.java @@ -31,8 +31,9 @@ import java.io.OutputStream; * be replayed on a hardware accelerated canvas.

    */ public class Picture { - private Canvas mRecordingCanvas; + private PictureCanvas mRecordingCanvas; private long mNativePicture; + private boolean mRequiresHwAcceleration; private static final int WORKING_STREAM_STORAGE = 16 * 1024; @@ -78,8 +79,12 @@ public class Picture { * into it. */ public Canvas beginRecording(int width, int height) { + if (mRecordingCanvas != null) { + throw new IllegalStateException("Picture already recording, must call #endRecording()"); + } long ni = nativeBeginRecording(mNativePicture, width, height); - mRecordingCanvas = new RecordingCanvas(this, ni); + mRecordingCanvas = new PictureCanvas(this, ni); + mRequiresHwAcceleration = false; return mRecordingCanvas; } @@ -91,6 +96,7 @@ public class Picture { */ public void endRecording() { if (mRecordingCanvas != null) { + mRequiresHwAcceleration = mRecordingCanvas.mHoldsHwBitmap; mRecordingCanvas = null; nativeEndRecording(mNativePicture); } @@ -112,6 +118,18 @@ public class Picture { return nativeGetHeight(mNativePicture); } + /** + * Indicates whether or not this Picture contains recorded commands that only work when + * drawn to a hardware-accelerated canvas. If this returns true then this Picture can only + * be drawn to another Picture or to a Canvas where canvas.isHardwareAccelerated() is true. + * + * @return true if the Picture can only be drawn to a hardware-accelerated canvas, + * false otherwise. + */ + public boolean requiresHardwareAcceleration() { + return mRequiresHwAcceleration; + } + /** * Draw this picture on the canvas. *

    @@ -129,6 +147,9 @@ public class Picture { if (mRecordingCanvas != null) { endRecording(); } + if (mRequiresHwAcceleration && !canvas.isHardwareAccelerated()) { + canvas.onHwBitmapInSwMode(); + } nativeDraw(canvas.getNativeCanvasWrapper(), mNativePicture); } @@ -164,8 +185,7 @@ public class Picture { if (stream == null) { throw new NullPointerException(); } - if (!nativeWriteToStream(mNativePicture, stream, - new byte[WORKING_STREAM_STORAGE])) { + if (!nativeWriteToStream(mNativePicture, stream, new byte[WORKING_STREAM_STORAGE])) { throw new RuntimeException(); } } @@ -182,10 +202,11 @@ public class Picture { OutputStream stream, byte[] storage); private static native void nativeDestructor(long nativePicture); - private static class RecordingCanvas extends Canvas { + private static class PictureCanvas extends Canvas { private final Picture mPicture; + boolean mHoldsHwBitmap; - public RecordingCanvas(Picture pict, long nativeCanvas) { + public PictureCanvas(Picture pict, long nativeCanvas) { super(nativeCanvas); mPicture = pict; } @@ -202,5 +223,10 @@ public class Picture { } super.drawPicture(picture); } + + @Override + protected void onHwBitmapInSwMode() { + mHoldsHwBitmap = true; + } } } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index ef4150763139cde748564af045ae12be1fbb14cf..f41267eacde68bfa012bfe0240e6bade57f9b9c0 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -60,6 +60,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.Arrays; @@ -801,39 +802,18 @@ public class Typeface { * @return The new typeface. */ public static Typeface createFromAsset(AssetManager mgr, String path) { - if (path == null) { - throw new NullPointerException(); // for backward compatibility - } - synchronized (sDynamicCacheLock) { - Typeface typeface = new Builder(mgr, path).build(); - if (typeface != null) return typeface; - - final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, - null /* axes */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE, - DEFAULT_FAMILY); - typeface = sDynamicTypefaceCache.get(key); - if (typeface != null) return typeface; + Preconditions.checkNotNull(path); // for backward compatibility + Preconditions.checkNotNull(mgr); - final FontFamily fontFamily = new FontFamily(); - if (fontFamily.addFontFromAssetManager(mgr, path, 0, true /* isAsset */, - 0 /* ttc index */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE, - null /* axes */)) { - // Due to backward compatibility, even if the font is not supported by our font - // stack, we need to place the empty font at the first place. The typeface with - // empty font behaves different from default typeface especially in fallback - // font selection. - fontFamily.allowUnsupportedFont(); - fontFamily.freeze(); - final FontFamily[] families = { fontFamily }; - typeface = createFromFamiliesWithDefault(families, DEFAULT_FAMILY, - RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE); - sDynamicTypefaceCache.put(key, typeface); - return typeface; - } else { - fontFamily.abortCreation(); - } + Typeface typeface = new Builder(mgr, path).build(); + if (typeface != null) return typeface; + // check if the file exists, and throw an exception for backward compatibility + try (InputStream inputStream = mgr.open(path)) { + } catch (IOException e) { + throw new RuntimeException("Font asset not found " + path); } - throw new RuntimeException("Font asset not found " + path); + + return Typeface.DEFAULT; } /** @@ -851,13 +831,22 @@ public class Typeface { /** * Create a new typeface from the specified font file. * - * @param path The path to the font data. + * @param file The path to the font data. * @return The new typeface. */ - public static Typeface createFromFile(@Nullable File path) { + public static Typeface createFromFile(@Nullable File file) { // For the compatibility reasons, leaving possible NPE here. // See android.graphics.cts.TypefaceTest#testCreateFromFileByFileReferenceNull - return createFromFile(path.getAbsolutePath()); + + Typeface typeface = new Builder(file).build(); + if (typeface != null) return typeface; + + // check if the file exists, and throw an exception for backward compatibility + if (!file.exists()) { + throw new RuntimeException("Font asset not found " + file.getAbsolutePath()); + } + + return Typeface.DEFAULT; } /** @@ -867,22 +856,8 @@ public class Typeface { * @return The new typeface. */ public static Typeface createFromFile(@Nullable String path) { - final FontFamily fontFamily = new FontFamily(); - if (fontFamily.addFont(path, 0 /* ttcIndex */, null /* axes */, - RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE)) { - // Due to backward compatibility, even if the font is not supported by our font - // stack, we need to place the empty font at the first place. The typeface with - // empty font behaves different from default typeface especially in fallback font - // selection. - fontFamily.allowUnsupportedFont(); - fontFamily.freeze(); - FontFamily[] families = { fontFamily }; - return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, - RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE); - } else { - fontFamily.abortCreation(); - } - throw new RuntimeException("Font not found " + path); + Preconditions.checkNotNull(path); // for backward compatibility + return createFromFile(new File(path)); } /** diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java index 0ec19f9a4aeee811ff71188dbb53e56dc8c53319..86e6fa8c2fc57bb79bcdc5924e637a423bc9ffed 100644 --- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import dalvik.annotation.optimization.FastNative; + import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -60,7 +62,6 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { private int mIntrinsicHeight; private boolean mStarting; - private boolean mRunning; private Handler mHandler; @@ -80,12 +81,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { private State mState; - private Runnable mRunnable = new Runnable() { - @Override - public void run() { - invalidateSelf(); - } - }; + private Runnable mRunnable; /** * Pass this to {@link #setLoopCount} to loop infinitely. @@ -222,8 +218,8 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { return mIntrinsicHeight; } - // nDraw returns -2 if the animation is not running. - private static final int NOT_RUNNING = -2; + // nDraw returns -1 if the animation has finished. + private static final int FINISHED = -1; @Override public void draw(@NonNull Canvas canvas) { @@ -235,21 +231,19 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { mStarting = false; postOnAnimationStart(); - - mRunning = true; } long nextUpdate = nDraw(mState.mNativePtr, canvas.getNativeCanvasWrapper()); // a value <= 0 indicates that the drawable is stopped or that renderThread // will manage the animation if (nextUpdate > 0) { - scheduleSelf(mRunnable, nextUpdate); - } else if (nextUpdate == NOT_RUNNING) { - // -2 means the animation ended, when drawn in software mode. - if (mRunning) { - postOnAnimationEnd(); - mRunning = false; + if (mRunnable == null) { + mRunnable = this::invalidateSelf; } + scheduleSelf(mRunnable, nextUpdate); + } else if (nextUpdate == FINISHED) { + // This means the animation was drawn in software mode and ended. + postOnAnimationEnd(); } } @@ -292,6 +286,19 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { return PixelFormat.TRANSLUCENT; } + @Override + public boolean setVisible(boolean visible, boolean restart) { + if (!super.setVisible(visible, restart)) { + return false; + } + + if (!visible) { + nMarkInvisible(mState.mNativePtr); + } + + return true; + } + // Animatable overrides /** * Return whether the animation is currently running. @@ -301,13 +308,17 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { */ @Override public boolean isRunning() { - return mRunning; + if (mState == null) { + throw new IllegalStateException("called isRunning on empty AnimatedImageDrawable"); + } + return nIsRunning(mState.mNativePtr); } /** * Start the animation. * - *

    Does nothing if the animation is already running. + *

    Does nothing if the animation is already running. If the animation is stopped, + * this will reset it.

    * *

    If the animation starts, this will call * {@link Animatable2.AnimationCallback#onAnimationStart}.

    @@ -335,8 +346,9 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { if (mState == null) { throw new IllegalStateException("called stop on empty AnimatedImageDrawable"); } - nStop(mState.mNativePtr); - mRunning = false; + if (nStop(mState.mNativePtr)) { + postOnAnimationEnd(); + } } // Animatable2 overrides @@ -353,21 +365,31 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { nSetOnAnimationEndListener(mState.mNativePtr, this); } - mAnimationCallbacks.add(callback); + if (!mAnimationCallbacks.contains(callback)) { + mAnimationCallbacks.add(callback); + } } @Override public boolean unregisterAnimationCallback(@NonNull AnimationCallback callback) { - if (callback == null || mAnimationCallbacks == null) { + if (callback == null || mAnimationCallbacks == null + || !mAnimationCallbacks.remove(callback)) { return false; } - return mAnimationCallbacks.remove(callback); + if (mAnimationCallbacks.isEmpty()) { + clearAnimationCallbacks(); + } + + return true; } @Override public void clearAnimationCallbacks() { - mAnimationCallbacks = null; + if (mAnimationCallbacks != null) { + mAnimationCallbacks = null; + nSetOnAnimationEndListener(mState.mNativePtr, null); + } } private void postOnAnimationStart() { @@ -401,22 +423,48 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { return mHandler; } + /** + * Called by JNI. + * + * The JNI code has already posted this to the thread that created the + * callback, so no need to post. + */ + @SuppressWarnings("unused") + private void onAnimationEnd() { + if (mAnimationCallbacks != null) { + for (Animatable2.AnimationCallback callback : mAnimationCallbacks) { + callback.onAnimationEnd(this); + } + } + } + private static native long nCreate(long nativeImageDecoder, @Nullable ImageDecoder decoder, int width, int height, Rect cropRect) throws IOException; + @FastNative private static native long nGetNativeFinalizer(); private static native long nDraw(long nativePtr, long canvasNativePtr); + @FastNative private static native void nSetAlpha(long nativePtr, int alpha); + @FastNative private static native int nGetAlpha(long nativePtr); + @FastNative private static native void nSetColorFilter(long nativePtr, long nativeFilter); + @FastNative private static native boolean nIsRunning(long nativePtr); // Return whether the animation started. + @FastNative private static native boolean nStart(long nativePtr); - private static native void nStop(long nativePtr); + @FastNative + private static native boolean nStop(long nativePtr); + @FastNative private static native void nSetLoopCount(long nativePtr, int loopCount); // Pass the drawable down to native so it can call onAnimationEnd. private static native void nSetOnAnimationEndListener(long nativePtr, @Nullable AnimatedImageDrawable drawable); + @FastNative private static native long nNativeByteSize(long nativePtr); + @FastNative + private static native void nMarkInvisible(long nativePtr); } diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 7ad062a6f6f97a62a4031a5cd6667ad9da84c8cb..44b783bb6e63a87294209c23acc8e13520a8a973 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -27,6 +27,7 @@ import android.graphics.BitmapFactory; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.ImageDecoder; import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Outline; @@ -49,6 +50,7 @@ import com.android.internal.R; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -111,7 +113,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable() { - mBitmapState = new BitmapState((Bitmap) null); + init(new BitmapState((Bitmap) null), null); } /** @@ -124,8 +126,7 @@ public class BitmapDrawable extends Drawable { @SuppressWarnings("unused") @Deprecated public BitmapDrawable(Resources res) { - mBitmapState = new BitmapState((Bitmap) null); - mBitmapState.mTargetDensity = mTargetDensity; + init(new BitmapState((Bitmap) null), res); } /** @@ -135,7 +136,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(Bitmap bitmap) { - this(new BitmapState(bitmap), null); + init(new BitmapState(bitmap), null); } /** @@ -143,8 +144,7 @@ public class BitmapDrawable extends Drawable { * the display metrics of the resources. */ public BitmapDrawable(Resources res, Bitmap bitmap) { - this(new BitmapState(bitmap), res); - mBitmapState.mTargetDensity = mTargetDensity; + init(new BitmapState(bitmap), res); } /** @@ -154,10 +154,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(String filepath) { - this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); - if (mBitmapState.mBitmap == null) { - android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); - } + this(null, filepath); } /** @@ -165,10 +162,21 @@ public class BitmapDrawable extends Drawable { */ @SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" }) public BitmapDrawable(Resources res, String filepath) { - this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); - mBitmapState.mTargetDensity = mTargetDensity; - if (mBitmapState.mBitmap == null) { - android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); + Bitmap bitmap = null; + try (FileInputStream stream = new FileInputStream(filepath)) { + bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream), + (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); + } catch (Exception e) { + /* do nothing. This matches the behavior of BitmapFactory.decodeFile() + If the exception happened on decode, mBitmapState.mBitmap will be null. + */ + } finally { + init(new BitmapState(bitmap), res); + if (mBitmapState.mBitmap == null) { + android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); + } } } @@ -179,10 +187,7 @@ public class BitmapDrawable extends Drawable { */ @Deprecated public BitmapDrawable(java.io.InputStream is) { - this(new BitmapState(BitmapFactory.decodeStream(is)), null); - if (mBitmapState.mBitmap == null) { - android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); - } + this(null, is); } /** @@ -190,10 +195,21 @@ public class BitmapDrawable extends Drawable { */ @SuppressWarnings({ "unused", "ChainingConstructorIgnoresParameter" }) public BitmapDrawable(Resources res, java.io.InputStream is) { - this(new BitmapState(BitmapFactory.decodeStream(is)), null); - mBitmapState.mTargetDensity = mTargetDensity; - if (mBitmapState.mBitmap == null) { - android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); + Bitmap bitmap = null; + try { + bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is), + (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); + } catch (Exception e) { + /* do nothing. This matches the behavior of BitmapFactory.decodeStream() + If the exception happened on decode, mBitmapState.mBitmap will be null. + */ + } finally { + init(new BitmapState(bitmap), res); + if (mBitmapState.mBitmap == null) { + android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); + } } } @@ -812,9 +828,19 @@ public class BitmapDrawable extends Drawable { } } + int density = Bitmap.DENSITY_NONE; + if (value.density == TypedValue.DENSITY_DEFAULT) { + density = DisplayMetrics.DENSITY_DEFAULT; + } else if (value.density != TypedValue.DENSITY_NONE) { + density = value.density; + } + Bitmap bitmap = null; try (InputStream is = r.openRawResource(srcResId, value)) { - bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null); + ImageDecoder.Source source = ImageDecoder.createSource(r, is, density); + bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); } catch (Exception e) { // Do nothing and pick up the error below. } @@ -1013,14 +1039,21 @@ public class BitmapDrawable extends Drawable { } } + private BitmapDrawable(BitmapState state, Resources res) { + init(state, res); + } + /** - * The one constructor to rule them all. This is called by all public + * The one helper to rule them all. This is called by all public & private * constructors to set the state and initialize local properties. */ - private BitmapDrawable(BitmapState state, Resources res) { + private void init(BitmapState state, Resources res) { mBitmapState = state; - updateLocalState(res); + + if (mBitmapState != null && res != null) { + mBitmapState.mTargetDensity = mTargetDensity; + } } /** diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index f17cd768c386cdc590c8dc63aea0420531e44e15..36a4d26d62bb9cdca1077b46cb2f7cde66bdcc23 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -37,6 +37,7 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; +import android.graphics.ImageDecoder; import android.graphics.Insets; import android.graphics.NinePatch; import android.graphics.Outline; @@ -50,11 +51,13 @@ import android.graphics.Xfermode; import android.os.Trace; import android.util.AttributeSet; import android.util.DisplayMetrics; +import android.util.Log; import android.util.StateSet; import android.util.TypedValue; import android.util.Xml; import android.view.View; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; @@ -1175,6 +1178,10 @@ public abstract class Drawable { return null; } + if (opts == null) { + return getBitmapDrawable(res, value, is); + } + /* ugh. The decodeStream contract is that we have already allocated the pad rect, but if the bitmap does not had a ninepatch chunk, then the pad will be ignored. If we could change this to lazily @@ -1207,6 +1214,33 @@ public abstract class Drawable { return null; } + private static Drawable getBitmapDrawable(Resources res, TypedValue value, InputStream is) { + try { + ImageDecoder.Source source = null; + if (value != null) { + int density = Bitmap.DENSITY_NONE; + if (value.density == TypedValue.DENSITY_DEFAULT) { + density = DisplayMetrics.DENSITY_DEFAULT; + } else if (value.density != TypedValue.DENSITY_NONE) { + density = value.density; + } + source = ImageDecoder.createSource(res, is, density); + } else { + source = ImageDecoder.createSource(res, is); + } + + return ImageDecoder.decodeDrawable(source, (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); + } catch (IOException e) { + /* do nothing. + If the exception happened on decode, the drawable will be null. + */ + Log.e("Drawable", "Unable to decode stream: " + e); + } + return null; + } + /** * Create a drawable from an XML document. For more information on how to * create resources in XML, see @@ -1306,11 +1340,10 @@ public abstract class Drawable { } Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName); - try { - Bitmap bm = BitmapFactory.decodeFile(pathName); - if (bm != null) { - return drawableFromBitmap(null, bm, null, null, null, pathName); - } + try (FileInputStream stream = new FileInputStream(pathName)) { + return getBitmapDrawable(null, null, stream); + } catch(IOException e) { + // Do nothing; we will just return null if the FileInputStream had an error } finally { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 17900204fa22d9c13d4d1ec3c1dcab74edd34770..a56e8d1b25ed6b7938a8c81e5693ce3d8a7fbaa8 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -24,9 +24,9 @@ import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.ImageDecoder; import android.graphics.Insets; import android.graphics.NinePatch; import android.graphics.Outline; @@ -211,7 +211,8 @@ public class NinePatchDrawable extends Drawable { restoreAlpha = -1; } - final boolean needsDensityScaling = canvas.getDensity() == 0; + final boolean needsDensityScaling = canvas.getDensity() == 0 + && Bitmap.DENSITY_NONE != state.mNinePatch.getDensity(); if (needsDensityScaling) { restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save(); @@ -421,10 +422,6 @@ public class NinePatchDrawable extends Drawable { final int srcResId = a.getResourceId(R.styleable.NinePatchDrawable_src, 0); if (srcResId != 0) { - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inDither = !state.mDither; - options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi; - final Rect padding = new Rect(); final Rect opticalInsets = new Rect(); Bitmap bitmap = null; @@ -433,7 +430,17 @@ public class NinePatchDrawable extends Drawable { final TypedValue value = new TypedValue(); final InputStream is = r.openRawResource(srcResId, value); - bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options); + int density = Bitmap.DENSITY_NONE; + if (value.density == TypedValue.DENSITY_DEFAULT) { + density = DisplayMetrics.DENSITY_DEFAULT; + } else if (value.density != TypedValue.DENSITY_NONE) { + density = value.density; + } + ImageDecoder.Source source = ImageDecoder.createSource(r, is, density); + bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> { + decoder.setOutPaddingRect(padding); + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); is.close(); } catch (IOException e) { diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java index f721ed3af7ba45fc047853a0c246ad5e6cf4aa6f..09b3b9b523b42cc0e33966ab06ab2d3ad9567536 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java @@ -248,7 +248,8 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { spec.getUserAuthenticationValidityDurationSeconds(), spec.isUserAuthenticationValidWhileOnBody(), spec.isInvalidatedByBiometricEnrollment(), - GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */); + GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */, + spec.isUserConfirmationRequired()); } catch (IllegalStateException | IllegalArgumentException e) { throw new InvalidAlgorithmParameterException(e); } @@ -289,7 +290,8 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { spec.getUserAuthenticationValidityDurationSeconds(), spec.isUserAuthenticationValidWhileOnBody(), spec.isInvalidatedByBiometricEnrollment(), - GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */); + GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */, + spec.isUserConfirmationRequired()); if (spec.isTrustedUserPresenceRequired()) { args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED); } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java index d1eb6888bbfdcae9c8430e374734946fe7a0de67..e33e3cd4e92b3e76dfb069a32b9b428e38259da0 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -349,7 +349,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato mSpec.getUserAuthenticationValidityDurationSeconds(), mSpec.isUserAuthenticationValidWhileOnBody(), mSpec.isInvalidatedByBiometricEnrollment(), - GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */); + GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */, + mSpec.isUserConfirmationRequired()); } catch (IllegalArgumentException | IllegalStateException e) { throw new InvalidAlgorithmParameterException(e); } @@ -545,7 +546,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato mSpec.getUserAuthenticationValidityDurationSeconds(), mSpec.isUserAuthenticationValidWhileOnBody(), mSpec.isInvalidatedByBiometricEnrollment(), - GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */); + GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */, + mSpec.isUserConfirmationRequired()); args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart()); args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, mSpec.getKeyValidityForOriginationEnd()); diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java index 9df37f58fd091b738154c95d8ced276ac44d0d05..7bbc0996458456e3e48a4c7ee6ea2986fda3b38a 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java @@ -190,6 +190,8 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { && !keymasterSecureUserIds.contains(getGateKeeperSecureUserId()); } + boolean userConfirmationRequired = keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED); + return new KeyInfo(entryAlias, insideSecureHardware, origin, @@ -207,7 +209,8 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { userAuthenticationRequirementEnforcedBySecureHardware, userAuthenticationValidWhileOnBody, trustedUserPresenceRequred, - invalidatedByBiometricEnrollment); + invalidatedByBiometricEnrollment, + userConfirmationRequired); } private static BigInteger getGateKeeperSecureUserId() throws ProviderException { diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java index 440e0863fbb1ddb76d31f9a23797626db9be291b..05cc74a0bec957e7de0fc2c04a74617486286b01 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java @@ -502,7 +502,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { spec.getUserAuthenticationValidityDurationSeconds(), spec.isUserAuthenticationValidWhileOnBody(), spec.isInvalidatedByBiometricEnrollment(), - spec.getBoundToSpecificSecureUserId()); + spec.getBoundToSpecificSecureUserId(), + spec.isUserConfirmationRequired()); importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart()); importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, @@ -704,7 +705,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { params.getUserAuthenticationValidityDurationSeconds(), params.isUserAuthenticationValidWhileOnBody(), params.isInvalidatedByBiometricEnrollment(), - params.getBoundToSpecificSecureUserId()); + params.getBoundToSpecificSecureUserId(), + params.isUserConfirmationRequired()); KeymasterUtils.addMinMacLengthAuthorizationIfNecessary( args, keymasterAlgorithm, diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index a896c72463fb3a813607d24461ae726ad3977184..da23c70f58bb7b7d330d1357129c67b19476d83b 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -264,6 +264,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { private final boolean mUserAuthenticationValidWhileOnBody; private final boolean mInvalidatedByBiometricEnrollment; private final boolean mIsStrongBoxBacked; + private final boolean mUserConfirmationRequired; /** * @hide should be built with Builder @@ -293,7 +294,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { boolean uniqueIdIncluded, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, - boolean isStrongBoxBacked) { + boolean isStrongBoxBacked, + boolean userConfirmationRequired) { if (TextUtils.isEmpty(keyStoreAlias)) { throw new IllegalArgumentException("keyStoreAlias must not be empty"); } @@ -341,6 +343,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody; mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; mIsStrongBoxBacked = isStrongBoxBacked; + mUserConfirmationRequired = userConfirmationRequired; } /** @@ -546,6 +549,26 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { return mUserAuthenticationRequired; } + /** + * Returns {@code true} if the key is authorized to be used only for messages confirmed by the + * user. + * + * Confirmation is separate from user authentication (see + * {@link Builder#setUserAuthenticationRequired(boolean)}). Keys can be created that require + * confirmation but not user authentication, or user authentication but not confirmation, or + * both. Confirmation verifies that some user with physical possession of the device has + * approved a displayed message. User authentication verifies that the correct user is present + * and has authenticated. + * + *

    This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. + * + * @see Builder#setUserConfirmationRequired(boolean) + */ + public boolean isUserConfirmationRequired() { + return mUserConfirmationRequired; + } + /** * Gets the duration of time (seconds) for which this key is authorized to be used after the * user is successfully authenticated. This has effect only if user authentication is required @@ -675,6 +698,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { private boolean mUserAuthenticationValidWhileOnBody; private boolean mInvalidatedByBiometricEnrollment = true; private boolean mIsStrongBoxBacked = false; + private boolean mUserConfirmationRequired; /** * Creates a new instance of the {@code Builder}. @@ -1062,6 +1086,29 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { return this; } + /** + * Sets whether this key is authorized to be used only for messages confirmed by the + * user. + * + * Confirmation is separate from user authentication (see + * {@link #setUserAuthenticationRequired(boolean)}). Keys can be created that require + * confirmation but not user authentication, or user authentication but not confirmation, + * or both. Confirmation verifies that some user with physical possession of the device has + * approved a displayed message. User authentication verifies that the correct user is + * present and has authenticated. + * + *

    This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. + * + * @see {@link android.security.ConfirmationPrompter ConfirmationPrompter} class for + * more details about user confirmations. + */ + @NonNull + public Builder setUserConfirmationRequired(boolean required) { + mUserConfirmationRequired = required; + return this; + } + /** * Sets the duration of time (seconds) for which this key is authorized to be used after the * user is successfully authenticated. This has effect if the key requires user @@ -1249,7 +1296,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { mUniqueIdIncluded, mUserAuthenticationValidWhileOnBody, mInvalidatedByBiometricEnrollment, - mIsStrongBoxBacked); + mIsStrongBoxBacked, + mUserConfirmationRequired); } } } diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java index 864f62a6de04d56528e38cc7601ad7c0e443107d..0a75cd5268b7bb4ef87730e9e5df5aecdd9c6c4e 100644 --- a/keystore/java/android/security/keystore/KeyInfo.java +++ b/keystore/java/android/security/keystore/KeyInfo.java @@ -82,6 +82,7 @@ public class KeyInfo implements KeySpec { private final boolean mUserAuthenticationValidWhileOnBody; private final boolean mTrustedUserPresenceRequired; private final boolean mInvalidatedByBiometricEnrollment; + private final boolean mUserConfirmationRequired; /** * @hide @@ -103,7 +104,8 @@ public class KeyInfo implements KeySpec { boolean userAuthenticationRequirementEnforcedBySecureHardware, boolean userAuthenticationValidWhileOnBody, boolean trustedUserPresenceRequired, - boolean invalidatedByBiometricEnrollment) { + boolean invalidatedByBiometricEnrollment, + boolean userConfirmationRequired) { mKeystoreAlias = keystoreKeyAlias; mInsideSecureHardware = insideSecureHardware; mOrigin = origin; @@ -125,6 +127,7 @@ public class KeyInfo implements KeySpec { mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody; mTrustedUserPresenceRequired = trustedUserPresenceRequired; mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; + mUserConfirmationRequired = userConfirmationRequired; } /** @@ -259,6 +262,27 @@ public class KeyInfo implements KeySpec { return mUserAuthenticationRequired; } + /** + * Returns {@code true} if the key is authorized to be used only for messages confirmed by the + * user. + * + * Confirmation is separate from user authentication (see + * {@link #isUserAuthenticationRequired()}). Keys can be created that require confirmation but + * not user authentication, or user authentication but not confirmation, or both. Confirmation + * verifies that some user with physical possession of the device has approved a displayed + * message. User authentication verifies that the correct user is present and has + * authenticated. + * + *

    This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. + * + * @see KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean) + * @see KeyProtection.Builder#setUserConfirmationRequired(boolean) + */ + public boolean isUserConfirmationRequired() { + return mUserConfirmationRequired; + } + /** * Gets the duration of time (seconds) for which this key is authorized to be used after the * user is successfully authenticated. This has effect only if user authentication is required diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index dbacb9c53dd68af383a4121d78add996434dcf39..b5b328192f2110f2fab35237896faa537deb016f 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -228,6 +228,7 @@ public final class KeyProtection implements ProtectionParameter { private final boolean mInvalidatedByBiometricEnrollment; private final long mBoundToSecureUserId; private final boolean mCriticalToDeviceEncryption; + private final boolean mUserConfirmationRequired; private KeyProtection( Date keyValidityStart, @@ -244,7 +245,8 @@ public final class KeyProtection implements ProtectionParameter { boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, long boundToSecureUserId, - boolean criticalToDeviceEncryption) { + boolean criticalToDeviceEncryption, + boolean userConfirmationRequired) { mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart); mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd); mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd); @@ -262,6 +264,7 @@ public final class KeyProtection implements ProtectionParameter { mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; mBoundToSecureUserId = boundToSecureUserId; mCriticalToDeviceEncryption = criticalToDeviceEncryption; + mUserConfirmationRequired = userConfirmationRequired; } /** @@ -395,6 +398,26 @@ public final class KeyProtection implements ProtectionParameter { return mUserAuthenticationRequired; } + /** + * Returns {@code true} if the key is authorized to be used only for messages confirmed by the + * user. + * + * Confirmation is separate from user authentication (see + * {@link #isUserAuthenticationRequired()}). Keys can be created that require confirmation but + * not user authentication, or user authentication but not confirmation, or both. Confirmation + * verifies that some user with physical possession of the device has approved a displayed + * message. User authentication verifies that the correct user is present and has + * authenticated. + * + *

    This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. + * + * @see Builder#setUserConfirmationRequired(boolean) + */ + public boolean isUserConfirmationRequired() { + return mUserConfirmationRequired; + } + /** * Gets the duration of time (seconds) for which this key is authorized to be used after the * user is successfully authenticated. This has effect only if user authentication is required @@ -488,6 +511,7 @@ public final class KeyProtection implements ProtectionParameter { private int mUserAuthenticationValidityDurationSeconds = -1; private boolean mUserAuthenticationValidWhileOnBody; private boolean mInvalidatedByBiometricEnrollment = true; + private boolean mUserConfirmationRequired; private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID; private boolean mCriticalToDeviceEncryption = false; @@ -718,6 +742,29 @@ public final class KeyProtection implements ProtectionParameter { return this; } + /** + * Sets whether this key is authorized to be used only for messages confirmed by the + * user. + * + * Confirmation is separate from user authentication (see + * {@link #setUserAuthenticationRequired(boolean)}). Keys can be created that require + * confirmation but not user authentication, or user authentication but not confirmation, + * or both. Confirmation verifies that some user with physical possession of the device has + * approved a displayed message. User authentication verifies that the correct user is + * present and has authenticated. + * + *

    This authorization applies only to secret key and private key operations. Public key + * operations are not restricted. + * + * @see {@link android.security.ConfirmationPrompter ConfirmationPrompter} class for + * more details about user confirmations. + */ + @NonNull + public Builder setUserConfirmationRequired(boolean required) { + mUserConfirmationRequired = required; + return this; + } + /** * Sets the duration of time (seconds) for which this key is authorized to be used after the * user is successfully authenticated. This has effect if the key requires user @@ -866,7 +913,8 @@ public final class KeyProtection implements ProtectionParameter { mUserAuthenticationValidWhileOnBody, mInvalidatedByBiometricEnrollment, mBoundToSecureUserId, - mCriticalToDeviceEncryption); + mCriticalToDeviceEncryption, + mUserConfirmationRequired); } } } diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java index 34c8d1f75f6038fec5931b32bea27c64976c9fcc..4e28601f17a11b11080904e018f032991e00c6d0 100644 --- a/keystore/java/android/security/keystore/KeymasterUtils.java +++ b/keystore/java/android/security/keystore/KeymasterUtils.java @@ -16,6 +16,7 @@ package android.security.keystore; +import android.util.Log; import android.hardware.fingerprint.FingerprintManager; import android.security.GateKeeper; import android.security.KeyStore; @@ -93,6 +94,8 @@ public abstract class KeymasterUtils { * overriding the default logic in this method where the key is bound to either the root * SID of the current user, or the fingerprint SID if explicit fingerprint authorization * is requested. + * @param userConfirmationRequired whether user confirmation is required to authorize the use + * of the key. * @throws IllegalStateException if user authentication is required but the system is in a wrong * state (e.g., secure lock screen not set up) for generating or importing keys that * require user authentication. @@ -102,7 +105,12 @@ public abstract class KeymasterUtils { int userAuthenticationValidityDurationSeconds, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, - long boundToSpecificSecureUserId) { + long boundToSpecificSecureUserId, + boolean userConfirmationRequired) { + if (userConfirmationRequired) { + args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED); + } + if (!userAuthenticationRequired) { args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); return; diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 17f9b7cd62fcef272810a0b4cc59b2965a79765a..24d819e93ff2a6b44bcf675a2d15bbdcaa0d43f3 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -134,10 +134,13 @@ cc_defaults { name: "libhwui_defaults", defaults: ["hwui_defaults"], + shared_libs: ["libstatslog"], + whole_static_libs: ["libskia"], srcs: [ "hwui/AnimatedImageDrawable.cpp", + "hwui/AnimatedImageThread.cpp", "hwui/Bitmap.cpp", "font/CacheTexture.cpp", "font/Font.cpp", @@ -317,7 +320,10 @@ cc_test { "libgmock", "libhwui_static_debug", ], - shared_libs: ["libmemunreachable"], + shared_libs: [ + "libmemunreachable", + "libstatslog", + ], cflags: [ "-include debug/wrap_gles.h", "-DHWUI_NULL_GPU", @@ -382,7 +388,10 @@ cc_benchmark { // set to libhwui_static_debug to skip actual GL commands whole_static_libs: ["libhwui"], - shared_libs: ["libmemunreachable"], + shared_libs: [ + "libmemunreachable", + "libstatslog", + ], srcs: [ "tests/macrobench/TestSceneRunner.cpp", @@ -404,7 +413,10 @@ cc_benchmark { ], whole_static_libs: ["libhwui_static_debug"], - shared_libs: ["libmemunreachable"], + shared_libs: [ + "libmemunreachable", + "libstatslog", + ], srcs: [ "tests/microbench/main.cpp", diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index f41956cdebeb4363f30c785a87c0bc08082c1055..ab27a0d00246f39cce5763d1af8f46b88e466308 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -164,6 +165,7 @@ void JankTracker::finishFrame(const FrameInfo& frame) { ALOGI("%s", ss.str().c_str()); // Just so we have something that counts up, the value is largely irrelevant ATRACE_INT(ss.str().c_str(), ++sDaveyCount); + android::util::stats_write(android::util::DAVEY_OCCURRED, ns2ms(totalDuration)); } } diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 3d2c2520624b3534dedcd0cc17e3f24ed61d8e20..55f4d895265c0c32671025ff4fd47a86468c4856 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -507,12 +507,20 @@ public: getOutline().getAlpha() != 0.0f; } - SkColor getShadowColor() const { - return mPrimitiveFields.mShadowColor; + SkColor getSpotShadowColor() const { + return mPrimitiveFields.mSpotShadowColor; } - bool setShadowColor(SkColor shadowColor) { - return RP_SET(mPrimitiveFields.mShadowColor, shadowColor); + bool setSpotShadowColor(SkColor shadowColor) { + return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor); + } + + SkColor getAmbientShadowColor() const { + return mPrimitiveFields.mAmbientShadowColor; + } + + bool setAmbientShadowColor(SkColor shadowColor) { + return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor); } bool fitsOnLayer() const { @@ -538,7 +546,8 @@ private: int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0; int mWidth = 0, mHeight = 0; int mClippingFlags = CLIP_TO_BOUNDS; - SkColor mShadowColor = SK_ColorBLACK; + SkColor mSpotShadowColor = SK_ColorBLACK; + SkColor mAmbientShadowColor = SK_ColorBLACK; float mAlpha = 1; float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0; float mElevation = 0; diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp index e01bf3d003e69697a08211cca3e57056fdf32e49..2bded9b3a2d8803dcc735859b4a46f52fad857b7 100644 --- a/libs/hwui/hwui/AnimatedImageDrawable.cpp +++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp @@ -15,21 +15,21 @@ */ #include "AnimatedImageDrawable.h" +#include "AnimatedImageThread.h" -#include "thread/Task.h" -#include "thread/TaskManager.h" -#include "thread/TaskProcessor.h" #include "utils/TraceUtils.h" #include #include -#include #include +#include namespace android { AnimatedImageDrawable::AnimatedImageDrawable(sk_sp animatedImage) - : mSkAnimatedImage(std::move(animatedImage)) { } + : mSkAnimatedImage(std::move(animatedImage)) { + mTimeToShowNextSnapshot = mSkAnimatedImage->currentFrameDuration(); +} void AnimatedImageDrawable::syncProperties() { mAlpha = mStagingAlpha; @@ -37,88 +37,83 @@ void AnimatedImageDrawable::syncProperties() { } bool AnimatedImageDrawable::start() { - SkAutoExclusive lock(mLock); - if (mSkAnimatedImage->isRunning()) { + if (mRunning) { return false; } - if (!mSnapshot) { - mSnapshot.reset(mSkAnimatedImage->newPictureSnapshot()); - } + // This will trigger a reset. + mFinished = true; - // While stopped, update() does not decode, but it does advance the time. - // This prevents us from skipping ahead when we resume. - const double currentTime = SkTime::GetMSecs(); - mSkAnimatedImage->update(currentTime); - mSkAnimatedImage->start(); - return mSkAnimatedImage->isRunning(); + mRunning = true; + return true; } -void AnimatedImageDrawable::stop() { - SkAutoExclusive lock(mLock); - mSkAnimatedImage->stop(); +bool AnimatedImageDrawable::stop() { + bool wasRunning = mRunning; + mRunning = false; + return wasRunning; } bool AnimatedImageDrawable::isRunning() { - return mSkAnimatedImage->isRunning(); + return mRunning; } -// This is really a Task but that doesn't really work when Future<> -// expects to be able to get/set a value -class AnimatedImageDrawable::AnimatedImageTask : public uirenderer::Task { -public: - AnimatedImageTask(AnimatedImageDrawable* animatedImageDrawable) - : mAnimatedImageDrawable(sk_ref_sp(animatedImageDrawable)) {} - - sk_sp mAnimatedImageDrawable; - bool mIsCompleted = false; -}; - -class AnimatedImageDrawable::AnimatedImageTaskProcessor : public uirenderer::TaskProcessor { -public: - explicit AnimatedImageTaskProcessor(uirenderer::TaskManager* taskManager) - : uirenderer::TaskProcessor(taskManager) {} - ~AnimatedImageTaskProcessor() {} - - virtual void onProcess(const sp>& task) override { - ATRACE_NAME("Updating AnimatedImageDrawables"); - AnimatedImageTask* t = static_cast(task.get()); - t->mAnimatedImageDrawable->update(); - t->mIsCompleted = true; - task->setResult(true); - }; -}; - -void AnimatedImageDrawable::scheduleUpdate(uirenderer::TaskManager* taskManager) { - if (!mSkAnimatedImage->isRunning() - || (mDecodeTask.get() != nullptr && !mDecodeTask->mIsCompleted)) { - return; - } - - if (!mDecodeTaskProcessor.get()) { - mDecodeTaskProcessor = new AnimatedImageTaskProcessor(taskManager); - } - - // TODO get one frame ahead and only schedule updates when you need to replenish - mDecodeTask = new AnimatedImageTask(this); - mDecodeTaskProcessor->add(mDecodeTask); +bool AnimatedImageDrawable::nextSnapshotReady() const { + return mNextSnapshot.valid() && + mNextSnapshot.wait_for(std::chrono::seconds(0)) == std::future_status::ready; } -void AnimatedImageDrawable::update() { - SkAutoExclusive lock(mLock); +// Only called on the RenderThread while UI thread is locked. +bool AnimatedImageDrawable::isDirty() { + const double currentTime = SkTime::GetMSecs(); + const double lastWallTime = mLastWallTime; - if (!mSkAnimatedImage->isRunning()) { - return; + mLastWallTime = currentTime; + if (!mRunning) { + mDidDraw = false; + return false; } - const double currentTime = SkTime::GetMSecs(); - if (currentTime >= mNextFrameTime) { - mNextFrameTime = mSkAnimatedImage->update(currentTime); - mSnapshot.reset(mSkAnimatedImage->newPictureSnapshot()); - mIsDirty = true; + std::unique_lock lock{mSwapLock}; + if (mDidDraw) { + mCurrentTime += currentTime - lastWallTime; + mDidDraw = false; + } + + if (!mNextSnapshot.valid()) { + // Need to trigger onDraw in order to start decoding the next frame. + return true; + } + + return nextSnapshotReady() && mCurrentTime >= mTimeToShowNextSnapshot; +} + +// Only called on the AnimatedImageThread. +AnimatedImageDrawable::Snapshot AnimatedImageDrawable::decodeNextFrame() { + Snapshot snap; + { + std::unique_lock lock{mImageLock}; + snap.mDuration = mSkAnimatedImage->decodeNextFrame(); + snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot()); } + + return snap; } +// Only called on the AnimatedImageThread. +AnimatedImageDrawable::Snapshot AnimatedImageDrawable::reset() { + Snapshot snap; + { + std::unique_lock lock{mImageLock}; + mSkAnimatedImage->reset(); + snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot()); + snap.mDuration = mSkAnimatedImage->currentFrameDuration(); + } + + return snap; +} + +// Only called on the RenderThread. void AnimatedImageDrawable::onDraw(SkCanvas* canvas) { SkTLazy lazyPaint; if (mAlpha != SK_AlphaOPAQUE || mColorFilter.get()) { @@ -128,25 +123,70 @@ void AnimatedImageDrawable::onDraw(SkCanvas* canvas) { lazyPaint.get()->setFilterQuality(kLow_SkFilterQuality); } - SkAutoExclusive lock(mLock); - if (mSnapshot) { - canvas->drawPicture(mSnapshot, nullptr, lazyPaint.getMaybeNull()); - } else { - // TODO: we could potentially keep the cached surface around if there is a paint and we know - // the drawable is attached to the view system + mDidDraw = true; + + bool drewDirectly = false; + if (!mSnapshot.mPic) { + // The image is not animating, and never was. Draw directly from + // mSkAnimatedImage. SkAutoCanvasRestore acr(canvas, false); if (lazyPaint.isValid()) { canvas->saveLayer(mSkAnimatedImage->getBounds(), lazyPaint.get()); } + + std::unique_lock lock{mImageLock}; mSkAnimatedImage->draw(canvas); + drewDirectly = true; + } + + if (mRunning && mFinished) { + auto& thread = uirenderer::AnimatedImageThread::getInstance(); + mNextSnapshot = thread.reset(sk_ref_sp(this)); + mFinished = false; + } + + bool finalFrame = false; + if (mRunning && nextSnapshotReady()) { + std::unique_lock lock{mSwapLock}; + if (mCurrentTime >= mTimeToShowNextSnapshot) { + mSnapshot = mNextSnapshot.get(); + const double timeToShowCurrentSnap = mTimeToShowNextSnapshot; + if (mSnapshot.mDuration == SkAnimatedImage::kFinished) { + finalFrame = true; + mRunning = false; + mFinished = true; + } else { + mTimeToShowNextSnapshot += mSnapshot.mDuration; + if (mCurrentTime >= mTimeToShowNextSnapshot) { + // This would mean showing the current frame very briefly. It's + // possible that not being displayed for a time resulted in + // mCurrentTime being far ahead. Prevent showing many frames + // rapidly by going back to the beginning of this frame time. + mCurrentTime = timeToShowCurrentSnap; + } + } + } + } + + if (mRunning && !mNextSnapshot.valid()) { + auto& thread = uirenderer::AnimatedImageThread::getInstance(); + mNextSnapshot = thread.decodeNextFrame(sk_ref_sp(this)); } - mIsDirty = false; + if (!drewDirectly) { + // No other thread will modify mCurrentSnap so this should be safe to + // use without locking. + canvas->drawPicture(mSnapshot.mPic, nullptr, lazyPaint.getMaybeNull()); + } + + if (finalFrame) { + if (mEndListener) { + mEndListener->onAnimationEnd(); + } + } } double AnimatedImageDrawable::drawStaging(SkCanvas* canvas) { - // update the drawable with the current time - double nextUpdate = mSkAnimatedImage->update(SkTime::GetMSecs()); SkAutoCanvasRestore acr(canvas, false); if (mStagingAlpha != SK_AlphaOPAQUE || mStagingColorFilter.get()) { SkPaint paint; @@ -154,8 +194,59 @@ double AnimatedImageDrawable::drawStaging(SkCanvas* canvas) { paint.setColorFilter(mStagingColorFilter); canvas->saveLayer(mSkAnimatedImage->getBounds(), &paint); } - canvas->drawDrawable(mSkAnimatedImage.get()); - return nextUpdate; + + if (mFinished && !mRunning) { + // Continue drawing the last frame, and return 0 to indicate no need to + // redraw. + std::unique_lock lock{mImageLock}; + canvas->drawDrawable(mSkAnimatedImage.get()); + return 0.0; + } + + bool update = false; + { + const double currentTime = SkTime::GetMSecs(); + std::unique_lock lock{mSwapLock}; + // mLastWallTime starts off at 0. If it is still 0, just update it to + // the current time and avoid updating + if (mLastWallTime == 0.0) { + mCurrentTime = currentTime; + } else if (mRunning) { + if (mFinished) { + mCurrentTime = currentTime; + { + std::unique_lock lock{mImageLock}; + mSkAnimatedImage->reset(); + } + mTimeToShowNextSnapshot = currentTime + mSkAnimatedImage->currentFrameDuration(); + } else { + mCurrentTime += currentTime - mLastWallTime; + update = mCurrentTime >= mTimeToShowNextSnapshot; + } + } + mLastWallTime = currentTime; + } + + double duration = 0.0; + { + std::unique_lock lock{mImageLock}; + if (update) { + duration = mSkAnimatedImage->decodeNextFrame(); + } + + canvas->drawDrawable(mSkAnimatedImage.get()); + } + + std::unique_lock lock{mSwapLock}; + if (update) { + if (duration == SkAnimatedImage::kFinished) { + mRunning = false; + mFinished = true; + } else { + mTimeToShowNextSnapshot += duration; + } + } + return mTimeToShowNextSnapshot; } -}; // namespace android +} // namespace android diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h index df8a5e48d18e715181fc13197b024802b36a8dbd..2fd6f40b71b5a49ef843f100d1fe6b6678bcd505 100644 --- a/libs/hwui/hwui/AnimatedImageDrawable.h +++ b/libs/hwui/hwui/AnimatedImageDrawable.h @@ -17,22 +17,20 @@ #pragma once #include +#include #include #include #include #include #include -#include +#include -class SkPicture; +#include +#include namespace android { -namespace uirenderer { -class TaskManager; -} - class OnAnimationEndListener { public: virtual ~OnAnimationEndListener() {} @@ -41,68 +39,104 @@ public: }; /** - * Native component of android.graphics.drawable.AnimatedImageDrawables.java. This class can be - * drawn into Canvas.h and maintains the state needed to drive the animation from the RenderThread. + * Native component of android.graphics.drawable.AnimatedImageDrawables.java. + * This class can be drawn into Canvas.h and maintains the state needed to drive + * the animation from the RenderThread. */ class ANDROID_API AnimatedImageDrawable : public SkDrawable { public: AnimatedImageDrawable(sk_sp animatedImage); /** - * This returns true if the animation has updated and signals that the next draw will contain - * new content. + * This updates the internal time and returns true if the animation needs + * to be redrawn. + * + * This is called on RenderThread, while the UI thread is locked. */ - bool isDirty() const { return mIsDirty; } + bool isDirty(); int getStagingAlpha() const { return mStagingAlpha; } void setStagingAlpha(int alpha) { mStagingAlpha = alpha; } void setStagingColorFilter(sk_sp filter) { mStagingColorFilter = filter; } void syncProperties(); - virtual SkRect onGetBounds() override { - return mSkAnimatedImage->getBounds(); - } + virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); } + // Draw to software canvas, and return time to next draw. double drawStaging(SkCanvas* canvas); - // Returns true if the animation was started; false otherwise (e.g. it was already running) + // Returns true if the animation was started; false otherwise (e.g. it was + // already running) bool start(); - void stop(); + // Returns true if the animation was stopped; false otherwise (e.g. it was + // already stopped) + bool stop(); bool isRunning(); - void setRepetitionCount(int count) { - mSkAnimatedImage->setRepetitionCount(count); - } + void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); } void setOnAnimationEndListener(std::unique_ptr listener) { mEndListener = std::move(listener); } - void scheduleUpdate(uirenderer::TaskManager* taskManager); + void markInvisible() { mDidDraw = false; } + + struct Snapshot { + sk_sp mPic; + int mDuration; + + Snapshot() = default; + + Snapshot(Snapshot&&) = default; + Snapshot& operator=(Snapshot&&) = default; + + PREVENT_COPY_AND_ASSIGN(Snapshot); + }; + + // These are only called on AnimatedImageThread. + Snapshot decodeNextFrame(); + Snapshot reset(); protected: virtual void onDraw(SkCanvas* canvas) override; private: - void update(); - sk_sp mSkAnimatedImage; - sk_sp mSnapshot; - SkMutex mLock; + bool mRunning = false; + bool mFinished = false; + + // A snapshot of the current frame to draw. + Snapshot mSnapshot; + + std::future mNextSnapshot; + + bool nextSnapshotReady() const; + + // When to switch from mSnapshot to mNextSnapshot. + double mTimeToShowNextSnapshot = 0.0; + + // The current time for the drawable itself. + double mCurrentTime = 0.0; + + // The wall clock of the last time we called isDirty. + double mLastWallTime = 0.0; + + // Whether we drew since the last call to isDirty. + bool mDidDraw = false; + + // Locked when assigning snapshots and times. Operations while this is held + // should be short. + std::mutex mSwapLock; + + // Locked when mSkAnimatedImage is being updated or drawn. + std::mutex mImageLock; int mStagingAlpha = SK_AlphaOPAQUE; sk_sp mStagingColorFilter; int mAlpha = SK_AlphaOPAQUE; sk_sp mColorFilter; - double mNextFrameTime = 0.0; - bool mIsDirty = false; - - class AnimatedImageTask; - class AnimatedImageTaskProcessor; - sp mDecodeTask; - sp mDecodeTaskProcessor; std::unique_ptr mEndListener; }; -}; // namespace android +} // namespace android diff --git a/libs/hwui/hwui/AnimatedImageThread.cpp b/libs/hwui/hwui/AnimatedImageThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8990039875e2e8310e5e345b3c3c5b63921559e --- /dev/null +++ b/libs/hwui/hwui/AnimatedImageThread.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AnimatedImageThread.h" + +#include + +namespace android { +namespace uirenderer { + +AnimatedImageThread& AnimatedImageThread::getInstance() { + static AnimatedImageThread* sInstance = new AnimatedImageThread(); + return *sInstance; +} + +AnimatedImageThread::AnimatedImageThread() { + setpriority(PRIO_PROCESS, 0, PRIORITY_NORMAL + PRIORITY_MORE_FAVORABLE); + start("AnimatedImageThread"); +} + +std::future AnimatedImageThread::decodeNextFrame( + const sk_sp& drawable) { + return queue().async([drawable]() { return drawable->decodeNextFrame(); }); +} + +std::future AnimatedImageThread::reset( + const sk_sp& drawable) { + return queue().async([drawable]() { return drawable->reset(); }); +} + +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/hwui/AnimatedImageThread.h b/libs/hwui/hwui/AnimatedImageThread.h new file mode 100644 index 0000000000000000000000000000000000000000..9e3537430d5aae87e9c03eb788e78f6635c7e7e4 --- /dev/null +++ b/libs/hwui/hwui/AnimatedImageThread.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANIMATEDIMAGETHREAD_H_ +#define ANIMATEDIMAGETHREAD_H_ + +#include "AnimatedImageDrawable.h" +#include "thread/ThreadBase.h" + +#include + +namespace android { + +namespace uirenderer { + +class AnimatedImageThread : private ThreadBase { + PREVENT_COPY_AND_ASSIGN(AnimatedImageThread); + +public: + static AnimatedImageThread& getInstance(); + + std::future decodeNextFrame( + const sk_sp&); + std::future reset(const sk_sp&); + +private: + AnimatedImageThread(); +}; + +} // namespace uirenderer + +} // namespace android + +#endif // ANIMATEDIMAGETHREAD_H_ diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp index ba877d395c8f97e0949705ecada1e6eb9d8770d9..a0d000dd2179e766c8f59170b3fdfb1b33733844 100644 --- a/libs/hwui/hwui/MinikinUtils.cpp +++ b/libs/hwui/hwui/MinikinUtils.cpp @@ -31,7 +31,7 @@ minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint, const Typeface* typeface) { const Typeface* resolvedFace = Typeface::resolveDefault(typeface); - minikin::MinikinPaint minikinPaint; + minikin::MinikinPaint minikinPaint(resolvedFace->fFontCollection); /* Prepare minikin Paint */ minikinPaint.size = paint->isLinearText() ? paint->getTextSize() : static_cast(paint->getTextSize()); @@ -44,7 +44,6 @@ minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint, minikinPaint.familyVariant = paint->getFamilyVariant(); minikinPaint.fontStyle = resolvedFace->fStyle; minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings(); - minikinPaint.hyphenEdit = minikin::HyphenEdit(paint->getHyphenEdit()); return minikinPaint; } @@ -53,21 +52,25 @@ minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFla size_t count, size_t bufSize, minikin::MeasuredText* mt, int mtOffset) { minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); - const auto& fc = Typeface::resolveDefault(typeface)->fFontCollection; minikin::Layout layout; + const minikin::U16StringPiece textBuf(buf, bufSize); + const minikin::Range range(start, start + count); + const minikin::HyphenEdit hyphenEdit = static_cast(paint->getHyphenEdit()); + const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit); + const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); + if (mt == nullptr) { - layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint, fc); + layout.doLayout(textBuf,range, bidiFlags, minikinPaint, startHyphen, endHyphen); return layout; } - if (mt->buildLayout(minikin::U16StringPiece(buf, bufSize), - minikin::Range(start, start + count), - minikinPaint, fc, bidiFlags, mtOffset, &layout)) { + if (mt->buildLayout(textBuf, range, minikinPaint, bidiFlags, mtOffset, startHyphen, endHyphen, + &layout)) { return layout; } - layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint, fc); + layout.doLayout(textBuf, range, bidiFlags, minikinPaint, startHyphen, endHyphen); return layout; } @@ -75,10 +78,14 @@ float MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags, const Typeface* typeface, const uint16_t* buf, size_t start, size_t count, size_t bufSize, float* advances) { minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); - const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface); - return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinPaint, - resolvedTypeface->fFontCollection, advances, - nullptr /* extent */); + const minikin::U16StringPiece textBuf(buf, bufSize); + const minikin::Range range(start, start + count); + const minikin::HyphenEdit hyphenEdit = static_cast(paint->getHyphenEdit()); + const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit); + const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); + + return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen, + endHyphen, advances, nullptr /* extent */); } bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) { diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index ebc14c8b675b8cee5a1bec0febf97e863edd84d2..091b5267881d67b95879dcddd79328f6810c0f65 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -182,10 +182,11 @@ void Typeface::setRobotoTypefaceForTest() { std::shared_ptr font = std::make_shared( std::move(typeface), data, st.st_size, 0, std::vector()); - std::shared_ptr family = std::make_shared( - std::vector({minikin::Font(std::move(font), minikin::FontStyle())})); - std::shared_ptr collection = - std::make_shared(std::move(family)); + std::vector fonts; + fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle())); + + std::shared_ptr collection = std::make_shared( + std::make_shared(std::move(fonts))); Typeface* hwTypeface = new Typeface(); hwTypeface->fFontCollection = collection; diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp index 7b59ccf3eec73a08399663d6f3ad5b8665a9568a..25c51f2716e62c3314c7ade235df05afc9b1e65e 100644 --- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp @@ -111,6 +111,10 @@ void EndReorderBarrierDrawable::onDraw(SkCanvas* canvas) { } } +static SkColor multiplyAlpha(SkColor color, float alpha) { + return SkColorSetA(color, alpha * SkColorGetA(color)); +} + // copied from FrameBuilder::deferShadow void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) { const RenderProperties& casterProperties = caster->getNodeProperties(); @@ -187,9 +191,11 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* } else { zParams = SkPoint3::Make(0, 0, casterProperties.getZ()); } + SkColor ambientColor = multiplyAlpha(casterProperties.getAmbientShadowColor(), ambientAlpha); + SkColor spotColor = multiplyAlpha(casterProperties.getSpotShadowColor(), spotAlpha); SkShadowUtils::DrawShadow( canvas, *casterPath, zParams, skiaLightPos, SkiaPipeline::getLightRadius(), - ambientAlpha, spotAlpha, casterProperties.getShadowColor(), + ambientColor, spotColor, casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0); } diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp index cf0b6a4d1dccba343f5ee04e49d197fbfaca54b4..aa14699ae4c201e7b11d5351a9c56ea6e4769b35 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp @@ -98,8 +98,6 @@ bool SkiaDisplayList::prepareListAndChildren( isDirty = true; } if (animatedImage->isRunning()) { - static_cast(info.canvasContext.getRenderPipeline()) - ->scheduleDeferredUpdate(animatedImage); info.out.hasAnimations = true; } } diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 534782a5dc022aaa7cf79d56ec1abed4d54964c3..9db39d954e4c70a10046f5898594ba2170ff4eee 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -40,7 +40,6 @@ uint8_t SkiaPipeline::mSpotShadowAlpha = 0; Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN}; SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) { - mAnimatedImageDrawables.reserve(30); mVectorDrawables.reserve(30); } @@ -327,15 +326,6 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli ATRACE_NAME("flush commands"); surface->getCanvas()->flush(); - - // TODO move to another method - if (!mAnimatedImageDrawables.empty()) { - ATRACE_NAME("Update AnimatedImageDrawables"); - for (auto animatedImage : mAnimatedImageDrawables) { - animatedImage->scheduleUpdate(getTaskManager()); - } - mAnimatedImageDrawables.clear(); - } } namespace { diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index cc75e9c5b38d7501a925d04076f6370dc89bdd47..3800194440f9ace8ade50ab8e19dc712983e0203 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -55,12 +55,6 @@ public: std::vector* getVectorDrawables() { return &mVectorDrawables; } - void scheduleDeferredUpdate(AnimatedImageDrawable* imageDrawable) { - mAnimatedImageDrawables.push_back(imageDrawable); - } - - std::vector* getAnimatingImages() { return &mAnimatedImageDrawables; } - static void destroyLayer(RenderNode* node); static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap); @@ -144,11 +138,6 @@ private: */ std::vector mVectorDrawables; - /** - * populated by prepareTree with images with active animations - */ - std::vector mAnimatedImageDrawables; - // Block of properties used only for debugging to record a SkPicture and save it in a file. /** * mCapturedFile is used to enforce we don't capture more than once for a given name (cause diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp index 66d6f527e60477ea58d8c370bb3f8d0e440b9067..2232c25de3456fb1a63e78496e061bee2b3348f3 100644 --- a/libs/hwui/tests/unit/TypefaceTests.cpp +++ b/libs/hwui/tests/unit/TypefaceTests.cpp @@ -56,8 +56,9 @@ std::shared_ptr buildFamily(const char* fileName) { LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", fileName); std::shared_ptr font = std::make_shared( std::move(typeface), data, st.st_size, 0, std::vector()); - return std::make_shared( - std::vector({minikin::Font(std::move(font), minikin::FontStyle())})); + std::vector fonts; + fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle())); + return std::make_shared(std::move(fonts)); } std::vector> makeSingleFamlyVector(const char* fileName) { diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp index 1904d40ea67ac41e71c00fc7f234d0993eb6d1a4..f24abaed2dceaffbaf20ef7d0dbe21422197648e 100644 --- a/libs/protoutil/src/ProtoOutputStream.cpp +++ b/libs/protoutil/src/ProtoOutputStream.cpp @@ -249,15 +249,15 @@ ProtoOutputStream::start(uint64_t fieldId) } uint32_t id = (uint32_t)fieldId; + size_t prevPos = mBuffer.wp()->pos(); mBuffer.writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED); - size_t sizePos = mBuffer.wp()->pos(); mDepth++; mObjectId++; mBuffer.writeRawFixed64(mExpectedObjectToken); // push previous token into stack. - mExpectedObjectToken = makeToken(get_varint_size(id), + mExpectedObjectToken = makeToken(sizePos - prevPos, (bool)(fieldId & FIELD_COUNT_REPEATED), mDepth, mObjectId, sizePos); return mExpectedObjectToken; } diff --git a/libs/services/src/os/DropBoxManager.cpp b/libs/services/src/os/DropBoxManager.cpp index f5685d9ca75358a7d23ae72398a5fea0a4279c6f..c2907a66fb9969aef8c61579586d8cbd403f0b3c 100644 --- a/libs/services/src/os/DropBoxManager.cpp +++ b/libs/services/src/os/DropBoxManager.cpp @@ -208,6 +208,11 @@ DropBoxManager::addFile(const String16& tag, const string& filename, int flags) Status DropBoxManager::addFile(const String16& tag, int fd, int flags) { + if (fd == -1) { + string message("invalid fd (-1) passed to to addFile"); + ALOGW("DropboxManager: %s", message.c_str()); + return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, message.c_str()); + } Entry entry(tag, flags, fd); return add(entry); } @@ -235,4 +240,3 @@ DropBoxManager::getNextEntry(const String16& tag, long msec, Entry* entry) } }} // namespace android::os - diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 018db9a7fc9d631139ff9d735375efe8bf3a2d0e..fa3f99a90cc8bcb0e922a72364c48c2bc6f13ae2 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -88,11 +88,6 @@ interface ILocationManager boolean providerMeetsCriteria(String provider, in Criteria criteria); ProviderProperties getProviderProperties(String provider); String getNetworkProviderPackage(); - boolean isProviderEnabled(String provider); - boolean isProviderEnabledForUser(String provider, int userId); - boolean setProviderEnabledForUser(String provider, boolean enabled, int userId); - boolean isLocationEnabledForUser(int userId); - void setLocationEnabledForUser(boolean enabled, int userId); void addTestProvider(String name, in ProviderProperties properties, String opPackageName); void removeTestProvider(String provider, String opPackageName); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index c33dce1777bba2f3ed771b728d7bf06b1956a09c..d3c6eddd02eb4ee2daaa8f59a0ca902bf246b9f9 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -236,6 +236,62 @@ public class LocationManager { */ public static final String GNSS_HARDWARE_MODEL_NAME_UNKNOWN = "Model Name Unknown"; + /** + * Broadcast intent action for Settings app to inject a footer at the bottom of location + * settings. + * + *

    This broadcast is used for two things: + *

      + *
    1. For receivers to inject a footer with provided text. This is for use only by apps + * that are included in the system image.
    2. + *
    3. For receivers to know their footer is injected under location settings.
    4. + *
    + * + *

    To inject a footer to location settings, you must declare a broadcast receiver of + * {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} in the manifest as so: + *

    +     *     <receiver android:name="com.example.android.footer.MyFooterInjector">
    +     *         <intent-filter>
    +     *             <action android:name="com.android.settings.location.INJECT_FOOTER" />
    +     *         </intent-filter>
    +     *         <meta-data
    +     *             android:name="com.android.settings.location.FOOTER_STRING"
    +     *             android:resource="@string/my_injected_footer_string" />
    +     *     </receiver>
    +     * 
    + * + *

    On entering location settings, Settings app will send a + * {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast to receivers whose footer is successfully + * injected. On leaving location settings, the footer becomes not visible to users. Settings app + * will send a {@link #SETTINGS_FOOTER_REMOVED_ACTION} broadcast to those receivers. + * + * @hide + */ + public static final String SETTINGS_FOOTER_DISPLAYED_ACTION = + "com.android.settings.location.DISPLAYED_FOOTER"; + + /** + * Broadcast intent action when location settings footer is not visible to users. + * + *

    See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use. + * + * @hide + */ + public static final String SETTINGS_FOOTER_REMOVED_ACTION = + "com.android.settings.location.REMOVED_FOOTER"; + + /** + * Metadata name for {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast + * receivers to specify a string resource id as location settings footer text. This is for use + * only by apps that are included in the system image. + * + *

    See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use. + * + * @hide + */ + public static final String METADATA_SETTINGS_FOOTER_STRING = + "com.android.settings.location.FOOTER_STRING"; + // Map from LocationListeners to their associated ListenerTransport objects private HashMap mListeners = new HashMap(); diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java index 603926f4fe4df62dca846f67f76376ba7b01048f..98e67c21c1a1459af70d6dbc426ac94f40229403 100644 --- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java +++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java @@ -17,7 +17,9 @@ package com.android.internal.location.gnssmetrics; import android.os.SystemClock; +import android.os.connectivity.GpsBatteryStats; +import android.text.format.DateUtils; import android.util.Base64; import android.util.Log; import android.util.TimeUtils; @@ -26,6 +28,7 @@ import java.util.Arrays; import com.android.internal.app.IBatteryStats; import com.android.internal.location.nano.GnssLogsProto.GnssLog; +import com.android.internal.location.nano.GnssLogsProto.PowerMetrics; /** * GnssMetrics: Is used for logging GNSS metrics @@ -171,6 +174,7 @@ public class GnssMetrics { msg.standardDeviationTopFourAverageCn0DbHz = topFourAverageCn0Statistics.getStandardDeviation(); } + msg.powerMetrics = mGnssPowerMetrics.buildProto(); String s = Base64.encodeToString(GnssLog.toByteArray(msg), Base64.DEFAULT); reset(); return s; @@ -218,6 +222,21 @@ public class GnssMetrics { topFourAverageCn0Statistics.getStandardDeviation()).append("\n"); } s.append("GNSS_KPI_END").append("\n"); + GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats(); + if (stats != null) { + s.append("Power Metrics").append('\n'); + long[] t = stats.getTimeInGpsSignalQualityLevel(); + if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) { + s.append(" Amount of time (while on battery) Top 4 Avg CN0 > " + + Double.toString(GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) + + " dB-Hz (min): ").append(t[1] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n"); + s.append(" Amount of time (while on battery) Top 4 Avg CN0 <= " + + Double.toString(GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) + + " dB-Hz (min): ").append(t[0] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n"); + } + s.append(" Energy consumed while on battery (mAh): ").append( + stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS)).append("\n"); + } return s.toString(); } @@ -294,7 +313,7 @@ public class GnssMetrics { private class GnssPowerMetrics { /* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */ - private static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0; + public static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0; /* Minimum change in Top Four Average CN0 needed to trigger a report */ private static final double REPORTING_THRESHOLD_DB_HZ = 1.0; @@ -312,6 +331,38 @@ public class GnssMetrics { mLastAverageCn0 = -100.0; } + /** + * Builds power metrics proto buf. This is included in the gnss proto buf. + * @return PowerMetrics + */ + public PowerMetrics buildProto() { + PowerMetrics p = new PowerMetrics(); + GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats(); + if (stats != null) { + p.loggingDurationMs = stats.getLoggingDurationMs(); + p.energyConsumedMah = stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS); + long[] t = stats.getTimeInGpsSignalQualityLevel(); + p.timeInSignalQualityLevelMs = new long[t.length]; + for (int i = 0; i < t.length; i++) { + p.timeInSignalQualityLevelMs[i] = t[i]; + } + } + return p; + } + + /** + * Returns the GPS power stats + * @return GpsBatteryStats + */ + public GpsBatteryStats getGpsBatteryStats() { + try { + return mBatteryStats.getGpsBatteryStats(); + } catch (Exception e) { + Log.w(TAG, "Exception", e); + return null; + } + } + /** * Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0. If * the number of SVs seen is less than 4, then signal quality is the average CN0. @@ -347,4 +398,4 @@ public class GnssMetrics { return GnssMetrics.GPS_SIGNAL_QUALITY_POOR; } } -} \ No newline at end of file +} diff --git a/lowpan/java/android/net/lowpan/LowpanManager.java b/lowpan/java/android/net/lowpan/LowpanManager.java index 2d974ee79e407972389fc5eba90c7c5e5cb996a3..76876ce01c96d9cd3e8f996b2548abbf22ae2aa1 100644 --- a/lowpan/java/android/net/lowpan/LowpanManager.java +++ b/lowpan/java/android/net/lowpan/LowpanManager.java @@ -57,7 +57,7 @@ public class LowpanManager { * This design pattern allows us to skip removal of items * from this Map without leaking memory. */ - private final Map> mBinderCache = + private final Map> mBinderCache = new WeakHashMap<>(); private final ILowpanManager mService; @@ -107,6 +107,20 @@ public class LowpanManager { mLooper = looper; } + /** @hide */ + @Nullable + public LowpanInterface getInterfaceNoCreate(@NonNull ILowpanInterface ifaceService) { + LowpanInterface iface = null; + + synchronized (mBinderCache) { + if (mBinderCache.containsKey(ifaceService.asBinder())) { + iface = mBinderCache.get(ifaceService.asBinder()).get(); + } + } + + return iface; + } + /** @hide */ @Nullable public LowpanInterface getInterface(@NonNull ILowpanInterface ifaceService) { @@ -114,8 +128,8 @@ public class LowpanManager { try { synchronized (mBinderCache) { - if (mBinderCache.containsKey(ifaceService)) { - iface = mBinderCache.get(ifaceService).get(); + if (mBinderCache.containsKey(ifaceService.asBinder())) { + iface = mBinderCache.get(ifaceService.asBinder()).get(); } if (iface == null) { @@ -127,7 +141,7 @@ public class LowpanManager { mInterfaceCache.put(iface.getName(), iface); } - mBinderCache.put(ifaceService, new WeakReference(iface)); + mBinderCache.put(ifaceService.asBinder(), new WeakReference(iface)); /* Make sure we remove the object from the * interface cache if the associated service @@ -260,7 +274,7 @@ public class LowpanManager { public void onInterfaceRemoved(ILowpanInterface ifaceService) { Runnable runnable = () -> { - LowpanInterface iface = getInterface(ifaceService); + LowpanInterface iface = getInterfaceNoCreate(ifaceService); if (iface != null) { cb.onInterfaceRemoved(iface); diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 41f9f09fbb880144b55d6e9f032c4942a08bcfa2..3d879f5a46602cceecca96c8a6ac297f6493b73a 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -22,6 +22,7 @@ import android.util.SparseIntArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Objects; import java.util.TreeSet; /** @@ -176,6 +177,19 @@ public final class AudioDeviceInfo { } } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AudioDeviceInfo that = (AudioDeviceInfo) o; + return Objects.equals(getPort(), that.getPort()); + } + + @Override + public int hashCode() { + return Objects.hash(getPort()); + } + private final AudioDevicePort mPort; AudioDeviceInfo(AudioDevicePort port) { diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java index 5d0c8e234d401801f03d098cd8e9da56733ab816..5467a69ea0bb9aa0217c6899f9c7dcd3beb87dd3 100644 --- a/media/java/android/media/AudioFocusInfo.java +++ b/media/java/android/media/AudioFocusInfo.java @@ -38,6 +38,10 @@ public final class AudioFocusInfo implements Parcelable { private int mLossReceived; private int mFlags; + // generation count for the validity of a request/response async exchange between + // external focus policy and MediaFocusControl + private long mGenCount = -1; + /** * Class constructor @@ -61,6 +65,16 @@ public final class AudioFocusInfo implements Parcelable { mSdkTarget = sdk; } + /** @hide */ + public void setGen(long g) { + mGenCount = g; + } + + /** @hide */ + public long getGen() { + return mGenCount; + } + /** * The audio attributes for the audio focus request. @@ -128,6 +142,7 @@ public final class AudioFocusInfo implements Parcelable { dest.writeInt(mLossReceived); dest.writeInt(mFlags); dest.writeInt(mSdkTarget); + dest.writeLong(mGenCount); } @Override @@ -168,6 +183,8 @@ public final class AudioFocusInfo implements Parcelable { if (mSdkTarget != other.mSdkTarget) { return false; } + // mGenCount is not used to verify equality between two focus holds as multiple requests + // (hence of different generations) could correspond to the same hold return true; } @@ -175,7 +192,7 @@ public final class AudioFocusInfo implements Parcelable { = new Parcelable.Creator() { public AudioFocusInfo createFromParcel(Parcel in) { - return new AudioFocusInfo( + final AudioFocusInfo afi = new AudioFocusInfo( AudioAttributes.CREATOR.createFromParcel(in), //AudioAttributes aa in.readInt(), // int clientUid in.readString(), //String clientId @@ -185,6 +202,8 @@ public final class AudioFocusInfo implements Parcelable { in.readInt(), //int flags in.readInt() //int sdkTarget ); + afi.setGen(in.readLong()); + return afi; } public AudioFocusInfo[] newArray(int size) { diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index b07d042200464e53bc06ffce9cced38fdd258a73..f98480b280017810ba4a383892a7470f2edb6082 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -265,6 +265,12 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_AAC_XHE = 16; /** Audio data format: AC-4 sync frame transport format */ public static final int ENCODING_AC4 = 17; + /** Audio data format: E-AC-3-JOC compressed + * E-AC-3-JOC streams can be decoded by downstream devices supporting {@link #ENCODING_E_AC3}. + * Use {@link #ENCODING_E_AC3} as the AudioTrack encoding when the downstream device + * supports {@link #ENCODING_E_AC3} but not {@link #ENCODING_E_AC3_JOC}. + **/ + public static final int ENCODING_E_AC3_JOC = 18; /** @hide */ public static String toLogFriendlyEncoding(int enc) { @@ -512,6 +518,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_PCM_FLOAT: case ENCODING_AC3: case ENCODING_E_AC3: + case ENCODING_E_AC3_JOC: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_MP3: @@ -537,6 +544,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_PCM_FLOAT: case ENCODING_AC3: case ENCODING_E_AC3: + case ENCODING_E_AC3_JOC: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_IEC61937: @@ -564,6 +572,7 @@ public final class AudioFormat implements Parcelable { return true; case ENCODING_AC3: case ENCODING_E_AC3: + case ENCODING_E_AC3_JOC: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_MP3: @@ -593,6 +602,7 @@ public final class AudioFormat implements Parcelable { return true; case ENCODING_AC3: case ENCODING_E_AC3: + case ENCODING_E_AC3_JOC: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_MP3: @@ -829,6 +839,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_PCM_FLOAT: case ENCODING_AC3: case ENCODING_E_AC3: + case ENCODING_E_AC3_JOC: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_IEC61937: @@ -1044,6 +1055,7 @@ public final class AudioFormat implements Parcelable { ENCODING_PCM_FLOAT, ENCODING_AC3, ENCODING_E_AC3, + ENCODING_E_AC3_JOC, ENCODING_DTS, ENCODING_DTS_HD, ENCODING_IEC61937, diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 22fa6202df5cb2835cb9acfc05754ac8e3769376..0be54ec2b2d9b0e5c725c70869204d5fb78257ff 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.media.audiopolicy.AudioPolicy; +import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.MediaSessionLegacyHelper; @@ -48,14 +49,19 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; import android.view.KeyEvent; +import com.android.internal.annotations.GuardedBy; + +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -2336,6 +2342,20 @@ public class AudioManager { } } } + + @Override + public void dispatchFocusResultFromExtPolicy(int requestResult, String clientId) { + synchronized (mFocusRequestsLock) { + // TODO use generation counter as the key instead + final BlockingFocusResultReceiver focusReceiver = + mFocusRequestsAwaitingResult.remove(clientId); + if (focusReceiver != null) { + focusReceiver.notifyResult(requestResult); + } else { + Log.e(TAG, "dispatchFocusResultFromExtPolicy found no result receiver"); + } + } + } }; private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) { @@ -2388,6 +2408,40 @@ public class AudioManager { */ public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; + /** @hide */ + @IntDef(flag = false, prefix = "AUDIOFOCUS_REQUEST", value = { + AUDIOFOCUS_REQUEST_FAILED, + AUDIOFOCUS_REQUEST_GRANTED, + AUDIOFOCUS_REQUEST_DELAYED } + ) + @Retention(RetentionPolicy.SOURCE) + public @interface FocusRequestResult {} + + /** + * @hide + * code returned when a synchronous focus request on the client-side is to be blocked + * until the external audio focus policy decides on the response for the client + */ + public static final int AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY = 100; + + /** + * Timeout duration in ms when waiting on an external focus policy for the result for a + * focus request + */ + private static final int EXT_FOCUS_POLICY_TIMEOUT_MS = 200; + + private static final String FOCUS_CLIENT_ID_STRING = "android_audio_focus_client_id"; + + private final Object mFocusRequestsLock = new Object(); + /** + * Map of all receivers of focus request results, one per unresolved focus request. + * Receivers are added before sending the request to the external focus policy, + * and are removed either after receiving the result, or after the timeout. + * This variable is lazily initialized. + */ + @GuardedBy("mFocusRequestsLock") + private HashMap mFocusRequestsAwaitingResult; + /** * Request audio focus. @@ -2654,18 +2708,100 @@ public class AudioManager { // some tests don't have a Context sdk = Build.VERSION.SDK_INT; } - try { - status = service.requestAudioFocus(afr.getAudioAttributes(), - afr.getFocusGain(), mICallBack, - mAudioFocusDispatcher, - getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()), - getContext().getOpPackageName() /* package name */, afr.getFlags(), - ap != null ? ap.cb() : null, - sdk); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + + final String clientId = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()); + final BlockingFocusResultReceiver focusReceiver; + synchronized (mFocusRequestsLock) { + try { + // TODO status contains result and generation counter for ext policy + status = service.requestAudioFocus(afr.getAudioAttributes(), + afr.getFocusGain(), mICallBack, + mAudioFocusDispatcher, + clientId, + getContext().getOpPackageName() /* package name */, afr.getFlags(), + ap != null ? ap.cb() : null, + sdk); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) { + // default path with no external focus policy + return status; + } + if (mFocusRequestsAwaitingResult == null) { + mFocusRequestsAwaitingResult = + new HashMap(1); + } + focusReceiver = new BlockingFocusResultReceiver(clientId); + mFocusRequestsAwaitingResult.put(clientId, focusReceiver); + } + focusReceiver.waitForResult(EXT_FOCUS_POLICY_TIMEOUT_MS); + if (DEBUG && !focusReceiver.receivedResult()) { + Log.e(TAG, "requestAudio response from ext policy timed out, denying request"); + } + synchronized (mFocusRequestsLock) { + mFocusRequestsAwaitingResult.remove(clientId); + } + return focusReceiver.requestResult(); + } + + // helper class that abstracts out the handling of spurious wakeups in Object.wait() + private static final class SafeWaitObject { + private boolean mQuit = false; + + public void safeNotify() { + synchronized (this) { + mQuit = true; + this.notify(); + } + } + + public void safeWait(long millis) throws InterruptedException { + final long timeOutTime = java.lang.System.currentTimeMillis() + millis; + synchronized (this) { + while (!mQuit) { + final long timeToWait = timeOutTime - java.lang.System.currentTimeMillis(); + if (timeToWait < 0) { break; } + this.wait(timeToWait); + } + } + } + } + + private static final class BlockingFocusResultReceiver { + private final SafeWaitObject mLock = new SafeWaitObject(); + @GuardedBy("mLock") + private boolean mResultReceived = false; + // request denied by default (e.g. timeout) + private int mFocusRequestResult = AudioManager.AUDIOFOCUS_REQUEST_FAILED; + private final String mFocusClientId; + + BlockingFocusResultReceiver(String clientId) { + mFocusClientId = clientId; + } + + boolean receivedResult() { return mResultReceived; } + int requestResult() { return mFocusRequestResult; } + + void notifyResult(int requestResult) { + synchronized (mLock) { + mResultReceived = true; + mFocusRequestResult = requestResult; + mLock.safeNotify(); + } + } + + public void waitForResult(long timeOutMs) { + synchronized (mLock) { + if (mResultReceived) { + // the result was received before waiting + return; + } + try { + mLock.safeWait(timeOutMs); + } catch (InterruptedException e) { } + } } - return status; } /** @@ -2710,6 +2846,32 @@ public class AudioManager { } } + /** + * @hide + * Set the result to the audio focus request received through + * {@link AudioPolicyFocusListener#onAudioFocusRequest(AudioFocusInfo, int)}. + * @param afi the information about the focus requester + * @param requestResult the result to the focus request to be passed to the requester + * @param ap a valid registered {@link AudioPolicy} configured as a focus policy. + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public void setFocusRequestResult(@NonNull AudioFocusInfo afi, + @FocusRequestResult int requestResult, @NonNull AudioPolicy ap) { + if (afi == null) { + throw new IllegalArgumentException("Illegal null AudioFocusInfo"); + } + if (ap == null) { + throw new IllegalArgumentException("Illegal null AudioPolicy"); + } + final IAudioService service = getService(); + try { + service.setFocusRequestResultFromExtPolicy(afi, requestResult, ap.cb()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * @hide * Notifies an application with a focus listener of gain or loss of audio focus. @@ -4578,6 +4740,51 @@ public class AudioManager { } } + /** + * Set port id for microphones by matching device type and address. + * @hide + */ + public static void setPortIdForMicrophones(ArrayList microphones) { + AudioDeviceInfo[] devices = getDevicesStatic(AudioManager.GET_DEVICES_INPUTS); + for (int i = microphones.size() - 1; i >= 0; i--) { + boolean foundPortId = false; + for (AudioDeviceInfo device : devices) { + if (device.getPort().type() == microphones.get(i).getInternalDeviceType() + && TextUtils.equals(device.getAddress(), microphones.get(i).getAddress())) { + microphones.get(i).setId(device.getId()); + foundPortId = true; + break; + } + } + if (!foundPortId) { + Log.i(TAG, "Failed to find port id for device with type:" + + microphones.get(i).getType() + " address:" + + microphones.get(i).getAddress()); + microphones.remove(i); + } + } + } + + /** + * Returns a list of {@link MicrophoneInfo} that corresponds to the characteristics + * of all available microphones. The list is empty when no microphones are available + * on the device. An error during the query will result in an IOException being thrown. + * + * @return a list that contains all microphones' characteristics + * @throws IOException if an error occurs. + */ + public List getMicrophones() throws IOException { + ArrayList microphones = new ArrayList(); + int status = AudioSystem.getMicrophones(microphones); + if (status != AudioManager.SUCCESS) { + // fail and bail! + Log.e(TAG, "getMicrophones failed:" + status); + return new ArrayList(); // Always return a list. + } + setPortIdForMicrophones(microphones); + return microphones; + } + // Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the // (unpredictable) last time updateAudioPortCache() was called by someone, keep a list // of the ports that exist at the time of the last notification. diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java new file mode 100644 index 0000000000000000000000000000000000000000..4652c180936c9d00efc2a47408434ec6c0a5f830 --- /dev/null +++ b/media/java/android/media/AudioPresentation.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + + +/** + * The AudioPresentation class encapsulates the information that describes an audio presentation + * which is available in next generation audio content. + * + * Used by {@link MediaExtractor} {@link MediaExtractor#getAudioPresentations(int)} and + * {@link AudioTrack} {@link AudioTrack#setPresentation(AudioPresentation)} to query available + * presentations and to select one. + * + * A list of available audio presentations in a media source can be queried using + * {@link MediaExtractor#getAudioPresentations(int)}. This list can be presented to a user for + * selection. + * An AudioPresentation can be passed to an offloaded audio decoder via + * {@link AudioTrack#setPresentation(AudioPresentation)} to request decoding of the selected + * presentation. An audio stream may contain multiple presentations that differ by language, + * accessibility, end point mastering and dialogue enhancement. An audio presentation may also have + * a set of description labels in different languages to help the user to make an informed + * selection. + */ +public final class AudioPresentation { + private final int mPresentationId; + private final int mProgramId; + private final Map mLabels; + private final String mLanguage; + + /** @hide */ + @IntDef( + value = { + MASTERING_NOT_INDICATED, + MASTERED_FOR_STEREO, + MASTERED_FOR_SURROUND, + MASTERED_FOR_3D, + MASTERED_FOR_HEADPHONE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MasteringIndicationType {} + + private final @MasteringIndicationType int mMasteringIndication; + private final boolean mAudioDescriptionAvailable; + private final boolean mSpokenSubtitlesAvailable; + private final boolean mDialogueEnhancementAvailable; + + /** + * No preferred reproduction channel layout. + */ + public static final int MASTERING_NOT_INDICATED = 0; + /** + * Stereo speaker layout. + */ + public static final int MASTERED_FOR_STEREO = 1; + /** + * Two-dimensional (e.g. 5.1) speaker layout. + */ + public static final int MASTERED_FOR_SURROUND = 2; + /** + * Three-dimensional (e.g. 5.1.2) speaker layout. + */ + public static final int MASTERED_FOR_3D = 3; + /** + * Prerendered for headphone playback. + */ + public static final int MASTERED_FOR_HEADPHONE = 4; + + AudioPresentation(int presentationId, + int programId, + Map labels, + String language, + @MasteringIndicationType int masteringIndication, + boolean audioDescriptionAvailable, + boolean spokenSubtitlesAvailable, + boolean dialogueEnhancementAvailable) { + this.mPresentationId = presentationId; + this.mProgramId = programId; + this.mLanguage = language; + this.mMasteringIndication = masteringIndication; + this.mAudioDescriptionAvailable = audioDescriptionAvailable; + this.mSpokenSubtitlesAvailable = spokenSubtitlesAvailable; + this.mDialogueEnhancementAvailable = dialogueEnhancementAvailable; + + this.mLabels = new HashMap(labels); + } + + /** + * The framework uses this presentation id to select an audio presentation rendered by a + * decoder. Presentation id is typically sequential, but does not have to be. + * @hide + */ + public int getPresentationId() { + return mPresentationId; + } + + /** + * The framework uses this program id to select an audio presentation rendered by a decoder. + * Program id can be used to further uniquely identify the presentation to a decoder. + * @hide + */ + public int getProgramId() { + return mProgramId; + } + + /** + * @return a map of available text labels for this presentation. Each label is indexed by its + * locale corresponding to the language code as specified by ISO 639-2 [42]. Either ISO 639-2/B + * or ISO 639-2/T could be used. + */ + public Map getLabels() { + Map localeLabels = new HashMap<>(); + for (Map.Entry entry : mLabels.entrySet()) { + localeLabels.put(new Locale(entry.getKey()), entry.getValue()); + } + return localeLabels; + } + + /** + * @return the locale corresponding to audio presentation's ISO 639-1/639-2 language code. + */ + public Locale getLocale() { + return new Locale(mLanguage); + } + + /** + * @return the mastering indication of the audio presentation. + * See {@link #MASTERING_NOT_INDICATED}, {@link #MASTERED_FOR_STEREO}, + * {@link #MASTERED_FOR_SURROUND}, {@link #MASTERED_FOR_3D}, {@link #MASTERED_FOR_HEADPHONE} + */ + @MasteringIndicationType + public int getMasteringIndication() { + return mMasteringIndication; + } + + /** + * Indicates whether an audio description for the visually impaired is available. + * @return {@code true} if audio description is available. + */ + public boolean hasAudioDescription() { + return mAudioDescriptionAvailable; + } + + /** + * Indicates whether spoken subtitles for the visually impaired are available. + * @return {@code true} if spoken subtitles are available. + */ + public boolean hasSpokenSubtitles() { + return mSpokenSubtitlesAvailable; + } + + /** + * Indicates whether dialogue enhancement is available. + * @return {@code true} if dialogue enhancement is available. + */ + public boolean hasDialogueEnhancement() { + return mDialogueEnhancementAvailable; + } +} diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index eb6e83065fe9bd56adef27c386daa388c8dac2d5..d0963cbcb87f01e3421d633cf9372853506ab132 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -16,12 +16,15 @@ package android.media; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.util.Collection; import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; import android.annotation.IntDef; import android.annotation.NonNull; @@ -35,6 +38,7 @@ import android.os.Message; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; @@ -1601,6 +1605,32 @@ public class AudioRecord implements AudioRouting } } + //-------------------------------------------------------------------------- + // Microphone information + //-------------------- + /** + * Returns a lists of {@link MicrophoneInfo} representing the active microphones. + * By querying channel mapping for each active microphone, developer can know how + * the microphone is used by each channels or a capture stream. + * Note that the information about the active microphones may change during a recording. + * See {@link AudioManager#registerAudioDeviceCallback} to be notified of changes + * in the audio devices, querying the active microphones then will return the latest + * information. + * + * @return a lists of {@link MicrophoneInfo} representing the active microphones. + * @throws IOException if an error occurs + */ + public List getActiveMicrophones() throws IOException { + ArrayList activeMicrophones = new ArrayList<>(); + int status = native_get_active_microphones(activeMicrophones); + if (status != AudioManager.SUCCESS) { + Log.e(TAG, "getActiveMicrophones failed:" + status); + return new ArrayList(); + } + AudioManager.setPortIdForMicrophones(activeMicrophones); + return activeMicrophones; + } + //--------------------------------------------------------- // Interface definitions //-------------------- @@ -1746,6 +1776,9 @@ public class AudioRecord implements AudioRouting private native final int native_get_timestamp(@NonNull AudioTimestamp outTimestamp, @AudioTimestamp.Timebase int timebase); + private native final int native_get_active_microphones( + ArrayList activeMicrophones); + //--------------------------------------------------------- // Utility methods //------------------ diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index dcd37dafd4955ce6bea633494b34d9c477a94ea2..be9fcb8fae83543e5c4292f97852a8a04e51b3a1 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -827,6 +827,8 @@ public class AudioSystem private static native boolean native_is_offload_supported(int encoding, int sampleRate, int channelMask, int channelIndexMask); + public static native int getMicrophones(ArrayList microphonesInfo); + // Items shared with audio service /** diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 4e9ce8e23e9c8c19ff1ed125d5f5f67b3426ff30..8e822a5d7a373d0a4695f81d1c6c7256d783ed5b 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -2007,6 +2007,25 @@ public class AudioTrack extends PlayerBase return native_set_loop(startInFrames, endInFrames, loopCount); } + /** + * Sets the audio presentation. + * If the audio presentation is invalid then {@link #ERROR_BAD_VALUE} will be returned. + * If a multi-stream decoder (MSD) is not present, or the format does not support + * multiple presentations, then {@link #ERROR_INVALID_OPERATION} will be returned. + * @param presentation see {@link AudioPresentation}. In particular, id should be set. + * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, + * {@link #ERROR_INVALID_OPERATION} + * @throws IllegalArgumentException if the audio presentation is null. + * @throws IllegalStateException if track is not initialized. + */ + public int setPresentation(@NonNull AudioPresentation presentation) { + if (presentation == null) { + throw new IllegalArgumentException("audio presentation is null"); + } + return native_setPresentation(presentation.getPresentationId(), + presentation.getProgramId()); + } + /** * Sets the initialization state of the instance. This method was originally intended to be used * in an AudioTrack subclass constructor to set a subclass-specific post-initialization state. @@ -3245,6 +3264,7 @@ public class AudioTrack extends PlayerBase @NonNull VolumeShaper.Operation operation); private native @Nullable VolumeShaper.State native_getVolumeShaperState(int id); + private native final int native_setPresentation(int presentationId, int programId); //--------------------------------------------------------- // Utility methods diff --git a/media/java/android/media/IAudioFocusDispatcher.aidl b/media/java/android/media/IAudioFocusDispatcher.aidl index 09575f733e328dd485b207c210011eff58465a9d..3b33c5b7a46a0aae75b573df8b209fab7b4f1ce4 100644 --- a/media/java/android/media/IAudioFocusDispatcher.aidl +++ b/media/java/android/media/IAudioFocusDispatcher.aidl @@ -25,4 +25,6 @@ oneway interface IAudioFocusDispatcher { void dispatchAudioFocusChange(int focusChange, String clientId); + void dispatchFocusResultFromExtPolicy(int requestResult, String clientId); + } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 88d0a60880261e48ca97e21cefaa8fcfd22e34f4..cd4143cf3120127c5bbfd2cf325f076420177aca 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -207,5 +207,8 @@ interface IAudioService { int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent); + oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult, + in IAudioPolicyCallback pcb); + // WARNING: read warning at top of file, it is recommended to add new methods at the end } diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java index 5ad4313c03326688489d438357d878c62ada4ec2..5cb831356472595a18ff238e9a2cca8bbc611383 100644 --- a/media/java/android/media/MediaBrowser2.java +++ b/media/java/android/media/MediaBrowser2.java @@ -19,7 +19,6 @@ package android.media; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.content.Context; import android.media.update.ApiLoader; import android.media.update.MediaBrowser2Provider; @@ -41,14 +40,14 @@ public class MediaBrowser2 extends MediaController2 { */ public static class BrowserCallback extends MediaController2.ControllerCallback { /** - * Called with the result of {@link #getBrowserRoot(Bundle)}. + * Called with the result of {@link #getLibraryRoot(Bundle)}. *

    - * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the browser root isn't + * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the library root isn't * available. * * @param rootHints rootHints that you previously requested. - * @param rootMediaId media id of the browser root. Can be {@code null} - * @param rootExtra extra of the browser root. Can be {@code null} + * @param rootMediaId media id of the library root. Can be {@code null} + * @param rootExtra extra of the library root. Can be {@code null} */ public void onGetRootResult(Bundle rootHints, @Nullable String rootMediaId, @Nullable Bundle rootExtra) { } @@ -114,8 +113,15 @@ public class MediaBrowser2 extends MediaController2 { .createMediaBrowser2(context, this, token, executor, (BrowserCallback) callback); } - public void getBrowserRoot(Bundle rootHints) { - mProvider.getBrowserRoot_impl(rootHints); + /** + * Get the library root. Result would be sent back asynchronously with the + * {@link BrowserCallback#onGetRootResult(Bundle, String, Bundle)}. + * + * @param rootHints hint for the root + * @see BrowserCallback#onGetRootResult(Bundle, String, Bundle) + */ + public void getLibraryRoot(Bundle rootHints) { + mProvider.getLibraryRoot_impl(rootHints); } /** diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java index 3d27a4894d0a352f9cad8fa2927540520c7757e3..e9ffe60ec32d4969f315349dad71ed2cdd93d7e7 100644 --- a/media/java/android/media/MediaController2.java +++ b/media/java/android/media/MediaController2.java @@ -30,6 +30,7 @@ import android.media.MediaSession2.PlaylistParams; import android.media.session.MediaSessionManager; import android.media.update.ApiLoader; import android.media.update.MediaController2Provider; +import android.media.update.PlaybackInfoProvider; import android.net.Uri; import android.os.Bundle; import android.os.ResultReceiver; @@ -104,7 +105,7 @@ public class MediaController2 implements AutoCloseable { * * @param info new playback info */ - public void onAudioInfoChanged(PlaybackInfo info) { } + public void onPlaybackInfoChanged(PlaybackInfo info) { } /** * Called when the allowed commands are changed by session. @@ -131,7 +132,7 @@ public class MediaController2 implements AutoCloseable { public void onPlaylistChanged(@NonNull List playlist) { } /** - * Called when the playback state is changed, or connection success. + * Called when the playback state is changed. * * @param state latest playback state */ @@ -160,21 +161,22 @@ public class MediaController2 implements AutoCloseable { */ public static final int PLAYBACK_TYPE_LOCAL = 1; - private final int mVolumeType; - private final int mVolumeControl; - private final int mMaxVolume; - private final int mCurrentVolume; - private final AudioAttributes mAudioAttrs; + private final PlaybackInfoProvider mProvider; /** * @hide */ - public PlaybackInfo(int type, AudioAttributes attrs, int control, int max, int current) { - mVolumeType = type; - mAudioAttrs = attrs; - mVolumeControl = control; - mMaxVolume = max; - mCurrentVolume = current; + @SystemApi + public PlaybackInfo(PlaybackInfoProvider provider) { + mProvider = provider; + } + + /** + * @hide + */ + @SystemApi + public PlaybackInfoProvider getProvider() { + return mProvider; } /** @@ -187,7 +189,7 @@ public class MediaController2 implements AutoCloseable { * @return The type of playback this session is using. */ public int getPlaybackType() { - return mVolumeType; + return mProvider.getPlaybackType_impl(); } /** @@ -199,22 +201,21 @@ public class MediaController2 implements AutoCloseable { * @return The attributes for this session. */ public AudioAttributes getAudioAttributes() { - return mAudioAttrs; + return mProvider.getAudioAttributes_impl(); } /** * Get the type of volume control that can be used. One of: *

      - *
    • {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}
    • - *
    • {@link VolumeProvider#VOLUME_CONTROL_RELATIVE}
    • - *
    • {@link VolumeProvider#VOLUME_CONTROL_FIXED}
    • + *
    • {@link VolumeProvider2#VOLUME_CONTROL_ABSOLUTE}
    • + *
    • {@link VolumeProvider2#VOLUME_CONTROL_RELATIVE}
    • + *
    • {@link VolumeProvider2#VOLUME_CONTROL_FIXED}
    • *
    * - * @return The type of volume control that may be used with this - * session. + * @return The type of volume control that may be used with this session. */ - public int getVolumeControl() { - return mVolumeControl; + public int getControlType() { + return mProvider.getControlType_impl(); } /** @@ -223,7 +224,7 @@ public class MediaController2 implements AutoCloseable { * @return The maximum allowed volume where this session is playing. */ public int getMaxVolume() { - return mMaxVolume; + return mProvider.getMaxVolume_impl(); } /** @@ -232,7 +233,7 @@ public class MediaController2 implements AutoCloseable { * @return The current volume where this session is playing. */ public int getCurrentVolume() { - return mCurrentVolume; + return mProvider.getCurrentVolume_impl(); } } @@ -277,6 +278,9 @@ public class MediaController2 implements AutoCloseable { mProvider.close_impl(); } + /** + * @hide + */ @SystemApi public MediaController2Provider getProvider() { return mProvider; @@ -420,7 +424,7 @@ public class MediaController2 implements AutoCloseable { * @param extras Optional extras that can include extra information about the media item * to be played. */ - public void playFromUri(@NonNull String uri, @Nullable Bundle extras) { + public void playFromUri(@NonNull Uri uri, @Nullable Bundle extras) { mProvider.playFromUri_impl(uri, extras); } @@ -476,7 +480,7 @@ public class MediaController2 implements AutoCloseable { /** * Set the volume of the output this session is playing on. The command will be ignored if it - * does not support {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. + * does not support {@link VolumeProvider2#VOLUME_CONTROL_ABSOLUTE}. *

    * If the session is local playback, this changes the device's volume with the stream that * session's player is using. Flags will be specified for the {@link AudioManager}. @@ -498,8 +502,8 @@ public class MediaController2 implements AutoCloseable { * must be one of {@link AudioManager#ADJUST_LOWER}, * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}. * The command will be ignored if the session does not support - * {@link VolumeProvider#VOLUME_CONTROL_RELATIVE} or - * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. + * {@link VolumeProvider2#VOLUME_CONTROL_RELATIVE} or + * {@link VolumeProvider2#VOLUME_CONTROL_ABSOLUTE}. *

    * If the session is local playback, this changes the device's volume with the stream that * session's player is using. Flags will be specified for the {@link AudioManager}. diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java index 174d6a3b879c89c4013f5f6719a8a7be1235fc3b..4919eeb4dacb35b6dd173560e4c5973eeed7579d 100644 --- a/media/java/android/media/MediaExtractor.java +++ b/media/java/android/media/MediaExtractor.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; +import android.media.AudioPresentation; import android.media.MediaCodec; import android.media.MediaFormat; import android.media.MediaHTTPService; @@ -40,6 +41,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -395,6 +397,17 @@ final public class MediaExtractor { return null; } + /** + * Get the list of available audio presentations for the track. + * @param trackIndex index of the track. + * @return a list of available audio presentations for a given valid audio track index. + * The list will be empty if the source does not contain any audio presentations. + */ + @NonNull + public List getAudioPresentations(int trackIndex) { + return new ArrayList(); + } + /** * Get the PSSH info if present. * @return a map of uuid-to-bytes, with the uuid specifying diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 35937de287a3714d40280b6279cec17ff7332a87..22c567a4e6a6bde1b3b065e83a83995ef24b16c7 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -70,8 +70,10 @@ public class MediaFile { // More video file types public static final int FILE_TYPE_MP2PS = 200; public static final int FILE_TYPE_QT = 201; + public static final int FILE_TYPE_DIVX = 202; + public static final int FILE_TYPE_FLV = 203; private static final int FIRST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS; - private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_QT; + private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_FLV; // Image file types public static final int FILE_TYPE_JPEG = 31; @@ -275,6 +277,8 @@ public class MediaFile { addFileType("ZIP", FILE_TYPE_ZIP, "application/zip"); addFileType("MPG", FILE_TYPE_MP2PS, "video/mp2p"); addFileType("MPEG", FILE_TYPE_MP2PS, "video/mp2p"); + addFileType("DIVX", FILE_TYPE_DIVX, "video/divx"); + addFileType("FLV", FILE_TYPE_FLV, "video/flv"); } public static boolean isAudioFileType(int fileType) { diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java index 2e9894b1da678d06524433ece25595a2b39c235f..eae4436cae788a010d0c25b1b9c5cc9d30674a71 100644 --- a/media/java/android/media/MediaItem2.java +++ b/media/java/android/media/MediaItem2.java @@ -24,7 +24,6 @@ import android.content.Context; import android.media.update.ApiLoader; import android.media.update.MediaItem2Provider; import android.os.Bundle; -import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -69,7 +68,7 @@ public class MediaItem2 { public MediaItem2(@NonNull Context context, @NonNull String mediaId, @NonNull DataSourceDesc dsd, @Nullable MediaMetadata2 metadata, @Flags int flags) { - mProvider = ApiLoader.getProvider(context).createMediaItem2Provider( + mProvider = ApiLoader.getProvider(context).createMediaItem2( context, this, mediaId, dsd, metadata, flags); } diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java index 79b105fb9706beb17e8b9856aa84ca8adf162570..a11768e69b9dceca92af0c3282a282bc7c85c378 100644 --- a/media/java/android/media/MediaLibraryService2.java +++ b/media/java/android/media/MediaLibraryService2.java @@ -19,13 +19,14 @@ package android.media; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.app.PendingIntent; import android.content.Context; import android.media.MediaSession2.BuilderBase; import android.media.MediaSession2.ControllerInfo; import android.media.update.ApiLoader; +import android.media.update.MediaLibraryService2Provider.LibraryRootProvider; import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider; -import android.media.update.MediaSession2Provider; import android.media.update.MediaSessionService2Provider; import android.os.Bundle; @@ -61,28 +62,19 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { public static final String SERVICE_INTERFACE = "android.media.MediaLibraryService2"; /** - * Session for the media library service. + * Session for the {@link MediaLibraryService2}. Build this object with + * {@link MediaLibrarySessionBuilder} and return in {@link #onCreateSession(String)}. */ - public class MediaLibrarySession extends MediaSession2 { + public static class MediaLibrarySession extends MediaSession2 { private final MediaLibrarySessionProvider mProvider; - MediaLibrarySession(Context context, MediaPlayerInterface player, String id, - VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity, - Executor callbackExecutor, SessionCallback callback) { - super(context, player, id, volumeProvider, ratingType, sessionActivity, - callbackExecutor, callback); - mProvider = (MediaLibrarySessionProvider) getProvider(); - } - - @Override - MediaSession2Provider createProvider(Context context, MediaPlayerInterface player, - String id, VolumeProvider volumeProvider, int ratingType, - PendingIntent sessionActivity, Executor callbackExecutor, - SessionCallback callback) { - return ApiLoader.getProvider(context) - .createMediaLibraryService2MediaLibrarySession(context, this, player, id, - volumeProvider, ratingType, sessionActivity, - callbackExecutor, (MediaLibrarySessionCallback) callback); + /** + * @hide + */ + @SystemApi + public MediaLibrarySession(MediaLibrarySessionProvider provider) { + super(provider); + mProvider = provider; } /** @@ -109,6 +101,9 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { } } + /** + * Callback for the {@link MediaLibrarySession}. + */ public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback { public MediaLibrarySessionCallback(Context context) { @@ -125,15 +120,15 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { * * @param controllerInfo information of the controller requesting access to browse media. * @param rootHints An optional bundle of service-specific arguments to send - * to the media browser service when connecting and retrieving the + * to the media library service when connecting and retrieving the * root id for browsing, or null if none. The contents of this * bundle may affect the information returned when browsing. - * @return The {@link BrowserRoot} for accessing this app's content or null. - * @see BrowserRoot#EXTRA_RECENT - * @see BrowserRoot#EXTRA_OFFLINE - * @see BrowserRoot#EXTRA_SUGGESTED + * @return The {@link LibraryRoot} for accessing this app's content or null. + * @see LibraryRoot#EXTRA_RECENT + * @see LibraryRoot#EXTRA_OFFLINE + * @see LibraryRoot#EXTRA_SUGGESTED */ - public @Nullable BrowserRoot onGetRoot(@NonNull ControllerInfo controllerInfo, + public @Nullable LibraryRoot onGetRoot(@NonNull ControllerInfo controllerInfo, @Nullable Bundle rootHints) { return null; } @@ -208,31 +203,49 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { /** * Builder for {@link MediaLibrarySession}. */ - // TODO(jaewan): Move this to updatable. - public class MediaLibrarySessionBuilder - extends BuilderBase { + // Override all methods just to show them with the type instead of generics in Javadoc. + // This workarounds javadoc issue described in the MediaSession2.BuilderBase. + public class MediaLibrarySessionBuilder extends BuilderBase { public MediaLibrarySessionBuilder( @NonNull Context context, @NonNull MediaPlayerInterface player, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull MediaLibrarySessionCallback callback) { - super(context, player); - setSessionCallback(callbackExecutor, callback); + super((instance) -> ApiLoader.getProvider(context).createMediaLibraryService2Builder( + context, (MediaLibrarySessionBuilder) instance, player, callbackExecutor, + callback)); + } + + @Override + public MediaLibrarySessionBuilder setVolumeProvider( + @Nullable VolumeProvider2 volumeProvider) { + return super.setVolumeProvider(volumeProvider); + } + + @Override + public MediaLibrarySessionBuilder setRatingType(int type) { + return super.setRatingType(type); + } + + @Override + public MediaLibrarySessionBuilder setSessionActivity(@Nullable PendingIntent pi) { + return super.setSessionActivity(pi); + } + + @Override + public MediaLibrarySessionBuilder setId(String id) { + return super.setId(id); } @Override public MediaLibrarySessionBuilder setSessionCallback( - @NonNull @CallbackExecutor Executor callbackExecutor, - @NonNull MediaLibrarySessionCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("MediaLibrarySessionCallback cannot be null"); - } - return super.setSessionCallback(callbackExecutor, callback); + @NonNull Executor executor, @NonNull MediaLibrarySessionCallback callback) { + return super.setSessionCallback(executor, callback); } @Override public MediaLibrarySession build() { - return new MediaLibrarySession(mContext, mPlayer, mId, mVolumeProvider, mRatingType, - mSessionActivity, mCallbackExecutor, mCallback); + return super.build(); } } @@ -253,7 +266,7 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { * This method will be called on the main thread. * * @param sessionId session id written in the AndroidManifest.xml. - * @return a new browser session + * @return a new library session * @see MediaLibrarySessionBuilder * @see #getSession() * @throws RuntimeException if returned session is invalid @@ -262,17 +275,17 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { public @NonNull abstract MediaLibrarySession onCreateSession(String sessionId); /** - * Contains information that the browser service needs to send to the client - * when first connected. + * Contains information that the library service needs to send to the client when + * {@link MediaBrowser2#getLibraryRoot(Bundle)} is called. */ - public static final class BrowserRoot { + public static final class LibraryRoot { /** - * The lookup key for a boolean that indicates whether the browser service should return a - * browser root for recently played media items. + * The lookup key for a boolean that indicates whether the library service should return a + * librar root for recently played media items. * - *

    When creating a media browser for a given media browser service, this key can be + *

    When creating a media browser for a given media library service, this key can be * supplied as a root hint for retrieving media items that are recently played. - * If the media browser service can provide such media items, the implementation must return + * If the media library service can provide such media items, the implementation must return * the key in the root hint when * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back. * @@ -284,13 +297,13 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { public static final String EXTRA_RECENT = "android.media.extra.RECENT"; /** - * The lookup key for a boolean that indicates whether the browser service should return a - * browser root for offline media items. + * The lookup key for a boolean that indicates whether the library service should return a + * library root for offline media items. * - *

    When creating a media browser for a given media browser service, this key can be + *

    When creating a media browser for a given media library service, this key can be * supplied as a root hint for retrieving media items that are can be played without an * internet connection. - * If the media browser service can provide such media items, the implementation must return + * If the media library service can provide such media items, the implementation must return * the key in the root hint when * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back. * @@ -302,14 +315,14 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { public static final String EXTRA_OFFLINE = "android.media.extra.OFFLINE"; /** - * The lookup key for a boolean that indicates whether the browser service should return a - * browser root for suggested media items. + * The lookup key for a boolean that indicates whether the library service should return a + * library root for suggested media items. * - *

    When creating a media browser for a given media browser service, this key can be - * supplied as a root hint for retrieving the media items suggested by the media browser + *

    When creating a media browser for a given media library service, this key can be + * supplied as a root hint for retrieving the media items suggested by the media library * service. The list of media items is considered ordered by relevance, first being the top * suggestion. - * If the media browser service can provide such media items, the implementation must return + * If the media library service can provide such media items, the implementation must return * the key in the root hint when * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back. * @@ -320,35 +333,31 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 { */ public static final String EXTRA_SUGGESTED = "android.media.extra.SUGGESTED"; - final private String mRootId; - final private Bundle mExtras; + private final LibraryRootProvider mProvider; /** - * Constructs a browser root. + * Constructs a library root. * @param rootId The root id for browsing. - * @param extras Any extras about the browser service. + * @param extras Any extras about the library service. */ - public BrowserRoot(@NonNull String rootId, @Nullable Bundle extras) { - if (rootId == null) { - throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " + - "Use null for BrowserRoot instead."); - } - mRootId = rootId; - mExtras = extras; + public LibraryRoot(@NonNull Context context, + @NonNull String rootId, @Nullable Bundle extras) { + mProvider = ApiLoader.getProvider(context).createMediaLibraryService2LibraryRoot( + context, this, rootId, extras); } /** * Gets the root id for browsing. */ public String getRootId() { - return mRootId; + return mProvider.getRootId_impl(); } /** - * Gets any extras about the browser service. + * Gets any extras about the library service. */ public Bundle getExtras() { - return mExtras; + return mProvider.getExtras_impl(); } } } diff --git a/media/java/android/media/MediaMetadata2.java b/media/java/android/media/MediaMetadata2.java index fcdb4f75edcf568be28214e6feceabede74941eb..54a9057eeb2d43408e5565ff3d062d3d483603fd 100644 --- a/media/java/android/media/MediaMetadata2.java +++ b/media/java/android/media/MediaMetadata2.java @@ -16,17 +16,16 @@ package android.media; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringDef; +import android.annotation.SystemApi; +import android.content.Context; import android.graphics.Bitmap; +import android.media.update.ApiLoader; +import android.media.update.MediaMetadata2Provider; import android.net.Uri; -import android.os.Build; import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; -import android.util.ArrayMap; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -37,9 +36,11 @@ import java.util.Set; * * @hide */ -// TODO(jaewan): Move this to updatable public final class MediaMetadata2 { - private static final String TAG = "MediaMetadata2"; + // New version of MediaMetadata that no longer implements Parcelable but added from/toBundle() + // for updatable. + // MediaDescription is deprecated because it was insufficient for controller to display media + // contents. Added getExtra() here to support all the features from the MediaDescription. /** * The title of the media. @@ -365,76 +366,14 @@ public final class MediaMetadata2 { @Retention(RetentionPolicy.SOURCE) public @interface RatingKey {} - static final int METADATA_TYPE_LONG = 0; - static final int METADATA_TYPE_TEXT = 1; - static final int METADATA_TYPE_BITMAP = 2; - static final int METADATA_TYPE_RATING = 3; - static final ArrayMap METADATA_KEYS_TYPE; - - static { - METADATA_KEYS_TYPE = new ArrayMap(); - METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP); - METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING); - METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_ID, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_BT_FOLDER_TYPE, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ADVERTISEMENT, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_DOWNLOAD_STATUS, METADATA_TYPE_LONG); - } - - private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = { - METADATA_KEY_TITLE, - METADATA_KEY_ARTIST, - METADATA_KEY_ALBUM, - METADATA_KEY_ALBUM_ARTIST, - METADATA_KEY_WRITER, - METADATA_KEY_AUTHOR, - METADATA_KEY_COMPOSER - }; - - private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = { - METADATA_KEY_DISPLAY_ICON, - METADATA_KEY_ART, - METADATA_KEY_ALBUM_ART - }; - - private static final @TextKey String[] PREFERRED_URI_ORDER = { - METADATA_KEY_DISPLAY_ICON_URI, - METADATA_KEY_ART_URI, - METADATA_KEY_ALBUM_ART_URI - }; - - final Bundle mBundle; + private final MediaMetadata2Provider mProvider; /** * @hide */ - public MediaMetadata2(Bundle bundle) { - mBundle = new Bundle(bundle); + @SystemApi + public MediaMetadata2(MediaMetadata2Provider provider) { + mProvider = provider; } /** @@ -443,8 +382,8 @@ public final class MediaMetadata2 { * @param key a String key * @return true if the key exists in this metadata, false otherwise */ - public boolean containsKey(String key) { - return mBundle.containsKey(key); + public boolean containsKey(@NonNull String key) { + return mProvider.containsKey_impl(key); } /** @@ -455,8 +394,8 @@ public final class MediaMetadata2 { * @param key The key the value is stored under * @return a CharSequence value, or null */ - public CharSequence getText(@TextKey String key) { - return mBundle.getCharSequence(key); + public @Nullable CharSequence getText(@TextKey String key) { + return mProvider.getText_impl(key); } /** @@ -464,11 +403,11 @@ public final class MediaMetadata2 { * the desired type exists for the given key or a null value is explicitly * associated with the key. * - * @ * @return media id. Can be {@code null} + * @see #METADATA_KEY_MEDIA_ID */ public @Nullable String getMediaId() { - return getString(METADATA_KEY_MEDIA_ID); + return mProvider.getMediaId_impl(); } /** @@ -479,12 +418,8 @@ public final class MediaMetadata2 { * @param key The key the value is stored under * @return a String value, or null */ - public String getString(@TextKey String key) { - CharSequence text = mBundle.getCharSequence(key); - if (text != null) { - return text.toString(); - } - return null; + public @Nullable String getString(@NonNull @TextKey String key) { + return mProvider.getString_impl(key); } /** @@ -494,8 +429,8 @@ public final class MediaMetadata2 { * @param key The key the value is stored under * @return a long value */ - public long getLong(@LongKey String key) { - return mBundle.getLong(key, 0); + public long getLong(@NonNull @LongKey String key) { + return mProvider.getLong_impl(key); } /** @@ -503,18 +438,10 @@ public final class MediaMetadata2 { * the given key. * * @param key The key the value is stored under - * @return A {@link Rating2} or null - */ - public Rating2 getRating(@RatingKey String key) { - // TODO(jaewan): Add backward compatibility - Rating2 rating = null; - try { - rating = Rating2.fromBundle(mBundle.getBundle(key)); - } catch (Exception e) { - // ignore, value was not a rating - Log.w(TAG, "Failed to retrieve a key as Rating.", e); - } - return rating; + * @return A {@link Rating2} or {@code null} + */ + public @Nullable Rating2 getRating(@RatingKey String key) { + return mProvider.getRating_impl(key); } /** @@ -525,14 +452,7 @@ public final class MediaMetadata2 { * @return A {@link Bitmap} or null */ public Bitmap getBitmap(@BitmapKey String key) { - Bitmap bmp = null; - try { - bmp = mBundle.getParcelable(key); - } catch (Exception e) { - // ignore, value was not a bitmap - Log.w(TAG, "Failed to retrieve a key as Bitmap.", e); - } - return bmp; + return mProvider.getBitmap_impl(key); } /** @@ -540,14 +460,8 @@ public final class MediaMetadata2 { * * @return A {@link Bundle} or {@code null} */ - public Bundle getExtra() { - try { - return mBundle.getBundle(METADATA_KEY_EXTRA); - } catch (Exception e) { - // ignore, value was not an bundle - Log.w(TAG, "Failed to retrieve an extra"); - } - return null; + public @Nullable Bundle getExtra() { + return mProvider.getExtra_impl(); } /** @@ -556,7 +470,7 @@ public final class MediaMetadata2 { * @return The number of fields in the metadata. */ public int size() { - return mBundle.size(); + return mProvider.size_impl(); } /** @@ -564,8 +478,8 @@ public final class MediaMetadata2 { * * @return a Set of String keys */ - public Set keySet() { - return mBundle.keySet(); + public @NonNull Set keySet() { + return mProvider.keySet_impl(); } /** @@ -574,8 +488,21 @@ public final class MediaMetadata2 { * * @return The Bundle backing this metadata. */ - public Bundle getBundle() { - return mBundle; + public @NonNull Bundle toBundle() { + return mProvider.toBundle_impl(); + } + + /** + * Creates the {@link MediaMetadata2} from the bundle that previously returned by + * {@link #toBundle()}. + * + * @param context context + * @param bundle bundle for the metadata + * @return a new MediaMetadata2 + */ + public static @NonNull MediaMetadata2 fromBundle(@NonNull Context context, + @Nullable Bundle bundle) { + return ApiLoader.getProvider(context).fromBundle_MediaMetadata2(context, bundle); } /** @@ -583,14 +510,15 @@ public final class MediaMetadata2 { * use the appropriate data type. */ public static final class Builder { - private final Bundle mBundle; + private final MediaMetadata2Provider.BuilderProvider mProvider; /** * Create an empty Builder. Any field that should be included in the * {@link MediaMetadata2} must be added. */ - public Builder() { - mBundle = new Bundle(); + public Builder(@NonNull Context context) { + mProvider = ApiLoader.getProvider(context).createMediaMetadata2Builder( + context, this); } /** @@ -600,31 +528,17 @@ public final class MediaMetadata2 { * * @param source */ - public Builder(MediaMetadata2 source) { - mBundle = new Bundle(source.mBundle); + public Builder(@NonNull Context context, @NonNull MediaMetadata2 source) { + mProvider = ApiLoader.getProvider(context).createMediaMetadata2Builder( + context, this, source); } /** - * Create a Builder using a {@link MediaMetadata2} instance to set - * initial values, but replace bitmaps with a scaled down copy if they - * are larger than maxBitmapSize. - * - * @param source The original metadata to copy. - * @param maxBitmapSize The maximum height/width for bitmaps contained - * in the metadata. * @hide */ - public Builder(MediaMetadata2 source, int maxBitmapSize) { - this(source); - for (String key : mBundle.keySet()) { - Object value = mBundle.get(key); - if (value instanceof Bitmap) { - Bitmap bmp = (Bitmap) value; - if (bmp.getHeight() > maxBitmapSize || bmp.getWidth() > maxBitmapSize) { - putBitmap(key, scaleBitmap(bmp, maxBitmapSize)); - } - } - } + @SystemApi + public Builder(@NonNull MediaMetadata2Provider.BuilderProvider provider) { + mProvider = provider; } /** @@ -653,15 +567,8 @@ public final class MediaMetadata2 { * @param value The CharSequence value to store * @return The Builder to allow chaining */ - public Builder putText(@TextKey String key, CharSequence value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a CharSequence"); - } - } - mBundle.putCharSequence(key, value); - return this; + public @NonNull Builder putText(@TextKey String key, @Nullable CharSequence value) { + return mProvider.putText_impl(key, value); } /** @@ -690,15 +597,8 @@ public final class MediaMetadata2 { * @param value The String value to store * @return The Builder to allow chaining */ - public Builder putString(@TextKey String key, String value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a String"); - } - } - mBundle.putCharSequence(key, value); - return this; + public @NonNull Builder putString(@TextKey String key, @Nullable String value) { + return mProvider.putString_impl(key, value); } /** @@ -720,15 +620,8 @@ public final class MediaMetadata2 { * @param value The String value to store * @return The Builder to allow chaining */ - public Builder putLong(@LongKey String key, long value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a long"); - } - } - mBundle.putLong(key, value); - return this; + public @NonNull Builder putLong(@NonNull @LongKey String key, long value) { + return mProvider.putLong_impl(key, value); } /** @@ -744,16 +637,8 @@ public final class MediaMetadata2 { * @param value The String value to store * @return The Builder to allow chaining */ - public Builder putRating(@RatingKey String key, Rating2 value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a Rating"); - } - } - mBundle.putBundle(key, value.toBundle()); - - return this; + public @NonNull Builder putRating(@NonNull @RatingKey String key, @Nullable Rating2 value) { + return mProvider.putRating_impl(key, value); } /** @@ -774,23 +659,15 @@ public final class MediaMetadata2 { * @param value The Bitmap to store * @return The Builder to allow chaining */ - public Builder putBitmap(@BitmapKey String key, Bitmap value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a Bitmap"); - } - } - mBundle.putParcelable(key, value); - return this; + public @NonNull Builder putBitmap(@NonNull @BitmapKey String key, @Nullable Bitmap value) { + return mProvider.putBitmap_impl(key, value); } /** * Set an extra {@link Bundle} into the metadata. */ - public Builder setExtra(Bundle bundle) { - mBundle.putBundle(METADATA_KEY_EXTRA, bundle); - return this; + public @NonNull Builder setExtra(@Nullable Bundle bundle) { + return mProvider.setExtra_impl(bundle); } /** @@ -798,18 +675,8 @@ public final class MediaMetadata2 { * * @return The new MediaMetadata2 instance */ - public MediaMetadata2 build() { - return new MediaMetadata2(mBundle); - } - - private Bitmap scaleBitmap(Bitmap bmp, int maxSize) { - float maxSizeF = maxSize; - float widthScale = maxSizeF / bmp.getWidth(); - float heightScale = maxSizeF / bmp.getHeight(); - float scale = Math.min(widthScale, heightScale); - int height = (int) (bmp.getHeight() * scale); - int width = (int) (bmp.getWidth() * scale); - return Bitmap.createScaledBitmap(bmp, width, height, true); + public @NonNull MediaMetadata2 build() { + return mProvider.build_impl(); } } } diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java index d84eedf94820a66f6ee0f363eedc0f30d5f83444..e331b2cbf645d4915918efe6c7572d5d38e6b771 100644 --- a/media/java/android/media/MediaPlayer2.java +++ b/media/java/android/media/MediaPlayer2.java @@ -1670,35 +1670,6 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener */ public abstract void deselectTrack(int index); - /** - * Sets the target UDP re-transmit endpoint for the low level player. - * Generally, the address portion of the endpoint is an IP multicast - * address, although a unicast address would be equally valid. When a valid - * retransmit endpoint has been set, the media player will not decode and - * render the media presentation locally. Instead, the player will attempt - * to re-multiplex its media data using the Android@Home RTP profile and - * re-transmit to the target endpoint. Receiver devices (which may be - * either the same as the transmitting device or different devices) may - * instantiate, prepare, and start a receiver player using a setDataSource - * URL of the form... - * - * aahRX://<multicastIP>:<port> - * - * to receive, decode and render the re-transmitted content. - * - * setRetransmitEndpoint may only be called before setDataSource has been - * called; while the player is in the Idle state. - * - * @param endpoint the address and UDP port of the re-transmission target or - * null if no re-transmission is to be performed. - * @throws IllegalStateException if it is called in an invalid state - * @throws IllegalArgumentException if the retransmit endpoint is supplied, - * but invalid. - * - * {@hide} pending API council - */ - public void setRetransmitEndpoint(InetSocketAddress endpoint) { } - /** * Releases the resources held by this {@code MediaPlayer2} object. * diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 222c66ea4551ada88f45939c91f35e8beebb0f48..e3d5ac07665edbcbb65b060a6e848f589471513c 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -2963,53 +2963,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } - /** - * Sets the target UDP re-transmit endpoint for the low level player. - * Generally, the address portion of the endpoint is an IP multicast - * address, although a unicast address would be equally valid. When a valid - * retransmit endpoint has been set, the media player will not decode and - * render the media presentation locally. Instead, the player will attempt - * to re-multiplex its media data using the Android@Home RTP profile and - * re-transmit to the target endpoint. Receiver devices (which may be - * either the same as the transmitting device or different devices) may - * instantiate, prepare, and start a receiver player using a setDataSource - * URL of the form... - * - * aahRX://<multicastIP>:<port> - * - * to receive, decode and render the re-transmitted content. - * - * setRetransmitEndpoint may only be called before setDataSource has been - * called; while the player is in the Idle state. - * - * @param endpoint the address and UDP port of the re-transmission target or - * null if no re-transmission is to be performed. - * @throws IllegalStateException if it is called in an invalid state - * @throws IllegalArgumentException if the retransmit endpoint is supplied, - * but invalid. - * - * {@hide} pending API council - */ - @Override - public void setRetransmitEndpoint(InetSocketAddress endpoint) - throws IllegalStateException, IllegalArgumentException - { - String addrString = null; - int port = 0; - - if (null != endpoint) { - addrString = endpoint.getAddress().getHostAddress(); - port = endpoint.getPort(); - } - - int ret = native_setRetransmitEndpoint(addrString, port); - if (ret != 0) { - throw new IllegalArgumentException("Illegal re-transmit endpoint; native ret " + ret); - } - } - - private native final int native_setRetransmitEndpoint(String addrString, int port); - /** * Releases the resources held by this {@code MediaPlayer2} object. * diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 78477f757e2ab6a2a46764a0c659c79fe53ca181..62240cedf0be35086f84ccc80fb226305e5971e5 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.view.Surface; @@ -34,6 +35,8 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.RandomAccessFile; import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; import com.android.internal.annotations.GuardedBy; @@ -1406,6 +1409,31 @@ public class MediaRecorder implements AudioRouting private native final int native_getRoutedDeviceId(); private native final void native_enableDeviceCallback(boolean enabled); + //-------------------------------------------------------------------------- + // Microphone information + //-------------------- + /** + * Return A lists of {@link MicrophoneInfo} representing the active microphones. + * By querying channel mapping for each active microphone, developer can know how + * the microphone is used by each channels or a capture stream. + * + * @return a lists of {@link MicrophoneInfo} representing the active microphones + * @throws IOException if an error occurs + */ + public List getActiveMicrophones() throws IOException { + ArrayList activeMicrophones = new ArrayList<>(); + int status = native_getActiveMicrophones(activeMicrophones); + if (status != AudioManager.SUCCESS) { + Log.e(TAG, "getActiveMicrophones failed:" + status); + return new ArrayList(); + } + AudioManager.setPortIdForMicrophones(activeMicrophones); + return activeMicrophones; + } + + private native final int native_getActiveMicrophones( + ArrayList activeMicrophones); + /** * Called from native code when an interesting event happens. This method * just uses the EventHandler system to post the event back to the main app thread. diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java index 7eebcdcb0af6347e7565076437e445eb037ba170..943b827289f1688c07859ec0162e3c787fe93023 100644 --- a/media/java/android/media/MediaSession2.java +++ b/media/java/android/media/MediaSession2.java @@ -30,20 +30,21 @@ import android.media.session.MediaSession.Callback; import android.media.session.PlaybackState; import android.media.update.ApiLoader; import android.media.update.MediaSession2Provider; +import android.media.update.MediaSession2Provider.BuilderBaseProvider; +import android.media.update.MediaSession2Provider.CommandButtonProvider; +import android.media.update.MediaSession2Provider.CommandGroupProvider; import android.media.update.MediaSession2Provider.CommandProvider; import android.media.update.MediaSession2Provider.ControllerInfoProvider; +import android.media.update.ProviderCreator; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IInterface; -import android.os.Parcelable; import android.os.ResultReceiver; import android.text.TextUtils; -import android.util.ArraySet; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; @@ -83,34 +84,178 @@ import java.util.concurrent.Executor; public class MediaSession2 implements AutoCloseable { private final MediaSession2Provider mProvider; - // Note: Do not define IntDef because subclass can add more command code on top of these. + // TODO(jaewan): Should we define IntDef? Currently we don't have to allow subclass to add more. // TODO(jaewan): Shouldn't we pull out? - // TODO(jaewan): Should we also protect getPlaybackState()? + // TODO(jaewan): Should we also protect getters not related with metadata? + // Getters are getRatingType(), getPlaybackState(), getSessionActivity(), + // getPlaylistParams()) + // Next ID: 23 + /** + * Command code for the custom command which can be defined by string action in the + * {@link Command}. + */ public static final int COMMAND_CODE_CUSTOM = 0; - public static final int COMMAND_CODE_PLAYBACK_START = 1; + + /** + * Command code for {@link MediaController2#play()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ + public static final int COMMAND_CODE_PLAYBACK_PLAY = 1; + + /** + * Command code for {@link MediaController2#pause()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2; + + /** + * Command code for {@link MediaController2#stop()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_STOP = 3; + + /** + * Command code for {@link MediaController2#skipToNext()} ()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM = 4; + + /** + * Command code for {@link MediaController2#skipToPrevious()} ()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM = 5; + + /** + * Command code for {@link MediaController2#prepare()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6; + + /** + * Command code for {@link MediaController2#fastForward()} ()}. + *

    + * This is transport control command. Command would be sent directly to the player if the + * session doesn't reject the request through the + * {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_FAST_FORWARD = 7; + + /** + * Command code for {@link MediaController2#rewind()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_REWIND = 8; + + /** + * Command code for {@link MediaController2#seekTo(long)} ()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9; + /** + * Command code for {@link MediaController2#setCurrentPlaylistItem(int)} ()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM = 10; - public static final int COMMAND_CODE_PLAYLIST_GET = 11; + /** + * Command code for {@link MediaController2#setPlaylistParams(PlaylistParams)} ()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ + public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 11; + + /** + * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYLIST_ADD = 12; + + /** + * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ public static final int COMMAND_CODE_PLAYLIST_REMOVE = 13; - public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 14; - public static final int COMMAND_CODE_PLAY_FROM_URI = 15; - public static final int COMMAND_CODE_PLAY_FROM_SEARCH = 16; + /** + * Command code for {@link MediaController2#getPlaylist()}. + *

    + * Command would be sent directly to the player if the session doesn't reject the request + * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ + public static final int COMMAND_CODE_PLAYLIST_GET = 14; + + /** + * Command code for both {@link MediaController2#setVolumeTo(int, int)} and + * {@link MediaController2#adjustVolume(int, int)}. + *

    + * Command would adjust the volume or sent to the volume provider directly if the session + * doesn't reject the request through the + * {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}. + */ + public static final int COMMAND_CODE_SET_VOLUME = 15; - public static final int COMMAND_CODE_PREPARE_FROM_MEDIA_ID = 17; - public static final int COMMAND_CODE_PREPARE_FROM_URI = 18; - public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 19; + /** + * Command code for {@link MediaController2#playFromMediaId(String, Bundle)}. + */ + public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 16; - public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 20; + /** + * Command code for {@link MediaController2#playFromUri(String, Bundle)}. + */ + public static final int COMMAND_CODE_PLAY_FROM_URI = 17; + + /** + * Command code for {@link MediaController2#playFromSearch(String, Bundle)}. + */ + public static final int COMMAND_CODE_PLAY_FROM_SEARCH = 18; + + /** + * Command code for {@link MediaController2#prepareFromMediaId(String, Bundle)}. + */ + public static final int COMMAND_CODE_PREPARE_FROM_MEDIA_ID = 19; + + /** + * Command code for {@link MediaController2#prepareFromUri(Uri, Bundle)}. + */ + public static final int COMMAND_CODE_PREPARE_FROM_URI = 20; + + /** + * Command code for {@link MediaController2#prepareFromSearch(String, Bundle)}. + */ + public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 21; + + /** + * Command code for {@link MediaBrowser2} specific functions that allows navigation and search + * from the {@link MediaLibraryService2}. This would be ignored if a {@link MediaSession2}, + * not {@link android.media.MediaLibraryService2.MediaLibrarySession}, specify this. + * + * @see MediaBrowser2 + */ + public static final int COMMAND_CODE_BROWSER = 22; /** * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}. @@ -156,14 +301,6 @@ public class MediaSession2 implements AutoCloseable { return mProvider.toBundle_impl(); } - /** - * @return a new Command instance from the Bundle - * @hide - */ - public static Command fromBundle(@NonNull Context context, Bundle command) { - return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command); - } - @Override public boolean equals(Object obj) { if (!(obj instanceof Command)) { @@ -176,63 +313,58 @@ public class MediaSession2 implements AutoCloseable { public int hashCode() { return mProvider.hashCode_impl(); } + + /** + * @return a new Command instance from the Bundle + * @hide + */ + public static Command fromBundle(@NonNull Context context, Bundle command) { + return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command); + } } /** * Represent set of {@link Command}. */ - // TODO(jaewan): Move this to updatable public static class CommandGroup { - private static final String KEY_COMMANDS = - "android.media.mediasession2.commandgroup.commands"; - private ArraySet mCommands = new ArraySet<>(); - private final Context mContext; + private final CommandGroupProvider mProvider; public CommandGroup(Context context) { - mContext = context; + mProvider = ApiLoader.getProvider(context) + .createMediaSession2CommandGroup(context, this, null); } public CommandGroup(Context context, CommandGroup others) { - this(context); - mCommands.addAll(others.mCommands); + mProvider = ApiLoader.getProvider(context) + .createMediaSession2CommandGroup(context, this, others); } public void addCommand(Command command) { - mCommands.add(command); + mProvider.addCommand_impl(command); } public void addAllPredefinedCommands() { - // TODO(jaewan): Is there any better way than this? - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_START)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_PAUSE)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_STOP)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_PREPARE)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_FAST_FORWARD)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_REWIND)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SEEK_TO)); - mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM)); + mProvider.addAllPredefinedCommands_impl(); } public void removeCommand(Command command) { - mCommands.remove(command); + mProvider.removeCommand_impl(command); } public boolean hasCommand(Command command) { - return mCommands.contains(command); + return mProvider.hasCommand_impl(command); } public boolean hasCommand(int code) { - if (code == COMMAND_CODE_CUSTOM) { - throw new IllegalArgumentException("Use hasCommand(Command) for custom command"); - } - for (int i = 0; i < mCommands.size(); i++) { - if (mCommands.valueAt(i).getCommandCode() == code) { - return true; - } - } - return false; + return mProvider.hasCommand_impl(code); + } + + /** + * @hide + */ + @SystemApi + public CommandGroupProvider getProvider() { + return mProvider; } /** @@ -240,13 +372,7 @@ public class MediaSession2 implements AutoCloseable { * @hide */ public Bundle toBundle() { - ArrayList list = new ArrayList<>(); - for (int i = 0; i < mCommands.size(); i++) { - list.add(mCommands.valueAt(i).toBundle()); - } - Bundle bundle = new Bundle(); - bundle.putParcelableArrayList(KEY_COMMANDS, list); - return bundle; + return mProvider.toBundle_impl(); } /** @@ -254,26 +380,8 @@ public class MediaSession2 implements AutoCloseable { * @hide */ public static @Nullable CommandGroup fromBundle(Context context, Bundle commands) { - if (commands == null) { - return null; - } - List list = commands.getParcelableArrayList(KEY_COMMANDS); - if (list == null) { - return null; - } - CommandGroup commandGroup = new CommandGroup(context); - for (int i = 0; i < list.size(); i++) { - Parcelable parcelable = list.get(i); - if (!(parcelable instanceof Bundle)) { - continue; - } - Bundle commandBundle = (Bundle) parcelable; - Command command = Command.fromBundle(context, commandBundle); - if (command != null) { - commandGroup.addCommand(command); - } - } - return commandGroup; + return ApiLoader.getProvider(context) + .fromBundle_MediaSession2CommandGroup(context, commands); } } @@ -316,22 +424,36 @@ public class MediaSession2 implements AutoCloseable { public void onDisconnected(@NonNull ControllerInfo controller) { } /** - * Called when a controller sent a command to the session, and the command will be sent to - * the player directly unless you reject the request by {@code false}. + * Called when a controller sent a command that will be sent directly to the player. Return + * {@code false} here to reject the request and stop sending command to the player. * * @param controller controller information. * @param command a command. This method will be called for every single command. * @return {@code true} if you want to accept incoming command. {@code false} otherwise. + * @see #COMMAND_CODE_PLAYBACK_PLAY + * @see #COMMAND_CODE_PLAYBACK_PAUSE + * @see #COMMAND_CODE_PLAYBACK_STOP + * @see #COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM + * @see #COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM + * @see #COMMAND_CODE_PLAYBACK_PREPARE + * @see #COMMAND_CODE_PLAYBACK_FAST_FORWARD + * @see #COMMAND_CODE_PLAYBACK_REWIND + * @see #COMMAND_CODE_PLAYBACK_SEEK_TO + * @see #COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM + * @see #COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS + * @see #COMMAND_CODE_PLAYLIST_ADD + * @see #COMMAND_CODE_PLAYLIST_REMOVE + * @see #COMMAND_CODE_PLAYLIST_GET + * @see #COMMAND_CODE_SET_VOLUME */ - // TODO(jaewan): Add more documentations (or make it clear) which commands can be filtered - // with this. public boolean onCommandRequest(@NonNull ControllerInfo controller, @NonNull Command command) { return true; } /** - * Called when a controller set rating on the currently playing contents. + * Called when a controller set rating on the currently playing contents by + * {@link MediaController2#setRating(Rating2)}. * * @param controller controller information * @param rating new rating from the controller @@ -339,7 +461,8 @@ public class MediaSession2 implements AutoCloseable { public void onSetRating(@NonNull ControllerInfo controller, @NonNull Rating2 rating) { } /** - * Called when a controller sent a custom command. + * Called when a controller sent a custom command through + * {@link MediaController2#sendCustomCommand(Command, Bundle, ResultReceiver)}. * * @param controller controller information * @param customCommand custom command. @@ -351,7 +474,48 @@ public class MediaSession2 implements AutoCloseable { @Nullable ResultReceiver cb) { } /** - * Override to handle requests to prepare for playing a specific mediaId. + * Called when a controller requested to play a specific mediaId through + * {@link MediaController2#playFromMediaId(String, Bundle)}. + * + * @param controller controller information + * @param mediaId media id + * @param extras optional extra bundle + * @see #COMMAND_CODE_PLAY_FROM_MEDIA_ID + */ + public void onPlayFromMediaId(@NonNull ControllerInfo controller, + @NonNull String mediaId, @Nullable Bundle extras) { } + + /** + * Called when a controller requested to begin playback from a search query through + * {@link MediaController2#playFromSearch(String, Bundle)} + *

    + * An empty query indicates that the app may play any music. The implementation should + * attempt to make a smart choice about what to play. + * + * @param controller controller information + * @param query query string. Can be empty to indicate any suggested media + * @param extras optional extra bundle + * @see #COMMAND_CODE_PLAY_FROM_SEARCH + */ + public void onPlayFromSearch(@NonNull ControllerInfo controller, + @NonNull String query, @Nullable Bundle extras) { } + + /** + * Called when a controller requested to play a specific media item represented by a URI + * through {@link MediaController2#playFromUri(Uri, Bundle)} + * + * @param controller controller information + * @param uri uri + * @param extras optional extra bundle + * @see #COMMAND_CODE_PLAY_FROM_URI + */ + public void onPlayFromUri(@NonNull ControllerInfo controller, + @NonNull Uri uri, @Nullable Bundle extras) { } + + /** + * Called when a controller requested to prepare for playing a specific mediaId through + * {@link MediaController2#prepareFromMediaId(String, Bundle)}. + *

    * During the preparation, a session should not hold audio focus in order to allow other * sessions play seamlessly. The state of playback should be updated to * {@link PlaybackState#STATE_PAUSED} after the preparation is done. @@ -361,28 +525,41 @@ public class MediaSession2 implements AutoCloseable { *

    * Override {@link #onPlayFromMediaId} to handle requests for starting * playback without preparation. + * + * @param controller controller information + * @param mediaId media id to prepare + * @param extras optional extra bundle + * @see #COMMAND_CODE_PREPARE_FROM_MEDIA_ID */ - public void onPlayFromMediaId(@NonNull ControllerInfo controller, + public void onPrepareFromMediaId(@NonNull ControllerInfo controller, @NonNull String mediaId, @Nullable Bundle extras) { } /** - * Override to handle requests to prepare playback from a search query. An empty query - * indicates that the app may prepare any music. The implementation should attempt to make a - * smart choice about what to play. During the preparation, a session should not hold audio - * focus in order to allow other sessions play seamlessly. The state of playback should be - * updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done. + * Called when a controller requested to prepare playback from a search query through + * {@link MediaController2#prepareFromSearch(String, Bundle)}. *

    - * The playback of the prepared content should start in the later calls of - * {@link MediaSession2#play()}. + * An empty query indicates that the app may prepare any music. The implementation should + * attempt to make a smart choice about what to play. + *

    + * The state of playback should be updated to {@link PlaybackState#STATE_PAUSED} after the + * preparation is done. The playback of the prepared content should start in the later + * calls of {@link MediaSession2#play()}. *

    * Override {@link #onPlayFromSearch} to handle requests for starting playback without * preparation. + * + * @param controller controller information + * @param query query string. Can be empty to indicate any suggested media + * @param extras optional extra bundle + * @see #COMMAND_CODE_PREPARE_FROM_SEARCH */ - public void onPlayFromSearch(@NonNull ControllerInfo controller, + public void onPrepareFromSearch(@NonNull ControllerInfo controller, @NonNull String query, @Nullable Bundle extras) { } /** - * Override to handle requests to prepare a specific media item represented by a URI. + * Called when a controller requested to prepare a specific media item represented by a URI + * through {@link MediaController2#prepareFromUri(Uri, Bundle)}. + *

    * During the preparation, a session should not hold audio focus in order to allow * other sessions play seamlessly. The state of playback should be updated to * {@link PlaybackState#STATE_PAUSED} after the preparation is done. @@ -392,89 +569,39 @@ public class MediaSession2 implements AutoCloseable { *

    * Override {@link #onPlayFromUri} to handle requests for starting playback without * preparation. - */ - public void onPlayFromUri(@NonNull ControllerInfo controller, - @NonNull String uri, @Nullable Bundle extras) { } - - /** - * Override to handle requests to play a specific mediaId. - */ - public void onPrepareFromMediaId(@NonNull ControllerInfo controller, - @NonNull String mediaId, @Nullable Bundle extras) { } - - /** - * Override to handle requests to begin playback from a search query. An - * empty query indicates that the app may play any music. The - * implementation should attempt to make a smart choice about what to - * play. - */ - public void onPrepareFromSearch(@NonNull ControllerInfo controller, - @NonNull String query, @Nullable Bundle extras) { } - - /** - * Override to handle requests to play a specific media item represented by a URI. + * + * @param controller controller information + * @param uri uri + * @param extras optional extra bundle + * @see #COMMAND_CODE_PREPARE_FROM_URI */ public void onPrepareFromUri(@NonNull ControllerInfo controller, @NonNull Uri uri, @Nullable Bundle extras) { } - - /** - * Called when a controller wants to add a {@link MediaItem2} at the specified position - * in the play queue. - *

    - * The item from the media controller wouldn't have valid data source descriptor because - * it would have been anonymized when it's sent to the remote process. - * - * @param item The media item to be inserted. - * @param index The index at which the item is to be inserted. - */ - public void onAddPlaylistItem(@NonNull ControllerInfo controller, - @NonNull MediaItem2 item, int index) { } - - /** - * Called when a controller wants to remove the {@link MediaItem2} - * - * @param item - */ - // Can we do this automatically? - public void onRemovePlaylistItem(@NonNull MediaItem2 item) { } }; /** - * Base builder class for MediaSession2 and its subclass. - * + * Base builder class for MediaSession2 and its subclass. Any change in this class should be + * also applied to the subclasses {@link MediaSession2.Builder} and + * {@link MediaLibraryService2.MediaLibrarySessionBuilder}. + *

    + * APIs here should be package private, but should have documentations for developers. + * Otherwise, javadoc will generate documentation with the generic types such as follows. + *

    U extends BuilderBase setSessionCallback(Executor executor, C callback)
    + *

    + * This class is hidden to prevent from generating test stub, which fails with + * 'unexpected bound' because it tries to auto generate stub class as follows. + *

    abstract static class BuilderBase<
    +     *      T extends android.media.MediaSession2,
    +     *      U extends android.media.MediaSession2.BuilderBase<
    +     *              T, U, C extends android.media.MediaSession2.SessionCallback>, C>
    * @hide */ static abstract class BuilderBase - , C extends SessionCallback> { - final Context mContext; - final MediaPlayerInterface mPlayer; - String mId; - Executor mCallbackExecutor; - C mCallback; - VolumeProvider mVolumeProvider; - int mRatingType; - PendingIntent mSessionActivity; + , C extends SessionCallback> { + private final BuilderBaseProvider mProvider; - /** - * Constructor. - * - * @param context a context - * @param player a player to handle incoming command from any controller. - * @throws IllegalArgumentException if any parameter is null, or the player is a - * {@link MediaSession2} or {@link MediaController2}. - */ - // TODO(jaewan): Also need executor - public BuilderBase(@NonNull Context context, @NonNull MediaPlayerInterface player) { - if (context == null) { - throw new IllegalArgumentException("context shouldn't be null"); - } - if (player == null) { - throw new IllegalArgumentException("player shouldn't be null"); - } - mContext = context; - mPlayer = player; - // Ensure non-null - mId = ""; + BuilderBase(ProviderCreator, BuilderBaseProvider> creator) { + mProvider = creator.createProvider(this); } /** @@ -484,11 +611,11 @@ public class MediaSession2 implements AutoCloseable { *

    * Set {@code null} to reset. * - * @param volumeProvider The provider that will handle volume changes. Can be {@code null} + * @param volumeProvider The provider that will handle volume changes. Can be {@code null}. */ - public T setVolumeProvider(@Nullable VolumeProvider volumeProvider) { - mVolumeProvider = volumeProvider; - return (T) this; + U setVolumeProvider(@Nullable VolumeProvider2 volumeProvider) { + mProvider.setVolumeProvider_impl(volumeProvider); + return (U) this; } /** @@ -504,9 +631,9 @@ public class MediaSession2 implements AutoCloseable { *

  • {@link Rating2#RATING_THUMB_UP_DOWN}
  • * */ - public T setRatingType(@Rating2.Style int type) { - mRatingType = type; - return (T) this; + U setRatingType(@Rating2.Style int type) { + mProvider.setRatingType_impl(type); + return (U) this; } /** @@ -516,9 +643,9 @@ public class MediaSession2 implements AutoCloseable { * * @param pi The intent to launch to show UI for this session. */ - public T setSessionActivity(@Nullable PendingIntent pi) { - mSessionActivity = pi; - return (T) this; + U setSessionActivity(@Nullable PendingIntent pi) { + mProvider.setSessionActivity_impl(pi); + return (U) this; } /** @@ -531,12 +658,9 @@ public class MediaSession2 implements AutoCloseable { * @throws IllegalArgumentException if id is {@code null} * @return */ - public T setId(@NonNull String id) { - if (id == null) { - throw new IllegalArgumentException("id shouldn't be null"); - } - mId = id; - return (T) this; + U setId(@NonNull String id) { + mProvider.setId_impl(id); + return (U) this; } /** @@ -546,17 +670,10 @@ public class MediaSession2 implements AutoCloseable { * @param callback session callback. * @return */ - public T setSessionCallback(@NonNull @CallbackExecutor Executor executor, + U setSessionCallback(@NonNull @CallbackExecutor Executor executor, @NonNull C callback) { - if (executor == null) { - throw new IllegalArgumentException("executor shouldn't be null"); - } - if (callback == null) { - throw new IllegalArgumentException("callback shouldn't be null"); - } - mCallbackExecutor = executor; - mCallback = callback; - return (T) this; + mProvider.setSessionCallback_impl(executor, callback); + return (U) this; } /** @@ -566,7 +683,9 @@ public class MediaSession2 implements AutoCloseable { * @throws IllegalStateException if the session with the same id is already exists for the * package. */ - public abstract MediaSession2 build(); + T build() { + return mProvider.build_impl(); + } } /** @@ -575,24 +694,43 @@ public class MediaSession2 implements AutoCloseable { * Any incoming event from the {@link MediaController2} will be handled on the thread * that created session with the {@link Builder#build()}. */ - // TODO(jaewan): Move this to updatable - // TODO(jaewan): Add setRatingType() - // TODO(jaewan): Add setSessionActivity() - public static final class Builder extends BuilderBase { + // Override all methods just to show them with the type instead of generics in Javadoc. + // This workarounds javadoc issue described in the MediaSession2.BuilderBase. + public static final class Builder extends BuilderBase { public Builder(Context context, @NonNull MediaPlayerInterface player) { - super(context, player); + super((instance) -> ApiLoader.getProvider(context).createMediaSession2Builder( + context, (Builder) instance, player)); + } + + @Override + public Builder setVolumeProvider(@Nullable VolumeProvider2 volumeProvider) { + return super.setVolumeProvider(volumeProvider); + } + + @Override + public Builder setRatingType(@Rating2.Style int type) { + return super.setRatingType(type); + } + + @Override + public Builder setSessionActivity(@Nullable PendingIntent pi) { + return super.setSessionActivity(pi); + } + + @Override + public Builder setId(@NonNull String id) { + return super.setId(id); + } + + @Override + public Builder setSessionCallback(@NonNull Executor executor, + @Nullable SessionCallback callback) { + return super.setSessionCallback(executor, callback); } @Override public MediaSession2 build() { - if (mCallbackExecutor == null) { - mCallbackExecutor = mContext.getMainExecutor(); - } - if (mCallback == null) { - mCallback = new SessionCallback(mContext); - } - return new MediaSession2(mContext, mPlayer, mId, mVolumeProvider, mRatingType, - mSessionActivity, mCallbackExecutor, mCallback); + return super.build(); } } @@ -610,7 +748,7 @@ public class MediaSession2 implements AutoCloseable { public ControllerInfo(Context context, int uid, int pid, String packageName, IInterface callback) { mProvider = ApiLoader.getProvider(context) - .createMediaSession2ControllerInfoProvider( + .createMediaSession2ControllerInfo( context, this, uid, pid, packageName, callback); } @@ -639,6 +777,9 @@ public class MediaSession2 implements AutoCloseable { return mProvider.isTrusted_impl(); } + /** + * @hide + */ @SystemApi public ControllerInfoProvider getProvider() { return mProvider; @@ -671,32 +812,15 @@ public class MediaSession2 implements AutoCloseable { *

    * It's up to the controller's decision to respect or ignore this customization request. */ - // TODO(jaewan): Move this to updatable. public static class CommandButton { - private static final String KEY_COMMAND - = "android.media.media_session2.command_button.command"; - private static final String KEY_ICON_RES_ID - = "android.media.media_session2.command_button.icon_res_id"; - private static final String KEY_DISPLAY_NAME - = "android.media.media_session2.command_button.display_name"; - private static final String KEY_EXTRA - = "android.media.media_session2.command_button.extra"; - private static final String KEY_ENABLED - = "android.media.media_session2.command_button.enabled"; - - private Command mCommand; - private int mIconResId; - private String mDisplayName; - private Bundle mExtra; - private boolean mEnabled; - - private CommandButton(@Nullable Command command, int iconResId, - @Nullable String displayName, Bundle extra, boolean enabled) { - mCommand = command; - mIconResId = iconResId; - mDisplayName = displayName; - mExtra = extra; - mEnabled = enabled; + private final CommandButtonProvider mProvider; + + /** + * @hide + */ + @SystemApi + public CommandButton(CommandButtonProvider provider) { + mProvider = provider; } /** @@ -706,7 +830,7 @@ public class MediaSession2 implements AutoCloseable { * @return command or {@code null} */ public @Nullable Command getCommand() { - return mCommand; + return mProvider.getCommand_impl(); } /** @@ -716,7 +840,7 @@ public class MediaSession2 implements AutoCloseable { * @return resource id of the icon. Can be {@code 0}. */ public int getIconResId() { - return mIconResId; + return mProvider.getIconResId_impl(); } /** @@ -726,7 +850,7 @@ public class MediaSession2 implements AutoCloseable { * @return custom display name. Can be {@code null} or empty. */ public @Nullable String getDisplayName() { - return mDisplayName; + return mProvider.getDisplayName_impl(); } /** @@ -735,7 +859,7 @@ public class MediaSession2 implements AutoCloseable { * @return */ public @Nullable Bundle getExtra() { - return mExtra; + return mProvider.getExtra_impl(); } /** @@ -744,92 +868,50 @@ public class MediaSession2 implements AutoCloseable { * @return {@code true} if enabled. {@code false} otherwise. */ public boolean isEnabled() { - return mEnabled; - } - - /** - * @hide - */ - // TODO(jaewan): @SystemApi - public @NonNull Bundle toBundle() { - Bundle bundle = new Bundle(); - bundle.putBundle(KEY_COMMAND, mCommand.toBundle()); - bundle.putInt(KEY_ICON_RES_ID, mIconResId); - bundle.putString(KEY_DISPLAY_NAME, mDisplayName); - bundle.putBundle(KEY_EXTRA, mExtra); - bundle.putBoolean(KEY_ENABLED, mEnabled); - return bundle; + return mProvider.isEnabled_impl(); } /** * @hide */ - // TODO(jaewan): @SystemApi - public static @Nullable CommandButton fromBundle(Context context, Bundle bundle) { - Builder builder = new Builder(); - builder.setCommand(Command.fromBundle(context, bundle.getBundle(KEY_COMMAND))); - builder.setIconResId(bundle.getInt(KEY_ICON_RES_ID, 0)); - builder.setDisplayName(bundle.getString(KEY_DISPLAY_NAME)); - builder.setExtra(bundle.getBundle(KEY_EXTRA)); - builder.setEnabled(bundle.getBoolean(KEY_ENABLED)); - try { - return builder.build(); - } catch (IllegalStateException e) { - // Malformed or version mismatch. Return null for now. - return null; - } + @SystemApi + public CommandButtonProvider getProvider() { + return mProvider; } /** * Builder for {@link CommandButton}. */ public static class Builder { - private Command mCommand; - private int mIconResId; - private String mDisplayName; - private Bundle mExtra; - private boolean mEnabled; - - public Builder() { - mEnabled = true; + private final CommandButtonProvider.BuilderProvider mProvider; + + public Builder(@NonNull Context context) { + mProvider = ApiLoader.getProvider(context) + .createMediaSession2CommandButtonBuilder(context, this); } public Builder setCommand(Command command) { - mCommand = command; - return this; + return mProvider.setCommand_impl(command); } public Builder setIconResId(int resId) { - mIconResId = resId; - return this; + return mProvider.setIconResId_impl(resId); } public Builder setDisplayName(String displayName) { - mDisplayName = displayName; - return this; + return mProvider.setDisplayName_impl(displayName); } public Builder setEnabled(boolean enabled) { - mEnabled = enabled; - return this; + return mProvider.setEnabled_impl(enabled); } public Builder setExtra(Bundle extra) { - mExtra = extra; - return this; + return mProvider.setExtra_impl(extra); } public CommandButton build() { - if (mEnabled && mCommand == null) { - throw new IllegalStateException("Enabled button needs Command" - + " for controller to invoke the command"); - } - if (mCommand != null && mCommand.getCommandCode() == COMMAND_CODE_CUSTOM - && (mIconResId == 0 || TextUtils.isEmpty(mDisplayName))) { - throw new IllegalStateException("Custom commands needs icon and" - + " and name to display"); - } - return new CommandButton(mCommand, mIconResId, mDisplayName, mExtra, mEnabled); + return mProvider.build_impl(); } } } @@ -837,7 +919,7 @@ public class MediaSession2 implements AutoCloseable { /** * Parameter for the playlist. */ - public static class PlaylistParams { + public final static class PlaylistParams { /** * @hide */ @@ -892,79 +974,71 @@ public class MediaSession2 implements AutoCloseable { */ public static final int SHUFFLE_MODE_GROUP = 2; + + private final MediaSession2Provider.PlaylistParamsProvider mProvider; + /** - * Keys used for converting a PlaylistParams object to a bundle object and vice versa. + * Instantiate {@link PlaylistParams} + * + * @param context context + * @param repeatMode repeat mode + * @param shuffleMode shuffle mode + * @param playlistMetadata metadata for the list */ - private static final String KEY_REPEAT_MODE = - "android.media.session2.playlistparams2.repeat_mode"; - private static final String KEY_SHUFFLE_MODE = - "android.media.session2.playlistparams2.shuffle_mode"; - private static final String KEY_MEDIA_METADATA2_BUNDLE = - "android.media.session2.playlistparams2.metadata2_bundle"; - - private @RepeatMode int mRepeatMode; - private @ShuffleMode int mShuffleMode; - - private MediaMetadata2 mPlaylistMetadata; - - public PlaylistParams(@RepeatMode int repeatMode, @ShuffleMode int shuffleMode, - @Nullable MediaMetadata2 playlistMetadata) { - mRepeatMode = repeatMode; - mShuffleMode = shuffleMode; - mPlaylistMetadata = playlistMetadata; + public PlaylistParams(@NonNull Context context, @RepeatMode int repeatMode, + @ShuffleMode int shuffleMode, @Nullable MediaMetadata2 playlistMetadata) { + mProvider = ApiLoader.getProvider(context).createMediaSession2PlaylistParams( + context, this, repeatMode, shuffleMode, playlistMetadata); } - public @RepeatMode int getRepeatMode() { - return mRepeatMode; + /** + * Create a new bundle for this object. + * + * @return + */ + public @NonNull Bundle toBundle() { + return mProvider.toBundle_impl(); } - public @ShuffleMode int getShuffleMode() { - return mShuffleMode; + /** + * Create a new playlist params from the bundle that was previously returned by + * {@link #toBundle}. + * + * @param context context + * @return a new playlist params. Can be {@code null} for error. + */ + public static @Nullable PlaylistParams fromBundle( + @NonNull Context context, @Nullable Bundle bundle) { + return ApiLoader.getProvider(context).fromBundle_PlaylistParams(context, bundle); } - public MediaMetadata2 getPlaylistMetadata() { - return mPlaylistMetadata; + /** + * Get repeat mode + * + * @return repeat mode + * @see #REPEAT_MODE_NONE, #REPEAT_MODE_ONE, #REPEAT_MODE_ALL, #REPEAT_MODE_GROUP + */ + public @RepeatMode int getRepeatMode() { + return mProvider.getRepeatMode_impl(); } /** - * Returns this object as a bundle to share between processes. + * Get shuffle mode * - * @hide + * @return shuffle mode + * @see #SHUFFLE_MODE_NONE, #SHUFFLE_MODE_ALL, #SHUFFLE_MODE_GROUP */ - public Bundle toBundle() { - Bundle bundle = new Bundle(); - bundle.putInt(KEY_REPEAT_MODE, mRepeatMode); - bundle.putInt(KEY_SHUFFLE_MODE, mShuffleMode); - if (mPlaylistMetadata != null) { - bundle.putBundle(KEY_MEDIA_METADATA2_BUNDLE, mPlaylistMetadata.getBundle()); - } - return bundle; + public @ShuffleMode int getShuffleMode() { + return mProvider.getShuffleMode_impl(); } /** - * Creates an instance from a bundle which is previously created by {@link #toBundle()}. + * Get metadata for the playlist * - * @param bundle A bundle created by {@link #toBundle()}. - * @return A new {@link PlaylistParams} instance. Returns {@code null} if the given - * {@param bundle} is null, or if the {@param bundle} has no playlist parameters. - * @hide + * @return metadata. Can be {@code null} */ - public static PlaylistParams fromBundle(Bundle bundle) { - if (bundle == null) { - return null; - } - if (!bundle.containsKey(KEY_REPEAT_MODE) || !bundle.containsKey(KEY_SHUFFLE_MODE)) { - return null; - } - - Bundle metadataBundle = bundle.getBundle(KEY_MEDIA_METADATA2_BUNDLE); - MediaMetadata2 metadata = - metadataBundle == null ? null : new MediaMetadata2(metadataBundle); - - return new PlaylistParams( - bundle.getInt(KEY_REPEAT_MODE), - bundle.getInt(KEY_SHUFFLE_MODE), - metadata); + public @Nullable MediaMetadata2 getPlaylistMetadata() { + return mProvider.getPlaylistMetadata_impl(); } } @@ -982,23 +1056,15 @@ public class MediaSession2 implements AutoCloseable { * framework had to add heuristics to figure out if an app is * @hide */ - MediaSession2(Context context, MediaPlayerInterface player, String id, - VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity, - Executor callbackExecutor, SessionCallback callback) { + @SystemApi + public MediaSession2(MediaSession2Provider provider) { super(); - mProvider = createProvider(context, player, id, volumeProvider, ratingType, sessionActivity, - callbackExecutor, callback); - mProvider.initialize(); - } - - MediaSession2Provider createProvider(Context context, MediaPlayerInterface player, String id, - VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity, - Executor callbackExecutor, SessionCallback callback) { - return ApiLoader.getProvider(context) - .createMediaSession2(context, this, player, id, volumeProvider, ratingType, - sessionActivity, callbackExecutor, callback); + mProvider = provider; } + /** + * @hide + */ @SystemApi public MediaSession2Provider getProvider() { return mProvider; @@ -1012,8 +1078,8 @@ public class MediaSession2 implements AutoCloseable { * If the new player is successfully set, {@link PlaybackListener} * will be called to tell the current playback state of the new player. *

    - * You can also specify a volume provider. If so, playback in the player is considered as - * remote playback. + * For the remote playback case which you want to handle volume by yourself, use + * {@link #setPlayer(MediaPlayerInterface, VolumeProvider2)}. * * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app. * @throws IllegalArgumentException if the player is {@code null}. @@ -1028,10 +1094,10 @@ public class MediaSession2 implements AutoCloseable { * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app. * @param volumeProvider a volume provider * @see #setPlayer(MediaPlayerInterface) - * @see Builder#setVolumeProvider(VolumeProvider) + * @see Builder#setVolumeProvider(VolumeProvider2) */ public void setPlayer(@NonNull MediaPlayerInterface player, - @NonNull VolumeProvider volumeProvider) { + @NonNull VolumeProvider2 volumeProvider) { mProvider.setPlayer_impl(player, volumeProvider); } diff --git a/media/java/android/media/MediaSessionService2.java b/media/java/android/media/MediaSessionService2.java index 6b2de06942db9c5e0344fd3182a2a667f5d090d1..0b5dddf92af5f57c4ad924f891b1fa5619ba6c28 100644 --- a/media/java/android/media/MediaSessionService2.java +++ b/media/java/android/media/MediaSessionService2.java @@ -21,10 +21,12 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.Service; +import android.content.Context; import android.content.Intent; import android.media.MediaSession2.ControllerInfo; import android.media.update.ApiLoader; import android.media.update.MediaSessionService2Provider; +import android.media.update.MediaSessionService2Provider.MediaNotificationProvider; import android.os.IBinder; /** @@ -165,7 +167,6 @@ public abstract class MediaSessionService2 extends Service { * @param state playback state * @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown. */ - // TODO(jaewan): Also add metadata public MediaNotification onUpdateNotification(PlaybackState2 state) { return mProvider.onUpdateNotification_impl(state); } @@ -204,31 +205,31 @@ public abstract class MediaSessionService2 extends Service { * foreground service to keep playback running in the background. It's highly recommended to * show media style notification here. */ - // TODO(jaewan): Should we also move this to updatable? public static class MediaNotification { - public final int id; - public final Notification notification; - - private MediaNotification(int id, @NonNull Notification notification) { - this.id = id; - this.notification = notification; - } + private final MediaNotificationProvider mProvider; /** - * Create a {@link MediaNotification}. + * Default constructor * + * @param context context * @param notificationId notification id to be used for * {@link android.app.NotificationManager#notify(int, Notification)}. * @param notification a notification to make session service foreground service. Media * style notification is recommended here. - * @return */ - public static MediaNotification create(int notificationId, - @NonNull Notification notification) { - if (notification == null) { - throw new IllegalArgumentException("Notification cannot be null"); - } - return new MediaNotification(notificationId, notification); + public MediaNotification(@NonNull Context context, + int notificationId, @NonNull Notification notification) { + mProvider = ApiLoader.getProvider(context) + .createMediaSessionService2MediaNotification( + context, this, notificationId, notification); + } + + public int getNotificationId() { + return mProvider.getNotificationId_impl(); + } + + public Notification getNotification() { + return mProvider.getNotification_impl(); } } } diff --git a/media/java/android/media/MicrophoneInfo.java b/media/java/android/media/MicrophoneInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..131e37bd6646b50068ed3cfe051332f1f6f3555b --- /dev/null +++ b/media/java/android/media/MicrophoneInfo.java @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.IntDef; +import android.util.Pair; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Class providing information on a microphone. It indicates the location and orientation of the + * microphone on the device as well as useful information like frequency response and sensitivity. + * It can be used by applications implementing special pre processing effects like noise suppression + * of beam forming that need to know about precise microphone characteristics in order to adapt + * their algorithms. + */ +public final class MicrophoneInfo { + + /** + * A microphone that the location is unknown. + */ + public static final int LOCATION_UNKNOWN = 0; + + /** + * A microphone that locate on main body of the device. + */ + public static final int LOCATION_MAINBODY = 1; + + /** + * A microphone that locate on a movable main body of the device. + */ + public static final int LOCATION_MAINBODY_MOVABLE = 2; + + /** + * A microphone that locate on a peripheral. + */ + public static final int LOCATION_PERIPHERAL = 3; + + /** + * Unknown microphone directionality. + */ + public static final int DIRECTIONALITY_UNKNOWN = 0; + + /** + * Microphone directionality type: omni. + */ + public static final int DIRECTIONALITY_OMNI = 1; + + /** + * Microphone directionality type: bi-directional. + */ + public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2; + + /** + * Microphone directionality type: cardioid. + */ + public static final int DIRECTIONALITY_CARDIOID = 3; + + /** + * Microphone directionality type: hyper cardioid. + */ + public static final int DIRECTIONALITY_HYPER_CARDIOID = 4; + + /** + * Microphone directionality type: super cardioid. + */ + public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; + + /** + * The channel contains raw audio from this microphone. + */ + public static final int CHANNEL_MAPPING_DIRECT = 1; + + /** + * The channel contains processed audio from this microphone and possibly another microphone. + */ + public static final int CHANNEL_MAPPING_PROCESSED = 2; + + /** @hide */ + @IntDef(flag = true, prefix = { "LOCATION_" }, value = { + LOCATION_UNKNOWN, + LOCATION_MAINBODY, + LOCATION_MAINBODY_MOVABLE, + LOCATION_PERIPHERAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MicrophoneLocation {} + + /** @hide */ + @IntDef(flag = true, prefix = { "DIRECTIONALITY_" }, value = { + DIRECTIONALITY_UNKNOWN, + DIRECTIONALITY_OMNI, + DIRECTIONALITY_BI_DIRECTIONAL, + DIRECTIONALITY_CARDIOID, + DIRECTIONALITY_HYPER_CARDIOID, + DIRECTIONALITY_SUPER_CARDIOID, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MicrophoneDirectionality {} + + private Coordinate3F mPosition; + private Coordinate3F mOrientation; + private String mDeviceId; + private String mAddress; + private List> mFrequencyResponse; + private List> mChannelMapping; + private float mMaxSpl; + private float mMinSpl; + private float mSensitivity; + private int mLocation; + private int mGroup; /* Usually 0 will be used for main body. */ + private int mIndexInTheGroup; + private int mPortId; /* mPortId will correspond to the id in AudioPort */ + private int mType; + private int mDirectionality; + + MicrophoneInfo(String deviceId, int type, String address, int location, + int group, int indexInTheGroup, Coordinate3F position, + Coordinate3F orientation, List> frequencyResponse, + List> channelMapping, float sensitivity, float maxSpl, + float minSpl, int directionality) { + mDeviceId = deviceId; + mType = type; + mAddress = address; + mLocation = location; + mGroup = group; + mIndexInTheGroup = indexInTheGroup; + mPosition = position; + mOrientation = orientation; + mFrequencyResponse = frequencyResponse; + mChannelMapping = channelMapping; + mSensitivity = sensitivity; + mMaxSpl = maxSpl; + mMinSpl = minSpl; + mDirectionality = directionality; + } + + /** + * Returns alphanumeric code that uniquely identifies the device. + * + * @return the description of the microphone + */ + public String getDescription() { + return mDeviceId; + } + + /** + * Returns The system unique device ID that corresponds to the id + * returned by {@link AudioDeviceInfo#getId()}. + * + * @return the microphone's id + */ + public int getId() { + return mPortId; + } + + /** + * @hide + * Returns the internal device type (e.g AudioSystem.DEVICE_IN_BUILTIN_MIC). + * The internal device type could be used when getting microphone's port id + * by matching type and address. + * + * @return the internal device type + */ + public int getInternalDeviceType() { + return mType; + } + + /** + * Returns the device type identifier of the microphone (e.g AudioDeviceInfo.TYPE_BUILTIN_MIC). + * + * @return the device type of the microphone + */ + public int getType() { + return AudioDeviceInfo.convertInternalDeviceToDeviceType(mType); + } + + /** + * @hide + * Returns The "address" string of the microphone that corresponds to the + * address returned by {@link AudioDeviceInfo#getAddress()} + * @return the address of the microphone + */ + public String getAddress() { + return mAddress; + } + + /** + * Returns the location of the microphone. The return value is + * one of {@link #LOCATION_UNKNOWN}, {@link #LOCATION_MAINBODY}, + * {@link #LOCATION_MAINBODY_MOVABLE}, or {@link #LOCATION_PERIPHERAL}. + * + * @return the location of the microphone + */ + public @MicrophoneLocation int getLocation() { + return mLocation; + } + + /** + * Returns A device group id that can be used to group together microphones on the same + * peripheral, attachments or logical groups. Main body is usually group 0. + * + * @return the group of the microphone + */ + public int getGroup() { + return mGroup; + } + + /** + * Returns unique index for device within its group. + * + * @return the microphone's index in its group + */ + public int getIndexInTheGroup() { + return mIndexInTheGroup; + } + + /** + * Returns A {@link Coordinate3F} object that represents the geometric location of microphone + * in meters, from botton-left-back corner of appliance. X-axis, Y-axis and Z-axis show + * as the x, y, z values. + * + * @return the geometric location of the microphone + */ + public Coordinate3F getPosition() { + return mPosition; + } + + /** + * Returns A {@link Coordinate3F} object that represents the orientation of microphone. + * X-axis, Y-axis and Z-axis show as the x, y, z value. The orientation will be normalized + * such as sqrt(x^2 + y^2 + z^2) equals 1. + * + * @return the orientation of the microphone + */ + public Coordinate3F getOrientation() { + return mOrientation; + } + + /** + * Returns a {@link android.util.Pair} list of frequency responses. + * For every {@link android.util.Pair} in the list, the first value represents frequency in Hz, + * and the second value represents response in dB. + * + * @return the frequency response of the microphone + */ + public List> getFrequencyResponse() { + return mFrequencyResponse; + } + + /** + * Returns a {@link android.util.Pair} list for channel mapping, which indicating how this + * microphone is used by each channels or a capture stream. For each {@link android.util.Pair}, + * the first value is channel index, the second value is channel mapping type, which could be + * either {@link #CHANNEL_MAPPING_DIRECT} or {@link #CHANNEL_MAPPING_PROCESSED}. + * If a channel has contributions from more than one microphone, it is likely the HAL + * did some extra processing to combine the sources, but this is to be inferred by the user. + * Empty list when the MicrophoneInfo is returned by AudioManager.getMicrophones(). + * At least one entry when the MicrophoneInfo is returned by AudioRecord.getActiveMicrophones(). + * + * @return a {@link android.util.Pair} list for channel mapping + */ + public List> getChannelMapping() { + return mChannelMapping; + } + + /** + * Returns the level in dBFS produced by a 1000Hz tone at 94 dB SPL. + * + * @return the sensitivity of the microphone + */ + public float getSensitivity() { + return mSensitivity; + } + + /** + * Returns the level in dB of the maximum SPL supported by the device at 1000Hz. + * + * @return the maximum level in dB + */ + public float getMaxSpl() { + return mMaxSpl; + } + + /** + * Returns the level in dB of the minimum SPL that can be registered by the device at 1000Hz. + * + * @return the minimum level in dB + */ + public float getMinSpl() { + return mMinSpl; + } + + /** + * Returns the directionality of microphone. The return value is one of + * {@link #DIRECTIONALITY_UNKNOWN}, {@link #DIRECTIONALITY_OMNI}, + * {@link #DIRECTIONALITY_BI_DIRECTIONAL}, {@link #DIRECTIONALITY_CARDIOID}, + * {@link #DIRECTIONALITY_HYPER_CARDIOID}, or {@link #DIRECTIONALITY_SUPER_CARDIOID}. + * + * @return the directionality of microphone + */ + public @MicrophoneDirectionality int getDirectionality() { + return mDirectionality; + } + + /** + * Set the port id for the device. + * @hide + */ + public void setId(int portId) { + mPortId = portId; + } + + /* A class containing three float value to represent a 3D coordinate */ + public class Coordinate3F { + public final float x; + public final float y; + public final float z; + + Coordinate3F(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + } +} diff --git a/media/java/android/media/PlaybackState2.java b/media/java/android/media/PlaybackState2.java index da776ebefa38adcc8a001f39f0b2220a96bb3eaa..627974a871377f64e051c12dc8335b7bcbed2cdd 100644 --- a/media/java/android/media/PlaybackState2.java +++ b/media/java/android/media/PlaybackState2.java @@ -17,6 +17,11 @@ package android.media; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.media.update.ApiLoader; +import android.media.update.PlaybackState2Provider; import android.os.Bundle; import java.lang.annotation.Retention; @@ -29,14 +34,51 @@ import java.lang.annotation.RetentionPolicy; * @hide */ public final class PlaybackState2 { - private static final String TAG = "PlaybackState2"; - + // Similar to the PlaybackState2 with following changes + // - Not implement Parcelable and added from/toBundle() + // - Removed playback state that doesn't match with the MediaPlayer2 + // Full list should be finalized when the MediaPlayer2 has getter for the playback state. + // Here's table for the MP2 state and PlaybackState2.State. + // +----------------------------------------+----------------------------------------+ + // | MediaPlayer2 state | Matching PlaybackState2.State | + // | (Names are from MP2' Javadoc) | | + // +----------------------------------------+----------------------------------------+ + // | Idle: Just finished creating MP2 | STATE_NONE | + // | or reset() is called | | + // +----------------------------------------+----------------------------------------+ + // | Initialized: setDataSource/Playlist | N/A (Session/Controller don't | + // | | differentiate with Prepared) | + // +----------------------------------------+----------------------------------------+ + // | Prepared: Prepared after initialized | STATE_PAUSED | + // +----------------------------------------+----------------------------------------+ + // | Started: Started playback | STATE_PLAYING | + // +----------------------------------------+----------------------------------------+ + // | Paused: Paused playback | STATE_PAUSED | + // +----------------------------------------+----------------------------------------+ + // | PlaybackCompleted: Playback is done | STATE_PAUSED | + // +----------------------------------------+----------------------------------------+ + // | Stopped: MP2.stop() is called. | STATE_STOPPED | + // | prepare() is needed to play again | | + // | (Seemingly the same as initialized | | + // | because cannot set data source | | + // | after this) | | + // +----------------------------------------+----------------------------------------+ + // | Error: an API is called in a state | STATE_ERROR | + // | that the API isn't supported | | + // +----------------------------------------+----------------------------------------+ + // | End: MP2.close() is called to release | N/A (MediaSession will be gone) | + // | MP2. Cannot be reused anymore | | + // +----------------------------------------+----------------------------------------+ + // | Started, but | STATE_BUFFERING | + // | EventCallback.onBufferingUpdate() | | + // +----------------------------------------+----------------------------------------+ + // - Removed actions and custom actions. + // - Repeat mode / shuffle mode is now in the PlaylistParams // TODO(jaewan): Replace states from MediaPlayer2 /** * @hide */ - @IntDef({STATE_NONE, STATE_STOPPED, STATE_PREPARED, STATE_PAUSED, STATE_PLAYING, - STATE_FINISH, STATE_BUFFERING, STATE_ERROR}) + @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_BUFFERING, STATE_ERROR}) @Retention(RetentionPolicy.SOURCE) public @interface State {} @@ -51,89 +93,47 @@ public final class PlaybackState2 { */ public final static int STATE_STOPPED = 1; - /** - * State indicating this item is currently prepared - */ - public final static int STATE_PREPARED = 2; - /** * State indicating this item is currently paused. */ - public final static int STATE_PAUSED = 3; + public final static int STATE_PAUSED = 2; /** * State indicating this item is currently playing. */ - public final static int STATE_PLAYING = 4; - - /** - * State indicating the playback reaches the end of the item. - */ - public final static int STATE_FINISH = 5; + public final static int STATE_PLAYING = 3; /** * State indicating this item is currently buffering and will begin playing * when enough data has buffered. */ - public final static int STATE_BUFFERING = 6; + public final static int STATE_BUFFERING = 4; /** * State indicating this item is currently in an error state. The error * message should also be set when entering this state. */ - public final static int STATE_ERROR = 7; + public final static int STATE_ERROR = 5; /** * Use this value for the position to indicate the position is not known. */ public final static long PLAYBACK_POSITION_UNKNOWN = -1; - /** - * Keys used for converting a PlaybackState2 to a bundle object and vice versa. - */ - private static final String KEY_STATE = "android.media.playbackstate2.state"; - private static final String KEY_POSITION = "android.media.playbackstate2.position"; - private static final String KEY_BUFFERED_POSITION = - "android.media.playbackstate2.buffered_position"; - private static final String KEY_SPEED = "android.media.playbackstate2.speed"; - private static final String KEY_ERROR_MESSAGE = "android.media.playbackstate2.error_message"; - private static final String KEY_UPDATE_TIME = "android.media.playbackstate2.update_time"; - private static final String KEY_ACTIVE_ITEM_ID = "android.media.playbackstate2.active_item_id"; - - private final int mState; - private final long mPosition; - private final long mUpdateTime; - private final float mSpeed; - private final long mBufferedPosition; - private final long mActiveItemId; - private final CharSequence mErrorMessage; + private final PlaybackState2Provider mProvider; // TODO(jaewan): Better error handling? // E.g. media item at #2 has issue, but continue playing #3 // login error. fire intent xxx to login - public PlaybackState2(int state, long position, long updateTime, float speed, - long bufferedPosition, long activeItemId, CharSequence error) { - mState = state; - mPosition = position; - mSpeed = speed; - mUpdateTime = updateTime; - mBufferedPosition = bufferedPosition; - mActiveItemId = activeItemId; - mErrorMessage = error; + public PlaybackState2(@NonNull Context context, int state, long position, long updateTime, + float speed, long bufferedPosition, long activeItemId, CharSequence error) { + mProvider = ApiLoader.getProvider(context).createPlaybackState2(context, this, state, + position, updateTime, speed, bufferedPosition, activeItemId, error); } @Override public String toString() { - StringBuilder bob = new StringBuilder("PlaybackState {"); - bob.append("state=").append(mState); - bob.append(", position=").append(mPosition); - bob.append(", buffered position=").append(mBufferedPosition); - bob.append(", speed=").append(mSpeed); - bob.append(", updated=").append(mUpdateTime); - bob.append(", active item id=").append(mActiveItemId); - bob.append(", error=").append(mErrorMessage); - bob.append("}"); - return bob.toString(); + return mProvider.toString_impl(); } /** @@ -141,22 +141,24 @@ public final class PlaybackState2 { *

      *
    • {@link PlaybackState2#STATE_NONE}
    • *
    • {@link PlaybackState2#STATE_STOPPED}
    • - *
    • {@link PlaybackState2#STATE_PLAYING}
    • + *
    • {@link PlaybackState2#STATE_PREPARED}
    • *
    • {@link PlaybackState2#STATE_PAUSED}
    • + *
    • {@link PlaybackState2#STATE_PLAYING}
    • + *
    • {@link PlaybackState2#STATE_FINISH}
    • *
    • {@link PlaybackState2#STATE_BUFFERING}
    • *
    • {@link PlaybackState2#STATE_ERROR}
    • *
    */ @State public int getState() { - return mState; + return mProvider.getState_impl(); } /** * Get the current playback position in ms. */ public long getPosition() { - return mPosition; + return mProvider.getPosition_impl(); } /** @@ -165,7 +167,7 @@ public final class PlaybackState2 { * content. */ public long getBufferedPosition() { - return mBufferedPosition; + return mProvider.getBufferedPosition_impl(); } /** @@ -176,7 +178,7 @@ public final class PlaybackState2 { * @return The current speed of playback. */ public float getPlaybackSpeed() { - return mSpeed; + return mProvider.getPlaybackSpeed_impl(); } /** @@ -184,7 +186,7 @@ public final class PlaybackState2 { * {@link PlaybackState2#STATE_ERROR}. */ public CharSequence getErrorMessage() { - return mErrorMessage; + return mProvider.getErrorMessage_impl(); } /** @@ -194,7 +196,7 @@ public final class PlaybackState2 { * @return The last time the position was updated. */ public long getLastPositionUpdateTime() { - return mUpdateTime; + return mProvider.getLastPositionUpdateTime_impl(); } /** @@ -203,53 +205,26 @@ public final class PlaybackState2 { * @return The id of the currently active item in the queue */ public long getCurrentPlaylistItemIndex() { - return mActiveItemId; + return mProvider.getCurrentPlaylistItemIndex_impl(); } /** * Returns this object as a bundle to share between processes. */ - public Bundle toBundle() { - Bundle bundle = new Bundle(); - bundle.putInt(KEY_STATE, mState); - bundle.putLong(KEY_POSITION, mPosition); - bundle.putLong(KEY_UPDATE_TIME, mUpdateTime); - bundle.putFloat(KEY_SPEED, mSpeed); - bundle.putLong(KEY_BUFFERED_POSITION, mBufferedPosition); - bundle.putLong(KEY_ACTIVE_ITEM_ID, mActiveItemId); - bundle.putCharSequence(KEY_ERROR_MESSAGE, mErrorMessage); - return bundle; + public @NonNull Bundle toBundle() { + return mProvider.toBundle_impl(); } /** * Creates an instance from a bundle which is previously created by {@link #toBundle()}. * + * @param context context * @param bundle A bundle created by {@link #toBundle()}. * @return A new {@link PlaybackState2} instance. Returns {@code null} if the given * {@param bundle} is null, or if the {@param bundle} has no playback state parameters. */ - public static PlaybackState2 fromBundle(Bundle bundle) { - if (bundle == null) { - return null; - } - - if (!bundle.containsKey(KEY_STATE) - || !bundle.containsKey(KEY_POSITION) - || !bundle.containsKey(KEY_UPDATE_TIME) - || !bundle.containsKey(KEY_SPEED) - || !bundle.containsKey(KEY_BUFFERED_POSITION) - || !bundle.containsKey(KEY_ACTIVE_ITEM_ID) - || !bundle.containsKey(KEY_ERROR_MESSAGE)) { - return null; - } - - return new PlaybackState2( - bundle.getInt(KEY_STATE), - bundle.getLong(KEY_POSITION), - bundle.getLong(KEY_UPDATE_TIME), - bundle.getFloat(KEY_SPEED), - bundle.getLong(KEY_BUFFERED_POSITION), - bundle.getLong(KEY_ACTIVE_ITEM_ID), - bundle.getCharSequence(KEY_ERROR_MESSAGE)); + public @Nullable static PlaybackState2 fromBundle(@NonNull Context context, + @Nullable Bundle bundle) { + return ApiLoader.getProvider(context).fromBundle_PlaybackState2(context, bundle); } } \ No newline at end of file diff --git a/media/java/android/media/Rating2.java b/media/java/android/media/Rating2.java index 93aea6f9c1d7a3895e431d6c81048e6891cb8825..4f77ecd5814961d50b13d02e39254f54f830e611 100644 --- a/media/java/android/media/Rating2.java +++ b/media/java/android/media/Rating2.java @@ -16,7 +16,13 @@ package android.media; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.IntDef; +import android.annotation.SystemApi; +import android.content.Context; +import android.media.update.ApiLoader; +import android.media.update.Rating2Provider; import android.os.Bundle; import android.util.Log; @@ -33,10 +39,8 @@ import java.lang.annotation.RetentionPolicy; * @hide */ public final class Rating2 { - private static final String TAG = "Rating2"; - - private static final String KEY_STYLE = "android.media.rating2.style"; - private static final String KEY_VALUE = "android.media.rating2.value"; + // Mostly same as the android.media.Rating, but it's no longer implements Parcelable for + // updatable support. /** * @hide @@ -91,31 +95,48 @@ public final class Rating2 { */ public final static int RATING_PERCENTAGE = 6; - private final static float RATING_NOT_RATED = -1.0f; + private final Rating2Provider mProvider; - private final int mRatingStyle; + /** + * @hide + */ + @SystemApi + public Rating2(@NonNull Rating2Provider provider) { + mProvider = provider; + } - private final float mRatingValue; + @Override + public String toString() { + return mProvider.toString_impl(); + } - private Rating2(@Style int ratingStyle, float rating) { - mRatingStyle = ratingStyle; - mRatingValue = rating; + /** + * @hide + */ + @SystemApi + public Rating2Provider getProvider() { + return mProvider; } @Override - public String toString() { - return "Rating2:style=" + mRatingStyle + " rating=" - + (mRatingValue < 0.0f ? "unrated" : String.valueOf(mRatingValue)); + public boolean equals(Object obj) { + return mProvider.equals_impl(obj); + } + + @Override + public int hashCode() { + return mProvider.hashCode_impl(); } /** * Create an instance from bundle object, previoulsy created by {@link #toBundle()} * + * @param context context * @param bundle bundle - * @return new Rating2 instance + * @return new Rating2 instance or {@code null} for error */ - public static Rating2 fromBundle(Bundle bundle) { - return new Rating2(bundle.getInt(KEY_STYLE), bundle.getFloat(KEY_VALUE)); + public static Rating2 fromBundle(@NonNull Context context, @Nullable Bundle bundle) { + return ApiLoader.getProvider(context).fromBundle_Rating2(context, bundle); } /** @@ -123,55 +144,45 @@ public final class Rating2 { * @return bundle of this object */ public Bundle toBundle() { - Bundle bundle = new Bundle(); - bundle.putInt(KEY_STYLE, mRatingStyle); - bundle.putFloat(KEY_VALUE, mRatingValue); - return bundle; + return mProvider.toBundle_impl(); } /** * Return a Rating2 instance with no rating. * Create and return a new Rating2 instance with no rating known for the given * rating style. + * @param context context * @param ratingStyle one of {@link #RATING_HEART}, {@link #RATING_THUMB_UP_DOWN}, * {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS}, * or {@link #RATING_PERCENTAGE}. * @return null if an invalid rating style is passed, a new Rating2 instance otherwise. */ - public static Rating2 newUnratedRating(@Style int ratingStyle) { - switch(ratingStyle) { - case RATING_HEART: - case RATING_THUMB_UP_DOWN: - case RATING_3_STARS: - case RATING_4_STARS: - case RATING_5_STARS: - case RATING_PERCENTAGE: - return new Rating2(ratingStyle, RATING_NOT_RATED); - default: - return null; - } + public static @Nullable Rating2 newUnratedRating(@NonNull Context context, @Style int ratingStyle) { + return ApiLoader.getProvider(context).newUnratedRating_Rating2(context, ratingStyle); } /** * Return a Rating2 instance with a heart-based rating. * Create and return a new Rating2 instance with a rating style of {@link #RATING_HEART}, * and a heart-based rating. + * @param context context * @param hasHeart true for a "heart selected" rating, false for "heart unselected". * @return a new Rating2 instance. */ - public static Rating2 newHeartRating(boolean hasHeart) { - return new Rating2(RATING_HEART, hasHeart ? 1.0f : 0.0f); + public static @Nullable Rating2 newHeartRating(@NonNull Context context, boolean hasHeart) { + return ApiLoader.getProvider(context).newHeartRating_Rating2(context, hasHeart); } /** * Return a Rating2 instance with a thumb-based rating. * Create and return a new Rating2 instance with a {@link #RATING_THUMB_UP_DOWN} * rating style, and a "thumb up" or "thumb down" rating. + * @param context context * @param thumbIsUp true for a "thumb up" rating, false for "thumb down". * @return a new Rating2 instance. */ - public static Rating2 newThumbRating(boolean thumbIsUp) { - return new Rating2(RATING_THUMB_UP_DOWN, thumbIsUp ? 1.0f : 0.0f); + public static @Nullable Rating2 newThumbRating(@NonNull Context context, boolean thumbIsUp) { + return ApiLoader.getProvider(context).newThumbRating_Rating2(context, thumbIsUp); } /** @@ -179,6 +190,7 @@ public final class Rating2 { * Create and return a new Rating2 instance with one of the star-base rating styles * and the given integer or fractional number of stars. Non integer values can for instance * be used to represent an average rating value, which might not be an integer number of stars. + * @param context context * @param starRatingStyle one of {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, * {@link #RATING_5_STARS}. * @param starRating a number ranging from 0.0f to 3.0f, 4.0f or 5.0f according to @@ -186,51 +198,30 @@ public final class Rating2 { * @return null if the rating style is invalid, or the rating is out of range, * a new Rating2 instance otherwise. */ - public static Rating2 newStarRating(@StarStyle int starRatingStyle, float starRating) { - float maxRating = -1.0f; - switch(starRatingStyle) { - case RATING_3_STARS: - maxRating = 3.0f; - break; - case RATING_4_STARS: - maxRating = 4.0f; - break; - case RATING_5_STARS: - maxRating = 5.0f; - break; - default: - Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating"); - return null; - } - if ((starRating < 0.0f) || (starRating > maxRating)) { - Log.e(TAG, "Trying to set out of range star-based rating"); - return null; - } - return new Rating2(starRatingStyle, starRating); + public static @Nullable Rating2 newStarRating(@NonNull Context context, + @StarStyle int starRatingStyle, float starRating) { + return ApiLoader.getProvider(context).newStarRating_Rating2( + context, starRatingStyle, starRating); } /** * Return a Rating2 instance with a percentage-based rating. * Create and return a new Rating2 instance with a {@link #RATING_PERCENTAGE} * rating style, and a rating of the given percentage. + * @param context context * @param percent the value of the rating * @return null if the rating is out of range, a new Rating2 instance otherwise. */ - public static Rating2 newPercentageRating(float percent) { - if ((percent < 0.0f) || (percent > 100.0f)) { - Log.e(TAG, "Invalid percentage-based rating value"); - return null; - } else { - return new Rating2(RATING_PERCENTAGE, percent); - } + public static @Nullable Rating2 newPercentageRating(@NonNull Context context, float percent) { + return ApiLoader.getProvider(context).newPercentageRating_Rating2(context, percent); } /** * Return whether there is a rating value available. - * @return true if the instance was not created with {@link #newUnratedRating(int)}. + * @return true if the instance was not created with {@link #newUnratedRating(Context, int)}. */ public boolean isRated() { - return mRatingValue >= 0.0f; + return mProvider.isRated_impl(); } /** @@ -241,7 +232,7 @@ public final class Rating2 { */ @Style public int getRatingStyle() { - return mRatingStyle; + return mProvider.getRatingStyle_impl(); } /** @@ -250,11 +241,7 @@ public final class Rating2 { * if the rating style is not {@link #RATING_HEART} or if it is unrated. */ public boolean hasHeart() { - if (mRatingStyle != RATING_HEART) { - return false; - } else { - return (mRatingValue == 1.0f); - } + return mProvider.hasHeart_impl(); } /** @@ -263,11 +250,7 @@ public final class Rating2 { * if the rating style is not {@link #RATING_THUMB_UP_DOWN} or if it is unrated. */ public boolean isThumbUp() { - if (mRatingStyle != RATING_THUMB_UP_DOWN) { - return false; - } else { - return (mRatingValue == 1.0f); - } + return mProvider.isThumbUp_impl(); } /** @@ -276,16 +259,7 @@ public final class Rating2 { * not star-based, or if it is unrated. */ public float getStarRating() { - switch (mRatingStyle) { - case RATING_3_STARS: - case RATING_4_STARS: - case RATING_5_STARS: - if (isRated()) { - return mRatingValue; - } - default: - return -1.0f; - } + return mProvider.getStarRating_impl(); } /** @@ -294,10 +268,6 @@ public final class Rating2 { * not percentage-based, or if it is unrated. */ public float getPercentRating() { - if ((mRatingStyle != RATING_PERCENTAGE) || !isRated()) { - return -1.0f; - } else { - return mRatingValue; - } + return mProvider.getPercentRating_impl(); } } diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 3eb9d529b75602fce24ac5bd2e11d40873c860d1..fefa1ede849e7b4d3dc56f4c9a6f603c92174fd3 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -28,11 +28,13 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.database.Cursor; import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.net.Uri; import android.os.Environment; +import android.os.FileUtils; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; @@ -47,22 +49,17 @@ import android.util.Log; import com.android.internal.database.SortCursor; -import libcore.io.Streams; - import java.io.Closeable; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; -import static android.content.ContentProvider.maybeAddUserId; -import static android.content.pm.PackageManager.NameNotFoundException; - /** * RingtoneManager provides access to ringtones, notification, and other types * of sounds. It manages querying the different media providers and combines the @@ -855,7 +852,7 @@ public class RingtoneManager { final Uri cacheUri = getCacheForType(type, context.getUserId()); try (InputStream in = openRingtone(context, ringtoneUri); OutputStream out = resolver.openOutputStream(cacheUri)) { - Streams.copy(in, out); + FileUtils.copy(in, out); } catch (IOException e) { Log.w(TAG, "Failed to cache ringtone: " + e); } @@ -960,7 +957,7 @@ public class RingtoneManager { // Copy contents to external ringtone storage. Throws IOException if the copy fails. try (final InputStream input = mContext.getContentResolver().openInputStream(fileUri); final OutputStream output = new FileOutputStream(outFile)) { - Streams.copy(input, output); + FileUtils.copy(input, output); } // Tell MediaScanner about the new file. Wait for it to assign a {@link Uri}. diff --git a/media/java/android/media/VolumeProvider2.java b/media/java/android/media/VolumeProvider2.java new file mode 100644 index 0000000000000000000000000000000000000000..53ba4663aaf6baa0ad8054628de9ea8b2c78000e --- /dev/null +++ b/media/java/android/media/VolumeProvider2.java @@ -0,0 +1,151 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.content.Context; +import android.media.update.ApiLoader; +import android.media.update.VolumeProvider2Provider; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Handles requests to adjust or set the volume on a session. This is also used + * to push volume updates back to the session. The provider must call + * {@link #setCurrentVolume(int)} each time the volume being provided changes. + *

    + * You can set a volume provider on a session by calling + * {@link MediaSession2#setPlayer(MediaPlayerInterface, VolumeProvider2)}. + * + * @hide + */ +public abstract class VolumeProvider2 { + + /** + * @hide + */ + @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE}) + @Retention(RetentionPolicy.SOURCE) + public @interface ControlType {} + + /** + * The volume is fixed and can not be modified. Requests to change volume + * should be ignored. + */ + public static final int VOLUME_CONTROL_FIXED = 0; + + /** + * The volume control uses relative adjustment via + * {@link #onAdjustVolume(int)}. Attempts to set the volume to a specific + * value should be ignored. + */ + public static final int VOLUME_CONTROL_RELATIVE = 1; + + /** + * The volume control uses an absolute value. It may be adjusted using + * {@link #onAdjustVolume(int)} or set directly using + * {@link #onSetVolumeTo(int)}. + */ + public static final int VOLUME_CONTROL_ABSOLUTE = 2; + + private final VolumeProvider2Provider mProvider; + + /** + * Create a new volume provider for handling volume events. You must specify + * the type of volume control, the maximum volume that can be used, and the + * current volume on the output. + * + * @param controlType The method for controlling volume that is used by this provider. + * @param maxVolume The maximum allowed volume. + * @param currentVolume The current volume on the output. + */ + public VolumeProvider2(@NonNull Context context, @ControlType int controlType, + int maxVolume, int currentVolume) { + mProvider = ApiLoader.getProvider(context).createVolumeProvider2( + context, this, controlType, maxVolume, currentVolume); + } + + /** + * @hide + */ + @SystemApi + public VolumeProvider2Provider getProvider() { + return mProvider; + } + + /** + * Get the volume control type that this volume provider uses. + * + * @return The volume control type for this volume provider + */ + @ControlType + public final int getControlType() { + return mProvider.getControlType_impl(); + } + + /** + * Get the maximum volume this provider allows. + * + * @return The max allowed volume. + */ + public final int getMaxVolume() { + return mProvider.getMaxVolume_impl(); + } + + /** + * Gets the current volume. This will be the last value set by + * {@link #setCurrentVolume(int)}. + * + * @return The current volume. + */ + public final int getCurrentVolume() { + return mProvider.getCurrentVolume_impl(); + } + + /** + * Notify the system that the current volume has been changed. This must be + * called every time the volume changes to ensure it is displayed properly. + * + * @param currentVolume The current volume on the output. + */ + public final void setCurrentVolume(int currentVolume) { + mProvider.setCurrentVolume_impl(currentVolume); + } + + /** + * Override to handle requests to set the volume of the current output. + * After the volume has been modified {@link #setCurrentVolume} must be + * called to notify the system. + * + * @param volume The volume to set the output to. + */ + public void onSetVolumeTo(int volume) { } + + /** + * Override to handle requests to adjust the volume of the current output. + * Direction will be one of {@link AudioManager#ADJUST_LOWER}, + * {@link AudioManager#ADJUST_RAISE}, {@link AudioManager#ADJUST_SAME}. + * After the volume has been modified {@link #setCurrentVolume} must be + * called to notify the system. + * + * @param direction The direction to change the volume in. + */ + public void onAdjustVolume(int direction) { } +} diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java index 0fe7246e85c46ead285feb48dedc9c435635f189..f2b4fe093248e08ff7eeb4e611b3c7f78d55cebd 100644 --- a/media/java/android/media/audiofx/Visualizer.java +++ b/media/java/android/media/audiofx/Visualizer.java @@ -546,22 +546,39 @@ public class Visualizer { /** * Method called when a new waveform capture is available. *

    Data in the waveform buffer is valid only within the scope of the callback. - * Applications which needs access to the waveform data after returning from the callback + * Applications which need access to the waveform data after returning from the callback * should make a copy of the data instead of holding a reference. * @param visualizer Visualizer object on which the listener is registered. * @param waveform array of bytes containing the waveform representation. - * @param samplingRate sampling rate of the audio visualized. + * @param samplingRate sampling rate of the visualized audio. */ void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate); /** * Method called when a new frequency capture is available. *

    Data in the fft buffer is valid only within the scope of the callback. - * Applications which needs access to the fft data after returning from the callback + * Applications which need access to the fft data after returning from the callback * should make a copy of the data instead of holding a reference. + * + *

    In order to obtain magnitude and phase values the following formulas can + * be used: + *

    +         *       for (int i = 0; i < fft.size(); i += 2) {
    +         *           float magnitude = (float)Math.hypot(fft[i], fft[i + 1]);
    +         *           float phase = (float)Math.atan2(fft[i + 1], fft[i]);
    +         *       }
    * @param visualizer Visualizer object on which the listener is registered. * @param fft array of bytes containing the frequency representation. - * @param samplingRate sampling rate of the audio visualized. + * The fft array only contains the first half of the actual + * FFT spectrum (frequencies up to Nyquist frequency), exploiting + * the symmetry of the spectrum. For each frequencies bin i: + *
      + *
    • the element at index 2*i in the array contains + * the real part of a complex number,
    • + *
    • the element at index 2*i+1 contains the imaginary + * part of the complex number.
    • + *
    + * @param samplingRate sampling rate of the visualized audio. */ void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate); } diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java index 4de731a9a8a3f357295c4530d0d98840a3bc74c1..219063564132f23f3e4abe07db39e0c775848bd0 100644 --- a/media/java/android/media/audiopolicy/AudioPolicy.java +++ b/media/java/android/media/audiopolicy/AudioPolicy.java @@ -463,9 +463,9 @@ public class AudioPolicy { * Only ever called if the {@link AudioPolicy} was built with * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}. * @param afi information about the focus request and the requester - * @param requestResult the result that was returned synchronously by the framework to the - * application, {@link #AUDIOFOCUS_REQUEST_FAILED},or - * {@link #AUDIOFOCUS_REQUEST_DELAYED}. + * @param requestResult deprecated after the addition of + * {@link AudioManager#setFocusRequestResult(AudioFocusInfo, int, AudioPolicy)} + * in Android P, always equal to {@link #AUDIOFOCUS_REQUEST_GRANTED}. */ public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {} /** @@ -534,7 +534,7 @@ public class AudioPolicy { sendMsg(MSG_FOCUS_REQUEST, afi, requestResult); if (DEBUG) { Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client=" - + afi.getClientId() + "reqRes=" + requestResult); + + afi.getClientId() + " gen=" + afi.getGen()); } } diff --git a/media/java/android/media/update/MediaBrowser2Provider.java b/media/java/android/media/update/MediaBrowser2Provider.java index 67680c75c2b2cd76b2d057dcfc3132e41798d116..17256a891277c82f4a0cc46bda2f529623f62bd9 100644 --- a/media/java/android/media/update/MediaBrowser2Provider.java +++ b/media/java/android/media/update/MediaBrowser2Provider.java @@ -23,7 +23,7 @@ import android.os.Bundle; * @hide */ public interface MediaBrowser2Provider extends MediaController2Provider { - void getBrowserRoot_impl(Bundle rootHints); + void getLibraryRoot_impl(Bundle rootHints); void subscribe_impl(String parentId, Bundle options); void unsubscribe_impl(String parentId, Bundle options); diff --git a/media/java/android/media/update/MediaControlView2Provider.java b/media/java/android/media/update/MediaControlView2Provider.java index 4464f8f2ac6ee0f28a4478477e06e29e605f5aba..ebde3fefac360bec2e6a37be02812bc3bb7f0eb1 100644 --- a/media/java/android/media/update/MediaControlView2Provider.java +++ b/media/java/android/media/update/MediaControlView2Provider.java @@ -18,6 +18,7 @@ package android.media.update; import android.annotation.SystemApi; import android.media.session.MediaController; +import android.util.AttributeSet; import android.view.View; /** @@ -34,11 +35,10 @@ import android.view.View; * @hide */ // TODO @SystemApi -public interface MediaControlView2Provider extends ViewProvider { +public interface MediaControlView2Provider extends ViewGroupProvider { + void initialize(AttributeSet attrs, int defStyleAttr, int defStyleRes); + void setController_impl(MediaController controller); - void show_impl(); - void show_impl(long timeout); - boolean isShowing_impl(); - void hide_impl(); void setButtonVisibility_impl(int button, int visibility); + void requestPlayButtonFocus_impl(); } diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java index 05790c113804f3def810e5d7bf2d7d4c83538396..71bc64a62abfe14be7125d2737048dbc17428675 100644 --- a/media/java/android/media/update/MediaController2Provider.java +++ b/media/java/android/media/update/MediaController2Provider.java @@ -52,7 +52,7 @@ public interface MediaController2Provider extends TransportControlProvider { void prepareFromSearch_impl(String query, Bundle extras); void prepareMediaId_impl(String mediaId, Bundle extras); void playFromSearch_impl(String query, Bundle extras); - void playFromUri_impl(String uri, Bundle extras); + void playFromUri_impl(Uri uri, Bundle extras); void playFromMediaId_impl(String mediaId, Bundle extras); void setRating_impl(Rating2 rating); diff --git a/media/java/android/media/update/MediaLibraryService2Provider.java b/media/java/android/media/update/MediaLibraryService2Provider.java index a56883910805b552a5d73c376f49d40baaccdbbf..923551a226b651bd45a4137da98679ffd5a052ea 100644 --- a/media/java/android/media/update/MediaLibraryService2Provider.java +++ b/media/java/android/media/update/MediaLibraryService2Provider.java @@ -17,12 +17,15 @@ package android.media.update; import android.annotation.SystemApi; +import android.media.MediaLibraryService2.MediaLibrarySession; +import android.media.MediaLibraryService2.MediaLibrarySessionCallback; import android.media.MediaSession2.ControllerInfo; import android.os.Bundle; /** * @hide */ +// TODO: @SystemApi public interface MediaLibraryService2Provider extends MediaSessionService2Provider { // Nothing new for now @@ -30,4 +33,9 @@ public interface MediaLibraryService2Provider extends MediaSessionService2Provid void notifyChildrenChanged_impl(ControllerInfo controller, String parentId, Bundle options); void notifyChildrenChanged_impl(String parentId, Bundle options); } + + interface LibraryRootProvider { + String getRootId_impl(); + Bundle getExtras_impl(); + } } diff --git a/media/java/android/media/update/MediaMetadata2Provider.java b/media/java/android/media/update/MediaMetadata2Provider.java new file mode 100644 index 0000000000000000000000000000000000000000..55ac43d797d45b09e1b356b484175cbf64051e80 --- /dev/null +++ b/media/java/android/media/update/MediaMetadata2Provider.java @@ -0,0 +1,37 @@ +package android.media.update; + +import android.graphics.Bitmap; +import android.media.MediaMetadata2; +import android.media.MediaMetadata2.Builder; +import android.media.Rating2; +import android.os.Bundle; + +import java.util.Set; + +/** + * @hide + */ +// TODO(jaewan): SystemApi +public interface MediaMetadata2Provider { + boolean containsKey_impl(String key); + CharSequence getText_impl(String key); + String getMediaId_impl(); + String getString_impl(String key); + long getLong_impl(String key); + Rating2 getRating_impl(String key); + Bundle toBundle_impl(); + Set keySet_impl(); + int size_impl(); + Bitmap getBitmap_impl(String key); + Bundle getExtra_impl(); + + interface BuilderProvider { + Builder putText_impl(String key, CharSequence value); + Builder putString_impl(String key, String value); + Builder putLong_impl(String key, long value); + Builder putRating_impl(String key, Rating2 value); + Builder putBitmap_impl(String key, Bitmap value); + Builder setExtra_impl(Bundle bundle); + MediaMetadata2 build_impl(); + } +} diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java index c0c0d80c01b7d65c94bdffbf2e31ec824ec26b3f..41162e0a15ea88d3e3d0498d9ee21c8ff804f611 100644 --- a/media/java/android/media/update/MediaSession2Provider.java +++ b/media/java/android/media/update/MediaSession2Provider.java @@ -16,17 +16,21 @@ package android.media.update; -import android.media.AudioAttributes; +import android.app.PendingIntent; import android.media.MediaItem2; +import android.media.MediaMetadata2; import android.media.MediaPlayerInterface; import android.media.MediaPlayerInterface.PlaybackListener; +import android.media.MediaSession2; import android.media.MediaSession2.Command; import android.media.MediaSession2.CommandButton; +import android.media.MediaSession2.CommandButton.Builder; import android.media.MediaSession2.CommandGroup; import android.media.MediaSession2.ControllerInfo; import android.media.MediaSession2.PlaylistParams; +import android.media.MediaSession2.SessionCallback; import android.media.SessionToken2; -import android.media.VolumeProvider; +import android.media.VolumeProvider2; import android.os.Bundle; import android.os.ResultReceiver; @@ -38,11 +42,9 @@ import java.util.concurrent.Executor; */ // TODO: @SystemApi public interface MediaSession2Provider extends TransportControlProvider { - void initialize(); - void close_impl(); void setPlayer_impl(MediaPlayerInterface player); - void setPlayer_impl(MediaPlayerInterface player, VolumeProvider volumeProvider); + void setPlayer_impl(MediaPlayerInterface player, VolumeProvider2 volumeProvider); MediaPlayerInterface getPlayer_impl(); SessionToken2 getToken_impl(); List getConnectedControllers_impl(); @@ -62,6 +64,42 @@ public interface MediaSession2Provider extends TransportControlProvider { void addPlaybackListener_impl(Executor executor, PlaybackListener listener); void removePlaybackListener_impl(PlaybackListener listener); + interface CommandProvider { + int getCommandCode_impl(); + String getCustomCommand_impl(); + Bundle getExtra_impl(); + Bundle toBundle_impl(); + + boolean equals_impl(Object ob); + int hashCode_impl(); + } + + interface CommandGroupProvider { + void addCommand_impl(Command command); + void addAllPredefinedCommands_impl(); + void removeCommand_impl(Command command); + boolean hasCommand_impl(Command command); + boolean hasCommand_impl(int code); + Bundle toBundle_impl(); + } + + interface CommandButtonProvider { + Command getCommand_impl(); + int getIconResId_impl(); + String getDisplayName_impl(); + Bundle getExtra_impl(); + boolean isEnabled_impl(); + + interface BuilderProvider { + Builder setCommand_impl(Command command); + Builder setIconResId_impl(int resId); + Builder setDisplayName_impl(String displayName); + Builder setEnabled_impl(boolean enabled); + Builder setExtra_impl(Bundle extra); + CommandButton build_impl(); + } + } + interface ControllerInfoProvider { String getPackageName_impl(); int getUid_impl(); @@ -70,13 +108,19 @@ public interface MediaSession2Provider extends TransportControlProvider { boolean equals_impl(ControllerInfoProvider obj); } - interface CommandProvider { - int getCommandCode_impl(); - String getCustomCommand_impl(); - Bundle getExtra_impl(); + interface PlaylistParamsProvider { + int getRepeatMode_impl(); + int getShuffleMode_impl(); + MediaMetadata2 getPlaylistMetadata_impl(); Bundle toBundle_impl(); + } - boolean equals_impl(Object ob); - int hashCode_impl(); + interface BuilderBaseProvider { + void setVolumeProvider_impl(VolumeProvider2 volumeProvider); + void setRatingType_impl(int type); + void setSessionActivity_impl(PendingIntent pi); + void setId_impl(String id); + void setSessionCallback_impl(Executor executor, C callback); + T build_impl(); } } diff --git a/media/java/android/media/update/MediaSessionService2Provider.java b/media/java/android/media/update/MediaSessionService2Provider.java index 9455da7d0bc747df0902b69ee7c8747337e4d8e3..42e75871e12f23770cddf9dbb210995720f0e7b2 100644 --- a/media/java/android/media/update/MediaSessionService2Provider.java +++ b/media/java/android/media/update/MediaSessionService2Provider.java @@ -17,6 +17,7 @@ package android.media.update; import android.annotation.SystemApi; +import android.app.Notification; import android.content.Intent; import android.media.MediaSession2; import android.media.MediaSessionService2.MediaNotification; @@ -33,4 +34,9 @@ public interface MediaSessionService2Provider { // Service void onCreate_impl(); IBinder onBind_impl(Intent intent); + + interface MediaNotificationProvider { + int getNotificationId_impl(); + Notification getNotification_impl(); + } } diff --git a/media/java/android/media/update/PlaybackInfoProvider.java b/media/java/android/media/update/PlaybackInfoProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..36eb58a97df94d72613322f15b3462f37153b54a --- /dev/null +++ b/media/java/android/media/update/PlaybackInfoProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.update; + +import android.media.AudioAttributes; + +/** + * @hide + */ +// TODO(jaewan): @SystemApi +public interface PlaybackInfoProvider { + int getPlaybackType_impl(); + AudioAttributes getAudioAttributes_impl(); + int getControlType_impl(); + int getMaxVolume_impl(); + int getCurrentVolume_impl(); +} diff --git a/media/java/android/media/update/PlaybackState2Provider.java b/media/java/android/media/update/PlaybackState2Provider.java new file mode 100644 index 0000000000000000000000000000000000000000..2875e98bb8a4c9b0e251a0cd990ab97bd01aafc3 --- /dev/null +++ b/media/java/android/media/update/PlaybackState2Provider.java @@ -0,0 +1,43 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.update; + +import android.os.Bundle; + +/** + * @hide + */ +// TODO(jaewan): @SystemApi +public interface PlaybackState2Provider { + String toString_impl(); + + int getState_impl(); + + long getPosition_impl(); + + long getBufferedPosition_impl(); + + float getPlaybackSpeed_impl(); + + CharSequence getErrorMessage_impl(); + + long getLastPositionUpdateTime_impl(); + + long getCurrentPlaylistItemIndex_impl(); + + Bundle toBundle_impl(); +} diff --git a/media/java/android/media/update/ProviderCreator.java b/media/java/android/media/update/ProviderCreator.java new file mode 100644 index 0000000000000000000000000000000000000000..f5f3e470812ff2b82164f6ca61d2f5067a843d47 --- /dev/null +++ b/media/java/android/media/update/ProviderCreator.java @@ -0,0 +1,23 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.update; + +/** @hide */ +@FunctionalInterface +public interface ProviderCreator { + U createProvider(T instance); +} diff --git a/media/java/android/media/update/Rating2Provider.java b/media/java/android/media/update/Rating2Provider.java new file mode 100644 index 0000000000000000000000000000000000000000..8966196890c7c24f5cad1df8489c047e3db8a3c7 --- /dev/null +++ b/media/java/android/media/update/Rating2Provider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.update; + +import android.annotation.SystemApi; +import android.os.Bundle; + +/** + * @hide + */ +// TODO(jaewan): @SystemApi +public interface Rating2Provider { + String toString_impl(); + boolean equals_impl(Object obj); + int hashCode_impl(); + Bundle toBundle_impl(); + boolean isRated_impl(); + int getRatingStyle_impl(); + boolean hasHeart_impl(); + boolean isThumbUp_impl(); + float getStarRating_impl(); + float getPercentRating_impl(); +} \ No newline at end of file diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java index ef8c9a25c9ac21d2c1927e29f81050b1126f46b7..57f04cc88ff579debd53156b2ad19541e7c0a0de 100644 --- a/media/java/android/media/update/StaticProvider.java +++ b/media/java/android/media/update/StaticProvider.java @@ -17,7 +17,7 @@ package android.media.update; import android.annotation.Nullable; -import android.app.PendingIntent; +import android.app.Notification; import android.content.Context; import android.media.DataSourceDesc; import android.media.MediaBrowser2; @@ -26,19 +26,31 @@ import android.media.MediaController2; import android.media.MediaController2.ControllerCallback; import android.media.MediaItem2; import android.media.MediaLibraryService2; +import android.media.MediaLibraryService2.LibraryRoot; import android.media.MediaLibraryService2.MediaLibrarySession; +import android.media.MediaLibraryService2.MediaLibrarySessionBuilder; import android.media.MediaLibraryService2.MediaLibrarySessionCallback; import android.media.MediaMetadata2; import android.media.MediaPlayerInterface; import android.media.MediaSession2; +import android.media.MediaSession2.CommandButton.Builder; +import android.media.MediaSession2.PlaylistParams; import android.media.MediaSession2.SessionCallback; import android.media.MediaSessionService2; +import android.media.MediaSessionService2.MediaNotification; +import android.media.PlaybackState2; +import android.media.Rating2; import android.media.SessionPlayer2; import android.media.SessionToken2; -import android.media.VolumeProvider; -import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider; +import android.media.VolumeProvider2; +import android.media.update.MediaLibraryService2Provider.LibraryRootProvider; +import android.media.update.MediaSession2Provider.BuilderBaseProvider; +import android.media.update.MediaSession2Provider.CommandButtonProvider.BuilderProvider; +import android.media.update.MediaSession2Provider.CommandGroupProvider; import android.media.update.MediaSession2Provider.CommandProvider; import android.media.update.MediaSession2Provider.ControllerInfoProvider; +import android.media.update.MediaSession2Provider.PlaylistParamsProvider; +import android.media.update.MediaSessionService2Provider.MediaNotificationProvider; import android.os.Bundle; import android.os.IInterface; import android.util.AttributeSet; @@ -55,21 +67,29 @@ import java.util.concurrent.Executor; * @hide */ public interface StaticProvider { - MediaControlView2Provider createMediaControlView2( - MediaControlView2 instance, ViewProvider superProvider); - VideoView2Provider createVideoView2( - VideoView2 instance, ViewProvider superProvider, + MediaControlView2Provider createMediaControlView2(MediaControlView2 instance, + ViewGroupProvider superProvider, ViewGroupProvider privateProvider, + @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes); + VideoView2Provider createVideoView2(VideoView2 instance, + ViewGroupProvider superProvider, ViewGroupProvider privateProvider, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes); - MediaSession2Provider createMediaSession2(Context context, MediaSession2 instance, - MediaPlayerInterface player, String id, VolumeProvider volumeProvider, int ratingType, - PendingIntent sessionActivity, Executor executor, SessionCallback callback); - ControllerInfoProvider createMediaSession2ControllerInfoProvider(Context context, - MediaSession2.ControllerInfo instance, int uid, int pid, - String packageName, IInterface callback); CommandProvider createMediaSession2Command(MediaSession2.Command instance, int commandCode, String action, Bundle extra); MediaSession2.Command fromBundle_MediaSession2Command(Context context, Bundle bundle); + CommandGroupProvider createMediaSession2CommandGroup(Context context, + MediaSession2.CommandGroup instance, MediaSession2.CommandGroup others); + MediaSession2.CommandGroup fromBundle_MediaSession2CommandGroup(Context context, Bundle bundle); + ControllerInfoProvider createMediaSession2ControllerInfo(Context context, + MediaSession2.ControllerInfo instance, int uid, int pid, + String packageName, IInterface callback); + PlaylistParamsProvider createMediaSession2PlaylistParams(Context context, + PlaylistParams playlistParams, int repeatMode, int shuffleMode, + MediaMetadata2 playlistMetadata); + PlaylistParams fromBundle_PlaylistParams(Context context, Bundle bundle); + BuilderProvider createMediaSession2CommandButtonBuilder(Context context, Builder builder); + BuilderBaseProvider createMediaSession2Builder( + Context context, MediaSession2.Builder instance, MediaPlayerInterface player); MediaController2Provider createMediaController2(Context context, MediaController2 instance, SessionToken2 token, Executor executor, ControllerCallback callback); @@ -78,12 +98,16 @@ public interface StaticProvider { SessionToken2 token, Executor executor, BrowserCallback callback); MediaSessionService2Provider createMediaSessionService2(MediaSessionService2 instance); - MediaSessionService2Provider createMediaLibraryService2(MediaLibraryService2 instance); + MediaNotificationProvider createMediaSessionService2MediaNotification(Context context, + MediaNotification mediaNotification, int notificationId, Notification notification); - MediaLibrarySessionProvider createMediaLibraryService2MediaLibrarySession(Context context, - MediaLibrarySession instance, MediaPlayerInterface player, String id, - VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity, - Executor executor, MediaLibrarySessionCallback callback); + MediaSessionService2Provider createMediaLibraryService2(MediaLibraryService2 instance); + BuilderBaseProvider + createMediaLibraryService2Builder( + Context context, MediaLibrarySessionBuilder instance, MediaPlayerInterface player, + Executor callbackExecutor, MediaLibrarySessionCallback callback); + LibraryRootProvider createMediaLibraryService2LibraryRoot(Context context, LibraryRoot instance, + String rootId, Bundle extras); SessionToken2Provider createSessionToken2(Context context, SessionToken2 instance, String packageName, String serviceName, int uid); @@ -91,7 +115,28 @@ public interface StaticProvider { SessionPlayer2Provider createSessionPlayer2(Context context, SessionPlayer2 instance); - MediaItem2Provider createMediaItem2Provider(Context context, MediaItem2 mediaItem2, + MediaItem2Provider createMediaItem2(Context context, MediaItem2 mediaItem2, String mediaId, DataSourceDesc dsd, MediaMetadata2 metadata, int flags); MediaItem2 fromBundle_MediaItem2(Context context, Bundle bundle); + + VolumeProvider2Provider createVolumeProvider2(Context context, VolumeProvider2 instance, + int controlType, int maxVolume, int currentVolume); + + MediaMetadata2 fromBundle_MediaMetadata2(Context context, Bundle bundle); + MediaMetadata2Provider.BuilderProvider createMediaMetadata2Builder( + Context context, MediaMetadata2.Builder builder); + MediaMetadata2Provider.BuilderProvider createMediaMetadata2Builder( + Context context, MediaMetadata2.Builder builder, MediaMetadata2 source); + + Rating2 newUnratedRating_Rating2(Context context, int ratingStyle); + Rating2 fromBundle_Rating2(Context context, Bundle bundle); + Rating2 newHeartRating_Rating2(Context context, boolean hasHeart); + Rating2 newThumbRating_Rating2(Context context, boolean thumbIsUp); + Rating2 newStarRating_Rating2(Context context, int starRatingStyle, float starRating); + Rating2 newPercentageRating_Rating2(Context context, float percent); + + PlaybackState2Provider createPlaybackState2(Context context, PlaybackState2 instance, int state, + long position, long updateTime, float speed, long bufferedPosition, long activeItemId, + CharSequence error); + PlaybackState2 fromBundle_PlaybackState2(Context context, Bundle bundle); } diff --git a/media/java/android/media/update/VideoView2Provider.java b/media/java/android/media/update/VideoView2Provider.java index c5b58f7bb61105b40ed1e3c8fdb80ed0845b4dca..7f9ecdd5115c8b51e7b35ed28b3e9e8addc2a1fa 100644 --- a/media/java/android/media/update/VideoView2Provider.java +++ b/media/java/android/media/update/VideoView2Provider.java @@ -16,12 +16,14 @@ package android.media.update; +import android.annotation.SystemApi; import android.media.AudioAttributes; import android.media.MediaPlayerInterface; import android.media.session.MediaController; import android.media.session.PlaybackState; import android.media.session.MediaSession; import android.net.Uri; +import android.util.AttributeSet; import android.widget.MediaControlView2; import android.widget.VideoView2; @@ -43,16 +45,21 @@ import java.util.concurrent.Executor; * @hide */ // TODO @SystemApi -public interface VideoView2Provider extends ViewProvider { - void setMediaControlView2_impl(MediaControlView2 mediaControlView); +public interface VideoView2Provider extends ViewGroupProvider { + void initialize(AttributeSet attrs, int defStyleAttr, int defStyleRes); + + void setMediaControlView2_impl(MediaControlView2 mediaControlView, long intervalMs); MediaController getMediaController_impl(); MediaControlView2 getMediaControlView2_impl(); - void showSubtitle_impl(); - void hideSubtitle_impl(); + void setSubtitleEnabled_impl(boolean enable); + boolean isSubtitleEnabled_impl(); // TODO: remove setSpeed_impl once MediaController2 is ready. void setSpeed_impl(float speed); void setAudioFocusRequest_impl(int focusGain); void setAudioAttributes_impl(AudioAttributes attributes); + /** + * @hide + */ void setRouteAttributes_impl(List routeCategories, MediaPlayerInterface player); // TODO: remove setRouteAttributes_impl with MediaSession.Callback once MediaSession2 is ready. void setRouteAttributes_impl(List routeCategories, MediaSession.Callback sessionPlayer); diff --git a/media/java/android/media/update/ViewGroupHelper.java b/media/java/android/media/update/ViewGroupHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..6b4f15d0fdb71e8487a5d6104dbe1eb150ccf61c --- /dev/null +++ b/media/java/android/media/update/ViewGroupHelper.java @@ -0,0 +1,369 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.update; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +/** + * Helper class for connecting the public API to an updatable implementation. + * + * @see ViewGroupProvider + * + * @hide + */ +public abstract class ViewGroupHelper extends ViewGroup { + /** @hide */ + final public T mProvider; + + /** @hide */ + public ViewGroupHelper(ProviderCreator creator, + Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + mProvider = creator.createProvider(this, new SuperProvider(), + new PrivateProvider()); + } + + /** @hide */ + // TODO @SystemApi + public T getProvider() { + return mProvider; + } + + @Override + protected void onAttachedToWindow() { + mProvider.onAttachedToWindow_impl(); + } + + @Override + protected void onDetachedFromWindow() { + mProvider.onDetachedFromWindow_impl(); + } + + @Override + public CharSequence getAccessibilityClassName() { + return mProvider.getAccessibilityClassName_impl(); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return mProvider.onTouchEvent_impl(ev); + } + + @Override + public boolean onTrackballEvent(MotionEvent ev) { + return mProvider.onTrackballEvent_impl(ev); + } + + @Override + public void onFinishInflate() { + mProvider.onFinishInflate_impl(); + } + + @Override + public void setEnabled(boolean enabled) { + mProvider.setEnabled_impl(enabled); + } + + @Override + public void onVisibilityAggregated(boolean isVisible) { + mProvider.onVisibilityAggregated_impl(isVisible); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + mProvider.onLayout_impl(changed, left, top, right, bottom); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + mProvider.onMeasure_impl(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected int getSuggestedMinimumWidth() { + return mProvider.getSuggestedMinimumWidth_impl(); + } + + @Override + protected int getSuggestedMinimumHeight() { + return mProvider.getSuggestedMinimumHeight_impl(); + } + + // setMeasuredDimension is final + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return mProvider.dispatchTouchEvent_impl(ev); + } + + @Override + protected boolean checkLayoutParams(LayoutParams p) { + return mProvider.checkLayoutParams_impl(p); + } + + @Override + protected LayoutParams generateDefaultLayoutParams() { + return mProvider.generateDefaultLayoutParams_impl(); + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return mProvider.generateLayoutParams_impl(attrs); + } + + @Override + protected LayoutParams generateLayoutParams(LayoutParams lp) { + return mProvider.generateLayoutParams_impl(lp); + } + + @Override + public boolean shouldDelayChildPressedState() { + return mProvider.shouldDelayChildPressedState_impl(); + } + + @Override + protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, + int parentHeightMeasureSpec, int heightUsed) { + mProvider.measureChildWithMargins_impl(child, + parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); + } + + /** @hide */ + public class SuperProvider implements ViewGroupProvider { + @Override + public CharSequence getAccessibilityClassName_impl() { + return ViewGroupHelper.super.getAccessibilityClassName(); + } + + @Override + public boolean onTouchEvent_impl(MotionEvent ev) { + return ViewGroupHelper.super.onTouchEvent(ev); + } + + @Override + public boolean onTrackballEvent_impl(MotionEvent ev) { + return ViewGroupHelper.super.onTrackballEvent(ev); + } + + @Override + public void onFinishInflate_impl() { + ViewGroupHelper.super.onFinishInflate(); + } + + @Override + public void setEnabled_impl(boolean enabled) { + ViewGroupHelper.super.setEnabled(enabled); + } + + @Override + public void onAttachedToWindow_impl() { + ViewGroupHelper.super.onAttachedToWindow(); + } + + @Override + public void onDetachedFromWindow_impl() { + ViewGroupHelper.super.onDetachedFromWindow(); + } + + @Override + public void onVisibilityAggregated_impl(boolean isVisible) { + ViewGroupHelper.super.onVisibilityAggregated(isVisible); + } + + @Override + public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) { + // abstract method; no super + } + + @Override + public void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec) { + ViewGroupHelper.super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public int getSuggestedMinimumWidth_impl() { + return ViewGroupHelper.super.getSuggestedMinimumWidth(); + } + + @Override + public int getSuggestedMinimumHeight_impl() { + return ViewGroupHelper.super.getSuggestedMinimumHeight(); + } + + @Override + public void setMeasuredDimension_impl(int measuredWidth, int measuredHeight) { + ViewGroupHelper.super.setMeasuredDimension(measuredWidth, measuredHeight); + } + + @Override + public boolean dispatchTouchEvent_impl(MotionEvent ev) { + return ViewGroupHelper.super.dispatchTouchEvent(ev); + } + + @Override + public boolean checkLayoutParams_impl(LayoutParams p) { + return ViewGroupHelper.super.checkLayoutParams(p); + } + + @Override + public LayoutParams generateDefaultLayoutParams_impl() { + return ViewGroupHelper.super.generateDefaultLayoutParams(); + } + + @Override + public LayoutParams generateLayoutParams_impl(AttributeSet attrs) { + return ViewGroupHelper.super.generateLayoutParams(attrs); + } + + @Override + public LayoutParams generateLayoutParams_impl(LayoutParams lp) { + return ViewGroupHelper.super.generateLayoutParams(lp); + } + + @Override + public boolean shouldDelayChildPressedState_impl() { + return ViewGroupHelper.super.shouldDelayChildPressedState(); + } + + @Override + public void measureChildWithMargins_impl(View child, + int parentWidthMeasureSpec, int widthUsed, + int parentHeightMeasureSpec, int heightUsed) { + ViewGroupHelper.super.measureChildWithMargins(child, + parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); + } + } + + /** @hide */ + public class PrivateProvider implements ViewGroupProvider { + @Override + public CharSequence getAccessibilityClassName_impl() { + return ViewGroupHelper.this.getAccessibilityClassName(); + } + + @Override + public boolean onTouchEvent_impl(MotionEvent ev) { + return ViewGroupHelper.this.onTouchEvent(ev); + } + + @Override + public boolean onTrackballEvent_impl(MotionEvent ev) { + return ViewGroupHelper.this.onTrackballEvent(ev); + } + + @Override + public void onFinishInflate_impl() { + ViewGroupHelper.this.onFinishInflate(); + } + + @Override + public void setEnabled_impl(boolean enabled) { + ViewGroupHelper.this.setEnabled(enabled); + } + + @Override + public void onAttachedToWindow_impl() { + ViewGroupHelper.this.onAttachedToWindow(); + } + + @Override + public void onDetachedFromWindow_impl() { + ViewGroupHelper.this.onDetachedFromWindow(); + } + + @Override + public void onVisibilityAggregated_impl(boolean isVisible) { + ViewGroupHelper.this.onVisibilityAggregated(isVisible); + } + + @Override + public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) { + ViewGroupHelper.this.onLayout(changed, left, top, right, bottom); + } + + @Override + public void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec) { + ViewGroupHelper.this.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public int getSuggestedMinimumWidth_impl() { + return ViewGroupHelper.this.getSuggestedMinimumWidth(); + } + + @Override + public int getSuggestedMinimumHeight_impl() { + return ViewGroupHelper.this.getSuggestedMinimumHeight(); + } + + @Override + public void setMeasuredDimension_impl(int measuredWidth, int measuredHeight) { + ViewGroupHelper.this.setMeasuredDimension(measuredWidth, measuredHeight); + } + + @Override + public boolean dispatchTouchEvent_impl(MotionEvent ev) { + return ViewGroupHelper.this.dispatchTouchEvent(ev); + } + + @Override + public boolean checkLayoutParams_impl(LayoutParams p) { + return ViewGroupHelper.this.checkLayoutParams(p); + } + + @Override + public LayoutParams generateDefaultLayoutParams_impl() { + return ViewGroupHelper.this.generateDefaultLayoutParams(); + } + + @Override + public LayoutParams generateLayoutParams_impl(AttributeSet attrs) { + return ViewGroupHelper.this.generateLayoutParams(attrs); + } + + @Override + public LayoutParams generateLayoutParams_impl(LayoutParams lp) { + return ViewGroupHelper.this.generateLayoutParams(lp); + } + + @Override + public boolean shouldDelayChildPressedState_impl() { + return ViewGroupHelper.this.shouldDelayChildPressedState(); + } + + @Override + public void measureChildWithMargins_impl(View child, + int parentWidthMeasureSpec, int widthUsed, + int parentHeightMeasureSpec, int heightUsed) { + ViewGroupHelper.this.measureChildWithMargins(child, + parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); + } + } + + /** @hide */ + @FunctionalInterface + public interface ProviderCreator { + T createProvider(ViewGroupHelper instance, ViewGroupProvider superProvider, + ViewGroupProvider privateProvider); + } +} diff --git a/media/java/android/media/update/ViewProvider.java b/media/java/android/media/update/ViewGroupProvider.java similarity index 54% rename from media/java/android/media/update/ViewProvider.java rename to media/java/android/media/update/ViewGroupProvider.java index 0dd8f388a8fe6c1e054eaa770d6e51ee0389d71b..67e8cea871e9a2cf8b8575b0618a242bd0d4e53e 100644 --- a/media/java/android/media/update/ViewProvider.java +++ b/media/java/android/media/update/ViewGroupProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,10 @@ package android.media.update; import android.annotation.SystemApi; +import android.util.AttributeSet; import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; /** * Interface for connecting the public API to an updatable implementation. @@ -33,8 +36,8 @@ import android.view.MotionEvent; * @hide */ // TODO @SystemApi -public interface ViewProvider { - // TODO Add more (all?) methods from View +public interface ViewGroupProvider { + // View methods void onAttachedToWindow_impl(); void onDetachedFromWindow_impl(); CharSequence getAccessibilityClassName_impl(); @@ -42,4 +45,23 @@ public interface ViewProvider { boolean onTrackballEvent_impl(MotionEvent ev); void onFinishInflate_impl(); void setEnabled_impl(boolean enabled); + void onVisibilityAggregated_impl(boolean isVisible); + void onLayout_impl(boolean changed, int left, int top, int right, int bottom); + void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec); + int getSuggestedMinimumWidth_impl(); + int getSuggestedMinimumHeight_impl(); + void setMeasuredDimension_impl(int measuredWidth, int measuredHeight); + boolean dispatchTouchEvent_impl(MotionEvent ev); + + // ViewGroup methods + boolean checkLayoutParams_impl(LayoutParams p); + LayoutParams generateDefaultLayoutParams_impl(); + LayoutParams generateLayoutParams_impl(AttributeSet attrs); + LayoutParams generateLayoutParams_impl(LayoutParams lp); + boolean shouldDelayChildPressedState_impl(); + void measureChildWithMargins_impl(View child, int parentWidthMeasureSpec, int widthUsed, + int parentHeightMeasureSpec, int heightUsed); + + // ViewManager methods + // ViewParent methods } diff --git a/media/java/android/media/update/VolumeProvider2Provider.java b/media/java/android/media/update/VolumeProvider2Provider.java new file mode 100644 index 0000000000000000000000000000000000000000..5657af60eb6bdd33a81b24644119c0ec61940c34 --- /dev/null +++ b/media/java/android/media/update/VolumeProvider2Provider.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.media.update; + +/** + * @hide + */ +// TODO(jaewan): @SystemApi +public interface VolumeProvider2Provider { + int getControlType_impl(); + int getMaxVolume_impl(); + int getCurrentVolume_impl(); + void setCurrentVolume_impl(int currentVolume); +} diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 9742443666f0f3a9c8ef4f90be4fa26be0a34ce2..1dde16cc935a69416d7dc107dee5712496adc0d5 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -34,6 +34,7 @@ cc_library_shared { "libutils", "libbinder", "libmedia", + "libmediaextractor", "libmedia_omx", "libmediametrics", "libmediadrm", diff --git a/media/jni/android_media_AudioPresentation.h b/media/jni/android_media_AudioPresentation.h new file mode 100644 index 0000000000000000000000000000000000000000..71b8dacfbdfa287f26ee3eee954ec491ac0b0b42 --- /dev/null +++ b/media/jni/android_media_AudioPresentation.h @@ -0,0 +1,173 @@ +/* + * Copyright 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_MEDIA_AUDIO_PRESENTATION_H_ +#define _ANDROID_MEDIA_AUDIO_PRESENTATION_H_ + +#include "jni.h" + +#include +#include +#include + +#include + +namespace android { + +struct JAudioPresentationInfo { + struct fields_t { + jclass clazz; + jmethodID constructID; + + // list parameters + jclass listclazz; + jmethodID listConstructId; + jmethodID listAddId; + + void init(JNIEnv *env) { + jclass lclazz = env->FindClass("android/media/AudioPresentation"); + if (lclazz == NULL) { + return; + } + + clazz = (jclass)env->NewGlobalRef(lclazz); + if (clazz == NULL) { + return; + } + + constructID = env->GetMethodID(clazz, "", + "(IILjava/util/Map;Ljava/lang/String;IZZZ)V"); + env->DeleteLocalRef(lclazz); + + // list objects + jclass llistclazz = env->FindClass("java/util/ArrayList"); + CHECK(llistclazz != NULL); + listclazz = static_cast(env->NewGlobalRef(llistclazz)); + CHECK(listclazz != NULL); + listConstructId = env->GetMethodID(listclazz, "", "()V"); + CHECK(listConstructId != NULL); + listAddId = env->GetMethodID(listclazz, "add", "(Ljava/lang/Object;)Z"); + CHECK(listAddId != NULL); + env->DeleteLocalRef(llistclazz); + } + + void exit(JNIEnv *env) { + env->DeleteGlobalRef(clazz); + clazz = NULL; + env->DeleteGlobalRef(listclazz); + listclazz = NULL; + } + }; + + static status_t ConvertMessageToMap(JNIEnv *env, const sp &msg, jobject *map) { + ScopedLocalRef hashMapClazz(env, env->FindClass("java/util/HashMap")); + + if (hashMapClazz.get() == NULL) { + return -EINVAL; + } + jmethodID hashMapConstructID = + env->GetMethodID(hashMapClazz.get(), "", "()V"); + + if (hashMapConstructID == NULL) { + return -EINVAL; + } + jmethodID hashMapPutID = + env->GetMethodID( + hashMapClazz.get(), + "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + if (hashMapPutID == NULL) { + return -EINVAL; + } + + jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID); + + for (size_t i = 0; i < msg->countEntries(); ++i) { + AMessage::Type valueType; + const char *key = msg->getEntryNameAt(i, &valueType); + + if (!strncmp(key, "android._", 9)) { + // don't expose private keys (starting with android._) + continue; + } + + jobject valueObj = NULL; + + AString val; + CHECK(msg->findString(key, &val)); + + valueObj = env->NewStringUTF(val.c_str()); + + if (valueObj != NULL) { + jstring keyObj = env->NewStringUTF(key); + + env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj); + + env->DeleteLocalRef(keyObj); keyObj = NULL; + env->DeleteLocalRef(valueObj); valueObj = NULL; + } + } + + *map = hashMap; + + return OK; + } + + jobject asJobject(JNIEnv *env, const fields_t& fields, const AudioPresentationInfo &info) { + jobject list = env->NewObject(fields.listclazz, fields.listConstructId); + + for (size_t i = 0; i < info.countPresentations(); ++i) { + const sp &ap = info.getPresentation(i); + jobject jLabelObject; + + sp labelMessage = new AMessage(); + for (size_t i = 0; i < ap->mLabels.size(); ++i) { + labelMessage->setString(ap->mLabels.keyAt(i).string(), + ap->mLabels.valueAt(i).string()); + } + if (ConvertMessageToMap(env, labelMessage, &jLabelObject) != OK) { + return NULL; + } + jstring jLanguage = env->NewStringUTF(ap->mLanguage.string()); + + jobject jValueObj = env->NewObject(fields.clazz, fields.constructID, + static_cast(ap->mPresentationId), + static_cast(ap->mProgramId), + jLabelObject, + jLanguage, + static_cast(ap->mMasteringIndication), + static_cast((ap->mAudioDescriptionAvailable == 1) ? + 1 : 0), + static_cast((ap->mSpokenSubtitlesAvailable == 1) ? + 1 : 0), + static_cast((ap->mDialogueEnhancementAvailable == 1) ? + 1 : 0)); + if (jValueObj == NULL) { + env->DeleteLocalRef(jLanguage); jLanguage = NULL; + return NULL; + } + + env->CallBooleanMethod(list, fields.listAddId, jValueObj); + env->DeleteLocalRef(jValueObj); jValueObj = NULL; + env->DeleteLocalRef(jLanguage); jLanguage = NULL; + } + return list; + } +}; +} // namespace android + +#endif // _ANDROID_MEDIA_AUDIO_PRESENTATION_H_ diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp index 90ee8a6814d54503bde9b324b2b16d35a57c8729..27eaed05b04d984f62957d79cf20937851609f12 100644 --- a/media/jni/android_media_MediaPlayer2.cpp +++ b/media/jni/android_media_MediaPlayer2.cpp @@ -19,12 +19,16 @@ #define LOG_TAG "MediaPlayer2-JNI" #include "utils/Log.h" +#include + #include #include +#include #include #include #include #include +#include #include // for FOURCC definition #include #include @@ -234,7 +238,8 @@ static sp setMediaPlayer(JNIEnv* env, jobject thiz, const sp mp = getMediaPlayer(env, thiz); - if (mp == NULL ) { + if (mp == NULL) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } @@ -282,16 +287,25 @@ android_media_MediaPlayer2_setDataSourceAndHeaders( if (tmp == NULL) { // Out of memory return; } - ALOGV("setDataSource: path %s", tmp); + ALOGV("setDataSourceAndHeaders: path %s", tmp); + + if (strncmp(tmp, "content://", 10) == 0) { + ALOGE("setDataSourceAndHeaders: content scheme is not supported in native code"); + jniThrowException(env, "java/io/IOException", + "content scheme is not supported in native code"); + return; + } + + sp dsd = new DataSourceDesc(); + dsd->mType = DataSourceDesc::TYPE_URL; + dsd->mUrl = tmp; - String8 pathStr(tmp); env->ReleaseStringUTFChars(path, tmp); tmp = NULL; // We build a KeyedVector out of the key and val arrays - KeyedVector headersVector; if (!ConvertKeyValueArraysToKeyedVector( - env, keys, values, &headersVector)) { + env, keys, values, &dsd->mHeaders)) { return; } @@ -299,20 +313,16 @@ android_media_MediaPlayer2_setDataSourceAndHeaders( if (httpServiceObj != NULL) { httpService = new JMedia2HTTPService(env, httpServiceObj); } - - status_t opStatus = - mp->setDataSource( - httpService, - pathStr, - headersVector.size() > 0? &headersVector : NULL); + dsd->mHttpService = httpService; process_media_player_call( - env, thiz, opStatus, "java/io/IOException", - "setDataSource failed." ); + env, thiz, mp->setDataSource(dsd), "java/io/IOException", + "setDataSourceAndHeaders failed." ); } static void -android_media_MediaPlayer2_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) +android_media_MediaPlayer2_setDataSourceFD( + JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) { sp mp = getMediaPlayer(env, thiz); if (mp == NULL ) { @@ -325,12 +335,46 @@ android_media_MediaPlayer2_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fi return; } int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); - ALOGV("setDataSourceFD: fd %d", fd); - process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); + ALOGV("setDataSourceFD: fd=%d (%s), offset=%lld, length=%lld", + fd, nameForFd(fd).c_str(), (long long)offset, (long long)length); + + struct stat sb; + int ret = fstat(fd, &sb); + if (ret != 0) { + ALOGE("setDataSourceFD: fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); + jniThrowException(env, "java/io/IOException", "setDataSourceFD failed fstat"); + return; + } + + ALOGV("st_dev = %llu", static_cast(sb.st_dev)); + ALOGV("st_mode = %u", sb.st_mode); + ALOGV("st_uid = %lu", static_cast(sb.st_uid)); + ALOGV("st_gid = %lu", static_cast(sb.st_gid)); + ALOGV("st_size = %llu", static_cast(sb.st_size)); + + if (offset >= sb.st_size) { + ALOGE("setDataSourceFD: offset is out of range"); + jniThrowException(env, "java/lang/IllegalArgumentException", + "setDataSourceFD failed, offset is out of range."); + return; + } + if (offset + length > sb.st_size) { + length = sb.st_size - offset; + ALOGV("setDataSourceFD: adjusted length = %lld", (long long)length); + } + + sp dsd = new DataSourceDesc(); + dsd->mType = DataSourceDesc::TYPE_FD; + dsd->mFD = fd; + dsd->mFDOffset = offset; + dsd->mFDLength = length; + process_media_player_call(env, thiz, mp->setDataSource(dsd), + "java/io/IOException", "setDataSourceFD failed." ); } static void -android_media_MediaPlayer2_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource) +android_media_MediaPlayer2_setDataSourceCallback( + JNIEnv *env, jobject thiz, jobject dataSource) { sp mp = getMediaPlayer(env, thiz); if (mp == NULL ) { @@ -343,7 +387,11 @@ android_media_MediaPlayer2_setDataSourceCallback(JNIEnv *env, jobject thiz, jobj return; } sp callbackDataSource = new JMedia2DataSource(env, dataSource); - process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." ); + sp dsd = new DataSourceDesc(); + dsd->mType = DataSourceDesc::TYPE_CALLBACK; + dsd->mCallbackSource = callbackDataSource; + process_media_player_call(env, thiz, mp->setDataSource(dsd), + "java/lang/RuntimeException", "setDataSourceCallback failed." ); } static sp @@ -1099,45 +1147,6 @@ static void android_media_MediaPlayer2_attachAuxEffect(JNIEnv *env, jobject thi process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL ); } -static jint -android_media_MediaPlayer2_setRetransmitEndpoint(JNIEnv *env, jobject thiz, - jstring addrString, jint port) { - sp mp = getMediaPlayer(env, thiz); - if (mp == NULL ) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); - return INVALID_OPERATION; - } - - const char *cAddrString = NULL; - - if (NULL != addrString) { - cAddrString = env->GetStringUTFChars(addrString, NULL); - if (cAddrString == NULL) { // Out of memory - return NO_MEMORY; - } - } - ALOGV("setRetransmitEndpoint: %s:%d", - cAddrString ? cAddrString : "(null)", port); - - status_t ret; - if (cAddrString && (port > 0xFFFF)) { - ret = BAD_VALUE; - } else { - ret = mp->setRetransmitEndpoint(cAddrString, - static_cast(port)); - } - - if (NULL != addrString) { - env->ReleaseStringUTFChars(addrString, cAddrString); - } - - if (ret == INVALID_OPERATION ) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); - } - - return (jint) ret; -} - static void android_media_MediaPlayer2_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player) { @@ -1418,7 +1427,6 @@ static const JNINativeMethod gMethods[] = { {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_set_audio_session_id}, {"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer2_setAuxEffectSendLevel}, {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer2_attachAuxEffect}, - {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer2_setRetransmitEndpoint}, {"setNextMediaPlayer", "(Landroid/media/MediaPlayer2;)V", (void *)android_media_MediaPlayer2_setNextMediaPlayer}, // Modular DRM { "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer2_prepareDrm }, diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index d2bc1743654fa3fc88ab94dd7b3572e3c91a1d3c..b3a8b21147c1f7553066a5dbef1386e12d94faf9 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -20,6 +20,7 @@ #include #include #include +#include //#define LOG_NDEBUG 0 #define LOG_TAG "MediaRecorderJNI" @@ -29,6 +30,7 @@ #include #include #include +#include #include #include @@ -36,7 +38,9 @@ #include "jni.h" #include +#include "android_media_AudioErrors.h" #include "android_media_MediaMetricsJNI.h" +#include "android_media_MicrophoneInfo.h" #include "android_runtime/AndroidRuntime.h" #include @@ -61,6 +65,12 @@ struct fields_t { }; static fields_t fields; +struct ArrayListFields { + jmethodID add; + jclass classId; +}; +static ArrayListFields gArrayListFields; + static Mutex sLock; // ---------------------------------------------------------------------------- @@ -565,6 +575,13 @@ android_media_MediaRecorder_native_init(JNIEnv *env) if (fields.post_event == NULL) { return; } + + clazz = env->FindClass("java/util/ArrayList"); + if (clazz == NULL) { + return; + } + gArrayListFields.add = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"); + gArrayListFields.classId = static_cast(env->NewGlobalRef(clazz)); } @@ -707,6 +724,45 @@ android_media_MediaRecorder_enableDeviceCallback(JNIEnv *env, jobject thiz, jboo process_media_recorder_call(env, mr->enableAudioDeviceCallback(enabled), "java/lang/RuntimeException", "enableDeviceCallback failed."); } + +static jint +android_media_MediaRecord_getActiveMicrophones(JNIEnv *env, + jobject thiz, jobject jActiveMicrophones) { + if (jActiveMicrophones == NULL) { + ALOGE("jActiveMicrophones is null"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + if (!env->IsInstanceOf(jActiveMicrophones, gArrayListFields.classId)) { + ALOGE("getActiveMicrophones not an arraylist"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + + sp mr = getMediaRecorder(env, thiz); + if (mr == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", NULL); + return (jint)AUDIO_JAVA_NO_INIT; + } + + jint jStatus = AUDIO_JAVA_SUCCESS; + std::vector activeMicrophones; + status_t status = mr->getActiveMicrophones(&activeMicrophones); + if (status != NO_ERROR) { + ALOGE_IF(status != NO_ERROR, "MediaRecorder::getActiveMicrophones error %d", status); + jStatus = nativeToJavaStatus(status); + return jStatus; + } + + for (size_t i = 0; i < activeMicrophones.size(); i++) { + jobject jMicrophoneInfo; + jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &activeMicrophones[i]); + if (jStatus != AUDIO_JAVA_SUCCESS) { + return jStatus; + } + env->CallBooleanMethod(jActiveMicrophones, gArrayListFields.add, jMicrophoneInfo); + env->DeleteLocalRef(jMicrophoneInfo); + } + return jStatus; +} // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -742,7 +798,9 @@ static const JNINativeMethod gMethods[] = { {"native_setInputDevice", "(I)Z", (void *)android_media_MediaRecorder_setInputDevice}, {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaRecorder_getRoutedDeviceId}, - {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaRecorder_enableDeviceCallback}, + {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaRecorder_enableDeviceCallback}, + + {"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones}, }; // This function only registers the native methods, and is called from diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java index 5680d9f9e4c31e75f5e83dd1595c9b13f2965434..b3f443b30a70a8bb17b10b1fb39c00261c9dd25e 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java @@ -1860,9 +1860,6 @@ public class StaticMetadata { return new ArrayList(); } - checkArrayValuesInRange(key, availableCaps, - CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, - CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO); capList = Arrays.asList(CameraTestUtils.toObject(availableCaps)); return capList; } diff --git a/native/android/Android.bp b/native/android/Android.bp index 00fe6382fc17300db80faa33eba6c7f7cfb7f3d5..4fb5e748aaacae506dbefbea87b25788ad817027 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -48,6 +48,7 @@ cc_library_shared { "sensor.cpp", "sharedmem.cpp", "storage_manager.cpp", + "surface_texture.cpp", "trace.cpp", ], diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index 3d5ee39e37d3800f748ca08cd994cfc237d862e1..d6dcd723e72160e74711960ffc068f5a9c271402 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -205,6 +205,14 @@ LIBANDROID { AStorageManager_mountObb; AStorageManager_new; AStorageManager_unmountObb; + ASurfaceTexture_acquireANativeWindow; # introduced=28 + ASurfaceTexture_attachToGLContext; # introduced=28 + ASurfaceTexture_detachFromGLContext; # introduced=28 + ASurfaceTexture_fromSurfaceTexture; # introduced=28 + ASurfaceTexture_getTimestamp; # introduced=28 + ASurfaceTexture_getTransformMatrix; # introduced=28 + ASurfaceTexture_release; # introduced=28 + ASurfaceTexture_updateTexImage; # introduced=28 ATrace_beginSection; # introduced=23 ATrace_endSection; # introduced=23 ATrace_isEnabled; # introduced=23 diff --git a/native/android/surface_texture.cpp b/native/android/surface_texture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b26688190ccdebb6590cb4e224a341df9206b5fc --- /dev/null +++ b/native/android/surface_texture.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define LOG_TAG "ASurfaceTexture" + +#include + +#include +#include + +#include + +using namespace android; + +struct ASurfaceTexture { + sp consumer; + sp producer; +}; + +ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) { + if (!surfacetexture || !android_SurfaceTexture_isInstanceOf(env, surfacetexture)) { + return nullptr; + } + ASurfaceTexture* ast = new ASurfaceTexture; + ast->consumer = SurfaceTexture_getSurfaceTexture(env, surfacetexture); + ast->producer = SurfaceTexture_getProducer(env, surfacetexture); + return ast; +} + +ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) { + sp surface = new Surface(st->producer); + ANativeWindow* win(surface.get()); + ANativeWindow_acquire(win); + return win; +} + +void ASurfaceTexture_release(ASurfaceTexture* st) { + delete st; +} + +int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t tex) { + return st->consumer->attachToContext(tex); +} + +int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) { + return st->consumer->detachFromContext(); +} + +int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) { + return st->consumer->updateTexImage(); +} + +void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) { + st->consumer->getTransformMatrix(mtx); +} + +int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) { + return st->consumer->getTimestamp(); +} diff --git a/packages/CaptivePortalLogin/OWNERS b/packages/CaptivePortalLogin/OWNERS index 6f77e04da3c0580c3fff9361596eb734e49b0436..ce50558bf4f6d6840fc672bdb89db8fad314213a 100644 --- a/packages/CaptivePortalLogin/OWNERS +++ b/packages/CaptivePortalLogin/OWNERS @@ -1,7 +1,6 @@ set noparent ek@google.com -hugobenichi@google.com jchalard@google.com lorenzo@google.com satk@google.com diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml index ad2fc24891f10b0604a3e87dc94c355c467889d2..bc1ff339fb1ae1275d647e9759b549f2de1feaba 100644 --- a/packages/CarrierDefaultApp/res/values-bs/strings.xml +++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml @@ -7,7 +7,7 @@ "Prijenos podataka na mobilnoj mreži je deaktiviran" "Dodirnite da posjetite %s web lokaciju" "Obratite se pružaocu usluga %s" - "Nema mobilnog prijenosa podataka" + "Nema veze za prijenos podataka na mobilnoj mreži" "Dodajte plan prijenosa podataka ili rominga putem operatera %s" "Status prijenosa podataka na mobilnoj mreži" "Prijava na mobilnu mrežu" diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 8b01aef81c6779dd976fd9458b78cbd4704f9acf..9f165bc97768fd8669c1bb41a126352e3f776f66 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -30,6 +30,7 @@ import android.content.res.ObbInfo; import android.content.res.ObbScanner; import android.os.Binder; import android.os.Environment.UserEnvironment; +import android.os.FileUtils; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; @@ -43,7 +44,6 @@ import com.android.internal.os.IParcelFileDescriptorFactory; import com.android.internal.util.ArrayUtils; import libcore.io.IoUtils; -import libcore.io.Streams; import java.io.File; import java.io.FileInputStream; @@ -260,7 +260,7 @@ public class DefaultContainerService extends IntentService { in = new FileInputStream(sourcePath); out = new ParcelFileDescriptor.AutoCloseOutputStream( target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE)); - Streams.copy(in, out); + FileUtils.copy(in, out); } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java index 6fe8975577a47f38779b33a3ecaafbf1e9fe229e..9a66b07fb74f1edfbc7382a18ebb153e5bf06976 100644 --- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java +++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java @@ -94,7 +94,7 @@ public class Assistant extends NotificationAssistantService { infile = mFile.openRead(); readXml(infile); } catch (FileNotFoundException e) { - // No data yet + Log.d(TAG, "File doesn't exist or isn't readable yet"); } catch (IOException e) { Log.e(TAG, "Unable to read channel impressions", e); } catch (NumberFormatException | XmlPullParserException e) { diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java index 7c35b48310f2de7dde943690f1b7a97b18656bba..db48f610471da4675e48095616af87e30f03afff 100644 --- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java +++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java @@ -325,7 +325,8 @@ public class AssistantTest extends ServiceTestCase { int dismiss2 = 777; String key2 = mAssistant.getKey("pkg2", 2, "channel2"); - String xml = "\n" + String xml = "" + + "\n" + "\n" @@ -377,7 +378,6 @@ public class AssistantTest extends ServiceTestCase { mAssistant.insertImpressions(key2, ci2); mAssistant.insertImpressions(key3, ci3); - XmlSerializer serializer = new FastXmlSerializer(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java index f6a259dbf9827e736b7edb56531ffc497a00c882..53e8813c736387ac6a892de583106d537c01c81c 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java @@ -16,8 +16,8 @@ package com.android.printspooler.model; -import static com.android.internal.print.DumpUtils.writeComponentName; import static com.android.internal.print.DumpUtils.writePrintJobInfo; +import static com.android.internal.util.dump.DumpUtils.writeComponentName; import android.annotation.FloatRange; import android.annotation.NonNull; @@ -59,10 +59,10 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.HandlerCaller; -import com.android.internal.print.DualDumpOutputStream; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; +import com.android.internal.util.dump.DualDumpOutputStream; import com.android.printspooler.R; import com.android.printspooler.util.ApprovedPrintServices; @@ -214,12 +214,11 @@ public final class PrintSpoolerService extends Service { try { synchronized (mLock) { if (dumpAsProto) { - dumpLocked(new DualDumpOutputStream(new ProtoOutputStream(fd), null)); + dumpLocked(new DualDumpOutputStream(new ProtoOutputStream(fd))); } else { try (FileOutputStream out = new FileOutputStream(fd)) { try (PrintWriter w = new PrintWriter(out)) { - dumpLocked(new DualDumpOutputStream(null, new IndentingPrintWriter(w, - " "))); + dumpLocked(new DualDumpOutputStream(new IndentingPrintWriter(w, " "))); } } catch (IOException ignored) { } diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk index 69287e8585326b7974184410c0b8b23e60311137..4338d26d502bf6d3f1576d522cef89c5feba1fac 100644 --- a/packages/SettingsLib/Android.mk +++ b/packages/SettingsLib/Android.mk @@ -14,10 +14,10 @@ LOCAL_SHARED_ANDROID_LIBRARIES := \ android-support-v7-preference \ android-support-v7-appcompat \ android-support-v14-preference \ - apptoolkit-lifecycle-runtime + android-arch-lifecycle-runtime LOCAL_SHARED_JAVA_LIBRARIES := \ - apptoolkit-lifecycle-common + android-arch-lifecycle-common LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk index 14f06254009e862565964413db2b6726babbf7ab..3c2ca2d3188871099ebdf674fd134d3046c8af1a 100644 --- a/packages/SettingsLib/common.mk +++ b/packages/SettingsLib/common.mk @@ -64,7 +64,7 @@ LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.android.settingslib LOCAL_STATIC_JAVA_LIBRARIES += \ android-support-annotations \ android-support-v4 \ - apptoolkit-lifecycle-runtime \ - apptoolkit-lifecycle-common \ + android-arch-lifecycle-runtime \ + android-arch-lifecycle-common \ SettingsLib endif diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml index 771abe666dc992260254c871af8423dcc7b84577..f995d585d900fa54bc67f691e547d4d5c46f0cdf 100644 --- a/packages/SettingsLib/res/values-af/arrays.xml +++ b/packages/SettingsLib/res/values-af/arrays.xml @@ -234,10 +234,6 @@ "Wys oortrekareas" "Wys areas vir Deuteranomaly" - - "OpenGL (verstek)" - "OpenGL (Skia)" - "Standaardlimiet" "Geen agtergrondprosesse" diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index b3ea9fbab4eae51dc8a05aa75146c4ca65feeb15..278b07d8dcdf4ec9f466c54f72dc8321368dce3d 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -275,7 +275,6 @@ "Wys hardewarelae se opdaterings" "Laat hardewarelae groen flits wanneer hulle opgedateer word" "Ontfout GPU-oortrek" - "Stel GPU-leweraar" "Deaktiveer HW-oorleggers" "Gebruik altyd GPU vir skermsamestelling" "Simuleer kleurruimte" @@ -409,4 +408,10 @@ "Meer tyd." "Minder tyd." + "Skakel aan" + "Kanselleer" + "Skakel Moenie steur nie aan" + "Nooit" + "Net prioriteit" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml index 3cda6ab8718e7284cfe2d88b50762b093afe5ad9..3f6d3b8aea31d32cd5f3f61960616b6d9fc8c195 100644 --- a/packages/SettingsLib/res/values-ca/arrays.xml +++ b/packages/SettingsLib/res/values-ca/arrays.xml @@ -234,10 +234,6 @@ "Mostra les àrees sobredibuixades" "Mostra les àrees amb deuteranomalia" - - "OpenGL (predeterminat)" - "OpenGL (Skia)" - "Límit estàndard" "Sense processos en segon pla" diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 60531f24fff8dabd7d2773d56f32e91ba80b597c..d020f801bfe792d8dca29f90aec9562e86e79429 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -275,7 +275,6 @@ "Mostra actualitzacions capes" "Il·lumina capes de maquinari en verd en actualitzar-se" "Depura sobredibuix de GPU" - "Configura renderitzador GPU" "Desactiva superposicions HW" "Utilitza sempre GPU per combinar pantalles" "Simula l\'espai de color" @@ -354,14 +353,14 @@ "S\'ha substituït per %1$s" "Temps restant aproximat: ^1" "Temps restant aproximat segons l\'ús que en fas: ^1" - "^1 per completar la pujada" + "^1 per completar la càrrega" "Temps restant: ^1" "Temps restant segons l\'ús que en fas: ^1" "^1: ^2 aproximadament per esgotar la bateria" "^1; temps restant aproximat segons l\'ús que en fas: ^2" "^1; temps restant: ^2" "%1$s: %2$s" - "^1: ^2 per completar la pujada" + "^1: ^2 per completar la càrrega" "Desconegut" "S\'està carregant" "s\'està carregant" @@ -409,4 +408,10 @@ "Més temps" "Menys temps" + "Activa" + "Cancel·la" + "Activa el mode No molestis" + "Mai" + "Només amb prioritat" + "%1$s. %2$s." diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml index 9d665a3bed55947195b6c7aa74629d264ea233d3..7e7bbe1b73231752fb8d90551b1231540f41c923 100644 --- a/packages/SettingsLib/res/values-cs/arrays.xml +++ b/packages/SettingsLib/res/values-cs/arrays.xml @@ -234,10 +234,6 @@ "Zobrazit překreslované oblasti" "Zobrazit oblasti pro deuteranomálii" - - "OpenGL (výchozí)" - "OpenGL (Skia)" - "Standardní limit" "Procesy na pozadí deaktivovány" diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 058f6a76ebb688c80225c840abd36f8c8ee71d8d..c29973c68f33c04eee62fc72559022dbaec29d5b 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -275,7 +275,6 @@ "Zobrazit aktual. HW vrstev" "Rozblikat zeleně hardwarové vrstvy při aktualizaci" "Ladit překreslování GPU" - "Nastavit modul vykreslení" "Zakázat hardwarové vrstvy" "Vždy použít GPU ke skládání obrazovky" "Simulovat barevný prostor" @@ -411,4 +410,10 @@ "Delší doba" "Kratší doba" + "Zapnout" + "Zrušit" + "Zapněte funkci Nerušit" + "Nikdy" + "Pouze prioritní" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml index 0993d314009727350604758108b696d1bf996e75..6d651d52fb3c54a206c7dc3500a2019b75276a33 100644 --- a/packages/SettingsLib/res/values-da/arrays.xml +++ b/packages/SettingsLib/res/values-da/arrays.xml @@ -234,10 +234,6 @@ "Vis områder med overlap" "Vis områder for deuteranomali" - - "OpenGL (standard)" - "OpenGL (Skia)" - "Standardgrænse" "Ingen baggrundsprocesser" diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 98bbaa2ac2c1d6d5e61c4d4b0af1c38ee2f0b887..14d07ff83485fefaa2daa9f3e7ec7b979fd5de1d 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -275,7 +275,6 @@ "Se opdat. af hardwarelag" "Hardwarelag blinker grønt, når de opdateres" "Ret GPU-overlapsfejl" - "Angiv GPU-gengiver" "Deaktiver HW-overlejring" "Brug altid GPU til skærmsammensætning" "Simuler farverum" @@ -409,4 +408,10 @@ "Mere tid." "Mindre tid." + "Aktivér" + "Annuller" + "Aktivér Forstyr ikke" + "Aldrig" + "Kun prioritet" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml index 846e3145ed6bc06ecb8686cbc4596e34cad33a57..b66ace9e7d9e550d0a7e5907bf9056663f9ec49d 100644 --- a/packages/SettingsLib/res/values-en-rXC/arrays.xml +++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml @@ -234,10 +234,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎Show overdraw areas‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎Show areas for Deuteranomaly‎‏‎‎‏‎" - - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎OpenGL (Default)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎OpenGL (Skia)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎Standard limit‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎No background processes‎‏‎‎‏‎" diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 6c9be080f3d6164a72bdb7215e9962f888c3d1cb..7eb1b31a9a1f8d3e6eb8a65abd636ed25947ba59 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -275,7 +275,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎Show hardware layers updates‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎Flash hardware layers green when they update‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎Debug GPU overdraw‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎Set GPU Renderer‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎Disable HW overlays‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎Always use GPU for screen compositing‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎‎‎Simulate color space‎‏‎‎‏‎" @@ -409,4 +408,10 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎More time.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‏‎Less time.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎Turn on‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎Cancel‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎Turn on Do Not Disturb‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎Never‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎Priority only‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml index 9ed0c8961f4622a2e2f4a039c1e749008d8f044d..0bb28e0b199c0d7fc4c8c9b5a388b8780cc243f2 100644 --- a/packages/SettingsLib/res/values-fi/arrays.xml +++ b/packages/SettingsLib/res/values-fi/arrays.xml @@ -234,10 +234,6 @@ "Näytä päällekkäiset alueet" "Näytä alueet puna-vihersokeille näkyvinä" - - "OpenGL (oletus)" - "OpenGL (Skia)" - "Vakioraja" "Ei taustaprosesseja" diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index be19ed63981588fb2fe27f16b74966f38d509ed5..5f9bf481bcc0cb9d6fa7a708fd0316368e7326e1 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -275,7 +275,6 @@ "Näytä laitt.tason päiv." "Näytä laitteistotasot vihreinä niiden päivittyessä" "GPU-objektien päällekkäisyys" - "Grafiikan piirtäjä" "Poista HW-peittok. käyt." "Käytä GPU:ta näytön koostamiseen" "Simuloi väriavaruus" @@ -409,4 +408,10 @@ "Enemmän aikaa" "Vähemmän aikaa" + "Ota käyttöön" + "Peruuta" + "Ota Älä häiritse ‑tila käyttöön" + "Ei koskaan" + "Vain tärkeät" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 13b2c4abc1caa67c4fad05f972a5fed407fd7f4e..4b5201cb080024a28857ad461e6c2e68ac0cc7ac 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -196,7 +196,7 @@ "નેટવર્કિંગ" "વાયરલેસ ડિસ્પ્લે પ્રમાણન" "વાઇ-ફાઇ વર્બોઝ લૉગિંગ સક્ષમ કરો" - "MAC ઍડ્રેસ રેન્ડમાઇઝ કરવું ચાલુ કર્યું" + "કનેક્ટ કરેલ MAC ઍડ્રેસને રેન્ડમાઇઝ કરવાનું ચાલુ કરો" "મોબાઇલ ડેટા હંમેશાં સક્રિય" "ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ" "નામ વિનાના બ્લૂટૂથ ઉપકરણો બતાવો" diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml index 1a765b34e4d76d4ec37f8ca22cf0f682ca156edc..cb8d851a6b13d6070900bbd1fbc338a755563b83 100644 --- a/packages/SettingsLib/res/values-hi/arrays.xml +++ b/packages/SettingsLib/res/values-hi/arrays.xml @@ -234,10 +234,6 @@ "ओवरड्रॉ क्षेत्रों को दिखाएं" "हरा रंग पहचानने में कमी के क्षेत्र दिखाएं" - - "OpenGL (डिफ़ॉल्ट)" - "OpenGL (Skia)" - "मानक सीमा" "कोई पृष्ठभूमि प्रक्रियाएं नहीं" diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index a7a6920ebc6e58f7135ccc922703a67c6518c2b4..16654bef67cc59330d62b848ca424b26f9d469aa 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -275,7 +275,6 @@ "हार्डवेयर लेयर अपडेट दिखाएं" "हार्डवेयर लेयर अपडेट होने पर उनमें हरी रोशनी डालें" "GPU ओवरड्रॉ डीबग करें" - "GPU दाता सेट करें" "HW ओवरले बंद करें" "स्‍क्रीन संयोजन के लिए हमेशा GPU का उपयोग करें" "रंग स्पेस सिम्युलेट करें" @@ -409,4 +408,10 @@ "ज़्यादा समय." "कम समय." + "चालू करें" + "रद्द करें" + "\'परेशान न करें\' चालू करें" + "कभी नहीं" + "सिर्फ़ ज़रूरी" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml index 606494911c13fcd2ed487af27f6d615bbae45a3d..2f21e5f88e9dd32e27d590c782b74fddd15015a5 100644 --- a/packages/SettingsLib/res/values-mr/arrays.xml +++ b/packages/SettingsLib/res/values-mr/arrays.xml @@ -234,10 +234,6 @@ "अधोरेखांकित क्षेत्रे दर्शवा" "हरित असंगतिसाठी क्षेत्रे दर्शवा" - - "OpenGL (डीफॉल्ट)" - "OpenGL (Skia)" - "मानक मर्यादा" "एकही पार्श्वभूमी प्रक्रिया नाही" diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index a15869e4fd99776d02218ce0a2c8d516bb588878..c1acfd0d022cce7188f51c330bbd1db092140817 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -275,7 +275,6 @@ "हार्डवेअर स्तर अपडेट दर्शवा" "हार्डवेअर स्तर अद्ययावत झाल्यावर ते हिरव्या रंगात फ्लॅश करा" "GPU ओव्हरड्रॉ डीबग करा" - "GPU प्रदाता सेट करा" "HW ओव्हरले अक्षम करा" "स्क्रीन तयार करण्यासाठी नेहमी GPU वापरा" "रंग स्थानाची बतावणी करा" @@ -409,4 +408,10 @@ "जास्त वेळ." "कमी वेळ." + "चालू करा" + "रद्द करा" + "व्यत्यय आणू नका चालू करा" + "कधीही नाही" + "केवळ प्राधान्य" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index c5015968e2f6ac9ba33ce2403260dddfa40e19e4..77ebdc7dd94f4e88f746508f0722723572ae011b 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -275,7 +275,6 @@ "Vis maskinvarelag-oppdat." "Maskinvarelag blinker grønt under oppdatering" "Feilsøk GPU-overtrekk" - "Angi GPU-gjengivelse" "Slå av maskinvareoverlegg" "Bruk alltid GPU for skjermsammensetting" "Simuler fargeområde" @@ -409,4 +408,10 @@ "Mer tid." "Mindre tid." + "Slå på" + "Avbryt" + "Slå på Ikke forstyrr" + "Aldri" + "Bare prioritet" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index a44ac29479461fb9073b47e50d049941deab825a..9aeb083958673c4d7ee82e1847da364388f362c9 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -174,9 +174,9 @@ "विकासकर्ता विकल्प सक्रिया गर्नुहोस्" "अनुप्रयोग विकासको लागि विकल्पहरू सेट गर्नुहोस्" "विकासकर्ताका विकल्पहरू यस प्रयोगकर्ताका लागि उपलब्ध छैन" - "VPN सेटिङ्हरू यो प्रयोगकर्ताको लागि उपलब्ध छैन" - "कार्यक्षेत्र सीमा सेटिङ्हरू यो प्रयोगकर्ताको लागि उपलब्ध छैन" - "पहुँच बिन्दु नामको सेटिङ्हरू यो प्रयोगकर्ताको लागि उपलब्ध छैन" + "VPN सेटिङहरू यो प्रयोगकर्ताको लागि उपलब्ध छैन" + "कार्यक्षेत्र सीमा सेटिङहरू यो प्रयोगकर्ताको लागि उपलब्ध छैन" + "पहुँच बिन्दु नामको सेटिङहरू यो प्रयोगकर्ताको लागि उपलब्ध छैन" "USB डिबग गर्दै" "USB जडित हुँदा डिबग मोड" "USB डिबग गर्ने प्राधिकरणहरू उल्टाउनुहोस्" diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml index ace58fd3d2341f619fa12532172f77fd0453769b..6fcdfd276d897bf8d9b75ec9e5476119dec30f33 100644 --- a/packages/SettingsLib/res/values-nl/arrays.xml +++ b/packages/SettingsLib/res/values-nl/arrays.xml @@ -234,10 +234,6 @@ "Gedeeltes met overbelasting weergeven" "Gebieden voor deuteranomalie weergeven" - - "OpenGL (standaard)" - "OpenGL (Skia)" - "Standaardlimiet" "Geen achtergrondprocessen" diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 9fe32ff52ea4db0608b9f087914601b506d7daaf..c1ea14ee3215ac2f4fa3e1bb11660f7fae9e8311 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -275,7 +275,6 @@ "Updaten hardwarelgn wrgvn" "Hardwarelagen knipperen groen bij updates" "Foutopsporing GPU-overbelasting" - "GPU-renderer instellen" "HW-overlays uitschakelen" "GPU altijd gebruiken voor schermcompositing" "Kleurruimte simuleren" @@ -409,4 +408,10 @@ "Meer tijd." "Minder tijd." + "Inschakelen" + "Annuleren" + "Schakel Niet storen in." + "Nooit" + "Alleen prioriteit" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml index 78a24c4d3bb5c66f162d48a4736a01afcdbda26f..384d9f5862fecea92df12e2ee051f6b02673c558 100644 --- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml @@ -234,10 +234,6 @@ "Mostrar áreas de sobreposição" "Mostrar áreas para Deuteranomaly" - - "OpenGL (predefinição)" - "OpenGL (Skia)" - "Limite padrão" "Sem processos em segundo plano" diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 16e3d2bbb0fc64f7670b0a988ce9fc3749cd2a3a..2965ca72c14dd2c8548d83404201ba61b23d5a58 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -275,7 +275,6 @@ "Mostrar atual. cam. hard." "Camadas de hard. flash verdes quando estão atuali." "Depurar sobreposição GPU" - "Definir renderizador GPU" "Desativ. sobreposições HW" "Utilizar sempre GPU para a composição do ecrã" "Simular espaço da cor" @@ -409,4 +408,10 @@ "Mais tempo." "Menos tempo." + "Ativar" + "Cancelar" + "Ativar o modo Não incomodar" + "Nunca" + "Apenas prioridade" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml index 05ccc80f37c3e399f1d29ed42df454f2fcb8659f..4e771b74e1d005875f1655de694704c04ed65ec6 100644 --- a/packages/SettingsLib/res/values-ru/arrays.xml +++ b/packages/SettingsLib/res/values-ru/arrays.xml @@ -234,10 +234,6 @@ "Показывать области наложения" "Выделять области определенного цвета" - - "OpenGL (по умолчанию)" - "OpenGL (Skia)" - "Стандартное ограничение" "Без фоновых процессов" diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index bdf8a4a6f29dab23b91b24652c94954aa9762c41..a4732eb4f9bd8a8b38137a8d634f894e144bbb33 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -275,7 +275,6 @@ "Показ. аппаратные обновл." "Выделять аппаратные уровни зеленым при обновлении" "Отладка наложения" - "Средство визуализации" "Откл. аппарат. наложения" "Всегда использовать GPU при компоновке экрана" "Имитировать аномалию" @@ -411,4 +410,10 @@ "Увеличить продолжительность" "Уменьшить продолжительность" + "Включить" + "Отмена" + "Включите режим \"Не беспокоить\"" + "Никогда" + "Только важные" + "%1$s. %2$s." diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml index e3f21ad6b6f12d6f30cbd5a098e516b5a88295c2..4a1c6262e7a9b66e935ed406e338c34565062b31 100644 --- a/packages/SettingsLib/res/values-uk/arrays.xml +++ b/packages/SettingsLib/res/values-uk/arrays.xml @@ -234,10 +234,6 @@ "Показувати області накладання" "Показувати області дейтераномалії" - - "OpenGL (за умовчанням)" - "OpenGL (Skia)" - "Стандартне обмеження" "Без фонових процесів" diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index e9f6c06d868c82049c7c507e3716d140dc86c35b..6b864ea13b3596522fa28bf6fadefd18d81f335c 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -275,7 +275,6 @@ "Показ. апаратні оновлення" "Виділяти апаратні рівні зеленим під час оновлення" "Налагодити накладання GPU" - "Вибрати засіб обробки відео для ГП" "Вимк. апаратн. накладання" "Завжди використовувати GPU для компонування екрана" "Моделювання кольорів" @@ -411,4 +410,10 @@ "Більше часу." "Менше часу." + "Увімкнути" + "Скасувати" + "Увімкнути режим \"Не турбувати\"" + "Ніколи" + "Лише пріоритетні" + "%1$s. %2$s" diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml index ce2e89fd6047f9457410e2379c742b2ed01bae63..7e5696e18c6e0c837cbbb6d2582b0f5e1cfb2e06 100644 --- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml @@ -234,10 +234,6 @@ "顯示透支區域" "顯示綠色弱視區域" - - "OpenGL (預設)" - "OpenGL (Skia)" - "標準限制" "不執行背景處理程序" diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 6b7d7e876468f7d825433b6dbabfd9be7635908a..4e9e4a8b247590560bc3d9f6d9480518a173a56a 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -275,7 +275,6 @@ "顯示硬體層更新" "在硬體層更新時閃綠燈" "針對 GPU 重複繪圖進行偵錯" - "設定 GPU 轉譯器" "停用硬體重疊圖層" "一律使用 GPU 進行畫面合成" "模擬色彩空間" @@ -409,4 +408,10 @@ "增加時間。" "減少時間。" + "開啟" + "取消" + "開啟「零打擾」模式" + "永不" + "僅限優先通知" + "%1$s%2$s" diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml index 3d0de36adb0252060556ecd69783cb68146bc317..6361dc1e2cf3bcd06600c579ad86ccd3c06b805a 100644 --- a/packages/SettingsLib/res/values-zu/arrays.xml +++ b/packages/SettingsLib/res/values-zu/arrays.xml @@ -234,10 +234,6 @@ "Bonisa izindawo zokukhipha okungaphezulu" "Bonisa izindawo ze-Deuteranomaly" - - "I-OpenGL (Okuzenzakalelayo)" - "I-OpenGL (Skia)" - "Isilanganiso esivamile" "Azikho izinqubo zesizinda" diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index c5d6627c84edfb3f2b5d48eff94a1cc36d52f373..4f7f4196ef8a2f2812ab762b9ffb155be9867295 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -275,7 +275,6 @@ "Bonisa izibuyekezo zezendlalelo izingxenyekazi zekhompyutha" "Izendlalelo zengxenyekazi zekhompyutha eziluhlaza uma zibuyekeza" "Susa iphutha lokukhipha okungaphezulu kwe-GPU" - "Setha isinikezeli se-GPU" "Khubaza izimbondela ze-HW" "Njalo sebenzisa i-GPU ukwakha isikrini" "Qoqa isikhala sombala" @@ -409,4 +408,10 @@ "Isikhathi esiningi." "Isikhathi esincane." + "Vula" + "Khansela" + "Vula ukungaphazamisi" + "Soze" + "Okubalulekile kuphela" + "%1$s. %2$s" diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java index 79838962ef1eea2de249a4d02f3ac333f65543ab..c23f22648764a14092d368c82abe0e5a6455dd39 100644 --- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java +++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java @@ -17,21 +17,20 @@ package com.android.settingslib.core.instrumentation; import android.app.Activity; -import android.content.Context; +import android.arch.lifecycle.Lifecycle.Event; +import android.arch.lifecycle.LifecycleObserver; +import android.arch.lifecycle.OnLifecycleEvent; import android.content.Intent; import android.os.SystemClock; import com.android.internal.logging.nano.MetricsProto; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnPause; -import com.android.settingslib.core.lifecycle.events.OnResume; import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN; /** * Logs visibility change of a fragment. */ -public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPause { +public class VisibilityLoggerMixin implements LifecycleObserver { private static final String TAG = "VisibilityLoggerMixin"; @@ -55,7 +54,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPau mMetricsFeature = metricsFeature; } - @Override + @OnLifecycleEvent(Event.ON_RESUME) public void onResume() { mVisibleTimestamp = SystemClock.elapsedRealtime(); if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) { @@ -63,7 +62,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPau } } - @Override + @OnLifecycleEvent(Event.ON_PAUSE) public void onPause() { mVisibleTimestamp = 0; if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index e11017ce344923d2628a30d538391da94022d90e..f69944006a87ad638873ab9db1bb32c3c1992e19 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -622,6 +622,19 @@ public class AccessPoint implements Comparable { return builder.toString(); } + public static String getKey(WifiConfiguration config) { + StringBuilder builder = new StringBuilder(); + + if (TextUtils.isEmpty(config.SSID)) { + builder.append(config.BSSID); + } else { + builder.append(removeDoubleQuotes(config.SSID)); + } + + builder.append(',').append(getSecurity(config)); + return builder.toString(); + } + public String getKey() { return mKey; } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index 1ac56a9de98fc45e173056b47c282aba24284d12..fac585e06306696bcb95f70ab9a58aee0b0b1385 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -92,8 +92,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro * and used so as to assist with in-the-field WiFi connectivity debugging */ public static boolean sVerboseLogging; - // TODO(b/36733768): Remove flag includeSaved - // TODO: Allow control of this? // Combo scans can take 5-6s to complete - set to 10s. private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000; @@ -106,8 +104,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro private final NetworkRequest mNetworkRequest; private final AtomicBoolean mConnected = new AtomicBoolean(false); private final WifiListener mListener; - private final boolean mIncludeSaved; - private final boolean mIncludeScans; @VisibleForTesting MainHandler mMainHandler; @VisibleForTesting WorkHandler mWorkHandler; private HandlerThread mWorkThread; @@ -150,7 +146,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro // TODO(sghuman): Change this to be keyed on AccessPoint.getKey private final HashMap mScanResultCache = new HashMap<>(); - private Integer mScanId = 0; private NetworkInfo mLastNetworkInfo; private WifiInfo mLastInfo; @@ -189,16 +184,18 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro @Deprecated public WifiTracker(Context context, WifiListener wifiListener, boolean includeSaved, boolean includeScans) { - this(context, wifiListener, includeSaved, includeScans, + this(context, wifiListener, context.getSystemService(WifiManager.class), context.getSystemService(ConnectivityManager.class), context.getSystemService(NetworkScoreManager.class), newIntentFilter()); } + // TODO(Sghuman): Clean up includeSaved and includeScans from all constructors and linked + // calling apps once IC window is complete public WifiTracker(Context context, WifiListener wifiListener, @NonNull Lifecycle lifecycle, boolean includeSaved, boolean includeScans) { - this(context, wifiListener, includeSaved, includeScans, + this(context, wifiListener, context.getSystemService(WifiManager.class), context.getSystemService(ConnectivityManager.class), context.getSystemService(NetworkScoreManager.class), @@ -208,19 +205,13 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro @VisibleForTesting WifiTracker(Context context, WifiListener wifiListener, - boolean includeSaved, boolean includeScans, WifiManager wifiManager, ConnectivityManager connectivityManager, NetworkScoreManager networkScoreManager, IntentFilter filter) { - if (!includeSaved && !includeScans) { - throw new IllegalArgumentException("Must include either saved or scans"); - } mContext = context; mMainHandler = new MainHandler(Looper.getMainLooper()); mWifiManager = wifiManager; - mIncludeSaved = includeSaved; - mIncludeScans = includeScans; - mListener = wifiListener; + mListener = new WifiListenerWrapper(wifiListener); mConnectivityManager = connectivityManager; // check if verbose logging has been turned on or off @@ -458,7 +449,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro private void handleResume() { mScanResultCache.clear(); mSeenBssids.clear(); - mScanId = 0; } private Collection updateScanResultCache(final List newResults) { @@ -533,7 +523,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro /** * Update the internal list of access points. * - *

    Do not called directly (except for forceUpdate), use {@link #updateAccessPoints()} which + *

    Do not call directly (except for forceUpdate), use {@link #updateAccessPoints()} which * respects {@link #mStaleScanResults}. */ @GuardedBy("mLock") @@ -542,7 +532,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro WifiConfiguration connectionConfig = null; if (mLastInfo != null) { connectionConfig = getWifiConfigurationForNetworkId( - mLastInfo.getNetworkId(), mWifiManager.getConfiguredNetworks()); + mLastInfo.getNetworkId(), configs); } // Swap the current access points into a cached list. @@ -554,43 +544,12 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro accessPoint.clearConfig(); } - /* Lookup table to more quickly update AccessPoints by only considering objects with the - * correct SSID. Maps SSID -> List of AccessPoints with the given SSID. */ - Multimap existingApMap = new Multimap(); - final Collection results = updateScanResultCache(newScanResults); - // TODO(sghuman): This entire block only exists to populate the WifiConfiguration for - // APs, remove and refactor + final Map configsByKey = new ArrayMap(configs.size()); if (configs != null) { for (WifiConfiguration config : configs) { - if (config.selfAdded && config.numAssociation == 0) { - continue; - } - AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints); - if (mLastInfo != null && mLastNetworkInfo != null) { - accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo); - } - if (mIncludeSaved) { - // If saved network not present in scan result then set its Rssi to - // UNREACHABLE_RSSI - boolean apFound = false; - for (ScanResult result : results) { - if (result.SSID.equals(accessPoint.getSsidStr())) { - apFound = true; - break; - } - } - if (!apFound) { - accessPoint.setUnreachable(); - } - accessPoints.add(accessPoint); - existingApMap.put(accessPoint.getSsidStr(), accessPoint); - } else { - // If we aren't using saved networks, drop them into the cache so that - // we have access to their saved info. - cachedAccessPoints.add(accessPoint); - } + configsByKey.put(AccessPoint.getKey(config), config); } } @@ -626,40 +585,20 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro for (Map.Entry> entry : scanResultsByApKey.entrySet()) { // List can not be empty as it is dynamically constructed on each iteration ScanResult firstResult = entry.getValue().get(0); - boolean found = false; - for (AccessPoint accessPoint : existingApMap.getAll(firstResult.SSID)) { - accessPoint.setScanResults(entry.getValue()); - found = true; - break; - } - // Only create a new AP / add to the list if it wasn't already in the saved configs - if (!found) { - AccessPoint accessPoint = - getCachedOrCreate(entry.getValue(), cachedAccessPoints); - if (mLastInfo != null && mLastNetworkInfo != null) { - accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo); - } - - // TODO(sghuman): Move isPasspointNetwork logic into AccessPoint.java - if (firstResult.isPasspointNetwork()) { - // Retrieve a WifiConfiguration for a Passpoint provider that matches - // the given ScanResult. This is used for showing that a given AP - // (ScanResult) is available via a Passpoint provider (provider friendly - // name). - try { - WifiConfiguration config = - mWifiManager.getMatchingWifiConfig(firstResult); - if (config != null) { - accessPoint.update(config); - } - } catch (UnsupportedOperationException e) { - // Passpoint not supported on the device. - } - } + AccessPoint accessPoint = + getCachedOrCreate(entry.getValue(), cachedAccessPoints); + if (mLastInfo != null && mLastNetworkInfo != null) { + accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo); + } - accessPoints.add(accessPoint); + // Update the matching config if there is one, to populate saved network info + WifiConfiguration config = configsByKey.get(entry.getKey()); + if (config != null) { + accessPoint.update(config); } + + accessPoints.add(accessPoint); } } @@ -1052,6 +991,39 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro } } + /** + * Wraps the given {@link WifiListener} instance and executes it's methods on the Main Thread. + * + *

    This mechanism allows us to no longer need a separate MainHandler and WorkHandler, which + * were previously both performing work, while avoiding errors which occur from executing + * callbacks which manipulate UI elements from a different thread than the MainThread. + */ + private static class WifiListenerWrapper implements WifiListener { + + private final Handler mHandler; + private final WifiListener mDelegatee; + + public WifiListenerWrapper(WifiListener listener) { + mHandler = new Handler(Looper.getMainLooper()); + mDelegatee = listener; + } + + @Override + public void onWifiStateChanged(int state) { + mHandler.post(() -> mDelegatee.onWifiStateChanged(state)); + } + + @Override + public void onConnectedChanged() { + mHandler.post(() -> mDelegatee.onConnectedChanged()); + } + + @Override + public void onAccessPointsChanged() { + mHandler.post(() -> mDelegatee.onAccessPointsChanged()); + } + } + public interface WifiListener { /** * Called when the state of Wifi has changed, the state will be one of diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java index b36dda9deecf572ff9820ad1e7d87a62fa59f58b..6be4936413b73e5bc8204e75477e467f54652948 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java @@ -281,8 +281,6 @@ public class WifiTrackerTest { final WifiTracker wifiTracker = new WifiTracker( mContext, mockWifiListener, - true, - true, mockWifiManager, mockConnectivityManager, mockNetworkScoreManager, @@ -687,6 +685,7 @@ public class WifiTrackerTest { */ @Test public void trackPasspointApWithPasspointDisabled() throws Exception { + // TODO(sghuman): Delete this test and replace with a passpoint test WifiTracker tracker = createMockedWifiTracker(); // Add a Passpoint AP to the scan results. @@ -709,10 +708,7 @@ public class WifiTrackerTest { when(mockWifiManager.getConfiguredNetworks()) .thenReturn(new ArrayList()); when(mockWifiManager.getScanResults()).thenReturn(results); - doThrow(new UnsupportedOperationException()) - .when(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class)); tracker.forceUpdate(); - verify(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class)); } @Test @@ -758,7 +754,7 @@ public class WifiTrackerTest { tracker.forceUpdate(); verify(mockWifiManager).getConnectionInfo(); - verify(mockWifiManager, times(2)).getConfiguredNetworks(); + verify(mockWifiManager, times(1)).getConfiguredNetworks(); verify(mockConnectivityManager).getNetworkInfo(any(Network.class)); verify(mockWifiListener, never()).onAccessPointsChanged(); // mStaleAccessPoints is true diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java index a2648861d1d855e0dcca8a75d65a9292fba206e3..1ab6afe5b99dfaad589610d4f5858fe386db8858 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java @@ -18,6 +18,7 @@ package com.android.settingslib.core.instrumentation; import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; @@ -30,6 +31,8 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; import com.android.internal.logging.nano.MetricsProto; import com.android.settingslib.SettingsLibRobolectricTestRunner; import com.android.settingslib.TestConfig; @@ -39,6 +42,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; @@ -110,6 +115,30 @@ public class VisibilityLoggerMixinTest { .hidden(nullable(Context.class), anyInt()); } + @Test + public void activityShouldBecomeVisibleAndHide() { + ActivityController ac = Robolectric.buildActivity(TestActivity.class); + TestActivity testActivity = ac.get(); + MockitoAnnotations.initMocks(testActivity); + ac.create().start().resume(); + verify(testActivity.mMetricsFeatureProvider, times(1)).visible(any(), anyInt(), anyInt()); + ac.pause().stop().destroy(); + verify(testActivity.mMetricsFeatureProvider, times(1)).hidden(any(), anyInt()); + } + + public static class TestActivity extends FragmentActivity { + @Mock + MetricsFeatureProvider mMetricsFeatureProvider; + + @Override + public void onCreate(Bundle savedInstanceState) { + VisibilityLoggerMixin mixin = new VisibilityLoggerMixin( + TestInstrumentable.TEST_METRIC, mMetricsFeatureProvider); + getLifecycle().addObserver(mixin); + super.onCreate(savedInstanceState); + } + } + private final class TestInstrumentable implements Instrumentable { public static final int TEST_METRIC = 12345; diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 74281492413744dca889ed8fedd55b6f684bdf79..1dc8e46a694a08771967354205f1f93f0cfe8d94 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -87,7 +87,6 @@ class DatabaseHelper extends SQLiteOpenHelper { private static final HashSet mValidTables = new HashSet(); - private static final String DATABASE_JOURNAL_SUFFIX = "-journal"; private static final String DATABASE_BACKUP_SUFFIX = "-backup"; private static final String TABLE_SYSTEM = "system"; @@ -148,12 +147,7 @@ class DatabaseHelper extends SQLiteOpenHelper { } File databaseFile = mContext.getDatabasePath(getDatabaseName()); if (databaseFile.exists()) { - databaseFile.delete(); - } - File databaseJournalFile = mContext.getDatabasePath(getDatabaseName() - + DATABASE_JOURNAL_SUFFIX); - if (databaseJournalFile.exists()) { - databaseJournalFile.delete(); + SQLiteDatabase.deleteDatabase(databaseFile); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index b286f89d00495d59143ce5870059fb2bd6f51f7f..537e8dca39c82d3d54ba7d46c05cb79ff98ed0b4 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -522,9 +522,6 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.WIFI_WAKEUP_ENABLED, GlobalSettingsProto.WIFI_WAKEUP_ENABLED); - dumpSetting(s, p, - Settings.Global.WIFI_WAKEUP_AVAILABLE, - GlobalSettingsProto.WIFI_WAKEUP_AVAILABLE); dumpSetting(s, p, Settings.Global.NETWORK_SCORING_UI_ENABLED, GlobalSettingsProto.NETWORK_SCORING_UI_ENABLED); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index d1459bba90c132c7be505d1e41b9831abcbb9c73..85a579d2808d37a31c2e7af57db171f95651cc09 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -2328,7 +2328,9 @@ public class SettingsProvider extends ContentProvider { // Get all uids for the user's packages. final List packages; try { - packages = mPackageManager.getInstalledPackages(0, user.id).getList(); + packages = mPackageManager.getInstalledPackages( + PackageManager.MATCH_UNINSTALLED_PACKAGES, + user.id).getList(); } catch (RemoteException e) { throw new IllegalStateException("Package manager not available"); } @@ -3015,7 +3017,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 152; + private static final int SETTINGS_VERSION = 154; private final int mUserId; @@ -3401,7 +3403,9 @@ public class SettingsProvider extends ContentProvider { // Fill each uid with the legacy ssaid to be backwards compatible. final List packages; try { - packages = mPackageManager.getInstalledPackages(0, userId).getList(); + packages = mPackageManager.getInstalledPackages( + PackageManager.MATCH_UNINSTALLED_PACKAGES, + userId).getList(); } catch (RemoteException e) { throw new IllegalStateException("Package manager not available"); } @@ -3416,6 +3420,9 @@ public class SettingsProvider extends ContentProvider { // Android Id doesn't exist for this package so create it. ssaidSettings.insertSettingLocked(uid, legacySsaid, null, true, info.packageName); + if (DEBUG) { + Slog.d(LOG_TAG, "Keep the legacy ssaid for uid=" + uid); + } } } } @@ -3540,21 +3547,9 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 146) { - // Version 147: Set the default value for WIFI_WAKEUP_AVAILABLE. - if (userId == UserHandle.USER_SYSTEM) { - final SettingsState globalSettings = getGlobalSettingsLocked(); - final Setting currentSetting = globalSettings.getSettingLocked( - Settings.Global.WIFI_WAKEUP_AVAILABLE); - if (currentSetting.getValue() == null) { - final int defaultValue = getContext().getResources().getInteger( - com.android.internal.R.integer.config_wifi_wakeup_available); - globalSettings.insertSettingLocked( - Settings.Global.WIFI_WAKEUP_AVAILABLE, - String.valueOf(defaultValue), - null, true, SettingsState.SYSTEM_PACKAGE_NAME); - } - } - + // Version 147: Removed. (This version previously allowed showing the + // "wifi_wakeup_available" setting). + // The setting that was added here is deleted in 153. currentVersion = 147; } @@ -3621,18 +3616,34 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 151) { - // Version 152: Reset wifi wake available for upgrading users - final SettingsState globalSettings = getGlobalSettingsLocked(); - final int defaultValue = getContext().getResources().getInteger( - com.android.internal.R.integer.config_wifi_wakeup_available); - globalSettings.insertSettingLocked( - Settings.Global.WIFI_WAKEUP_AVAILABLE, - String.valueOf(defaultValue), - null, true, SettingsState.SYSTEM_PACKAGE_NAME); - + // Version 152: Removed. (This version made the setting for wifi_wakeup enabled + // by default but it is now no longer configurable). + // The setting updated here is deleted in 153. currentVersion = 152; } + if (currentVersion == 152) { + getGlobalSettingsLocked().deleteSettingLocked("wifi_wakeup_available"); + currentVersion = 153; + } + + if (currentVersion == 153) { + // Version 154: Read notification badge configuration from config. + // If user has already set the value, don't do anything. + final SettingsState systemSecureSettings = getSecureSettingsLocked(userId); + final Setting showNotificationBadges = systemSecureSettings.getSettingLocked( + Settings.Secure.NOTIFICATION_BADGING); + if (showNotificationBadges.isNull()) { + final boolean defaultValue = getContext().getResources().getBoolean( + com.android.internal.R.bool.config_notificationBadging); + systemSecureSettings.insertSettingLocked( + Secure.NOTIFICATION_BADGING, + defaultValue ? "1" : "0", + null, true, SettingsState.SYSTEM_PACKAGE_NAME); + } + currentVersion = 154; + } + // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk index 251ae2da121542452c34e84fe0fc89c34c3444a9..2bcf4ef9f8564555955386530a665c098df75654 100644 --- a/packages/SystemUI/Android.mk +++ b/packages/SystemUI/Android.mk @@ -48,8 +48,8 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \ android-slices-core \ android-slices-view \ android-slices-builders \ - apptoolkit-arch-core-runtime \ - apptoolkit-lifecycle-extensions \ + android-arch-core-runtime \ + android-arch-lifecycle-extensions \ LOCAL_STATIC_JAVA_LIBRARIES := \ SystemUI-tags \ diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS new file mode 100644 index 0000000000000000000000000000000000000000..af6dd77224c4f07b3c8f5a6c1afd0f3daf2477d2 --- /dev/null +++ b/packages/SystemUI/OWNERS @@ -0,0 +1,20 @@ +set noparent + +dsandler@google.com + +asc@google.com +ashaikh@google.com +beverlyt@google.com +cinek@google.com +cwren@google.com +evanlaird@google.com +jmonk@google.com +jaggies@google.com +jjaggi@google.com +juliacr@google.com +dupin@google.com +madym@google.com +roosa@google.com +shahrk@google.com +winsonc@google.com + diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml index bf0d6799bfd154fe2655d452b02ad01ec805d4d8..3f5f76fa0add95ab73541183c1948e6c6cbd3c40 100644 --- a/packages/SystemUI/res-keyguard/values-af/strings.xml +++ b/packages/SystemUI/res-keyguard/values-af/strings.xml @@ -53,6 +53,8 @@ "Volgende wekker gestel vir %1$s" "Vee uit" "Deaktiveer e-SIM" + "Kan nie e-SIM deaktiveer nie" + "Die e-SIM kan weens \'n fout nie gedeaktiveer word nie." "Enter" "Het jy die patroon vergeet?" "Verkeerde patroon" @@ -65,7 +67,7 @@ "Teken jou patroon" "Voer SIM se PIN in." "Voer SIM se PIN vir \"%1$s\" in." - "Deaktiveer e-SIM om toestel sonder mobiele diens te gebruik." + "%1$s Deaktiveer e-SIM om toestel sonder mobiele diens te gebruik." "Voer PIN in" "Voer wagwoord in" "SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Kontak diensverskaffer vir besonderhede." diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index 340e5141c05de7eda9e8a5ecad671f37022224d9..1cd862d8e0cd609c21359ae62e7df40de36e4f0c 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -53,6 +53,8 @@ "ቀጣዩ ማንቂያ ለ%1$s ተዘጋጅቷል" "ሰርዝ" "eSIMን አሰናክል" + "eSIMን ማሰናከል አልተቻለም" + "በአንድ ስህተት ምክንያት eSIM ሊሰናከል አልቻለም።" "አስገባ" "ስርዓተ ጥለቱን እርሳ" "የተሳሳተ ስርዓተ ጥለት" @@ -65,7 +67,7 @@ "ስርዓተ ጥለትዎን ይሳሉ" "የሲም ፒን ያስገቡ።" "የ«%1$s» ሲም ፒን ያስገቡ።" - "መሣሪያን ያለተንቀሳቃሽ ስልክ አገልግሎት ለመጠቀም eSIMን ያሰናክሉ።" + "%1$s መሣሪያን ያለሞባይል አገልግሎት ለመጠቀም eSIMን ያሰናክሉ።" "ፒን ያስገቡ" "የይለፍ ቃል ያስገቡ" "ሲም አሁን ተሰናክሏል። ለመቀጠል የፒዩኬ ኮድ ያስገቡ። ለዝርዝር አገልግሎት አቅራቢን ያግኙ።" diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml index b0503eade59954732409c7d8967d423238548b4a..3ab93c5c21c9660200828fc78c9fdcbb66c8a9c5 100644 --- a/packages/SystemUI/res-keyguard/values-az/strings.xml +++ b/packages/SystemUI/res-keyguard/values-az/strings.xml @@ -53,6 +53,8 @@ "Növbəti zəng vaxtı: %1$s" "Silin" "eSİM\'i deaktiv edin" + "eSIM-i deaktiv etmək alınmadı" + "eSIM xəta səbəbi ilə deaktiv edilmədi." "Daxil edin" "Modeli unutmuşam" "Yanlış Model" @@ -65,7 +67,7 @@ "Modeli çəkin" "SIM PIN\'ni daxil edin." "\"%1$s\" üçün SIM PIN\'ni daxil edin." - "Mobil xidmət olmadan cihazı istifadə etmək üçün eSIM\'i deaktiv edin." + "%1$s Mobil xidmət olmadan cihazı istifadə etmək üçün eSIM-i deaktiv edin." "PIN daxil edin" "Parol daxil edin" "SIM indi deaktivdir. Davam etmək üçün PUK kod daxil edin. Ətraflı məlumat üçün operatorla əlaqə saxlayın." diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index 791f5e9626fb383ab20cdd6d21d26f2f617a112b..81c56da4146b760b617ac5e3e78d10cff3cf486e 100644 --- a/packages/SystemUI/res-keyguard/values-bn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml @@ -53,6 +53,10 @@ "পরবর্তী অ্যালার্ম %1$s এ সেট করা হয়েছে" "মুছুন" "ই-সিমটি অক্ষম করুন" + + + + "এন্টার" "প্যাটার্ন ভুলে গেছি" "ভুল প্যাটার্ন" @@ -65,7 +69,8 @@ "আপনার প্যাটার্ন আঁকুন" "সিমের পিন লিখুন।" "\"%1$s\" এর জন্য সিমের পিন লিখুন।" - "মোবাইল পরিষেবা ছাড়াই ডিভাইস ব্যবহার করতে ই-সিম অক্ষম করুন।" + + "পিন লিখুন" "পাসওয়ার্ড লিখুন" "সিমটি এখন অক্ষম করা হয়েছে। চালিয়ে যেতে PUK কোডটি লিখুন। বিশদ বিবরণের জন্য পরিষেবা প্রদানকারীর সাথে যোগাযোগ করুন।" diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index 1f6addfb289266fc7b973fbb3d14616e05ca7364..6ff819ca45e63c6e966a4be1798622fa3555ddf7 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -53,6 +53,10 @@ "Naredni alarm je podešen za %1$s" "Izbriši" "Onemogući eSIM karticu" + + + + "Enter" "Zaboravili ste uzorak?" "Pogrešan uzorak" @@ -66,7 +70,8 @@ "Nacrtajte uzorak" "Unesite PIN SIM kartice." "Unesite PIN SIM kartice operatera \"%1$s\"" - "Onemogućite eSIM karticu za korištenje uređaja bez mobilne usluge." + + "Unesite PIN" "Unesite lozinku" "SIM kartica je sada onemogućena. Unesite PUK kôd da nastavite. Za više informacija obratite se operateru." diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index dd2844abb6ecfd57451dd48a633792cb60d884aa..511516ea79261161fc3720f1599eca5f8e6333dd 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -53,6 +53,10 @@ "S\'ha definit la pròxima alarma per a l\'hora següent: %1$s" "Suprimeix" "Desactiva l\'eSIM" + + + + "Retorn" "He oblidat el patró" "El patró no és correcte" @@ -65,7 +69,8 @@ "Dibuixa el patró" "Introdueix el PIN de la SIM." "Introdueix el PIN de la SIM de: %1$s." - "Desactiva l\'eSIM per utilitzar el dispositiu sense servei mòbil." + + "Introdueix el PIN" "Introdueix la contrasenya" "La SIM està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir més informació." diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index cf7abf121301f604b9975e18f965f2af7ba3eed2..d5f80cbd227a5392183aa2eae165e88b385a7d15 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -53,6 +53,8 @@ "Další budík je nastaven na %1$s" "Smazat" "Deaktivovat eSIM kartu" + "Nelze deaktivovat eSIM kartu" + "eSIM kartu kvůli chybě nelze deaktivovat." "Enter" "Zapomenuté gesto" "Nesprávné gesto" @@ -67,7 +69,7 @@ "Zadejte gesto" "Zadejte kód PIN SIM karty." "Zadejte kód PIN SIM karty %1$s." - "eSIM kartu deaktivujte, chcete-li telefon používat bez mobilních služeb." + "%1$s eSIM kartu deaktivujte, chcete-li zařízení používat bez mobilních služeb." "Zadejte kód PIN" "Zadejte heslo" "SIM karta byla zablokována. Chcete-li pokračovat, je třeba zadat kód PUK. Podrobné informace získáte od operátora." diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml index b6dc72b52bfe92e56219c3a2278d534fa7af6db5..57b98fa47238d3ae22d5c7eea30f0b7ff0e810e0 100644 --- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml @@ -53,6 +53,8 @@ "Next alarm set for %1$s" "Delete" "Disable eSIM" + "Can’t disable eSIM" + "The eSIM can’t be disabled due to an error." "Enter" "Forgotten Pattern" "Wrong Pattern" @@ -65,7 +67,7 @@ "Draw your pattern" "Enter SIM PIN." "Enter SIM PIN for \'%1$s\'." - "Disable eSIM to use device without mobile service." + "%1$s Disable eSIM to use device without mobile service." "Enter PIN" "Enter Password" "SIM is now disabled. Enter PUK code to continue. Contact carrier for details." diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml index b6dc72b52bfe92e56219c3a2278d534fa7af6db5..57b98fa47238d3ae22d5c7eea30f0b7ff0e810e0 100644 --- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml @@ -53,6 +53,8 @@ "Next alarm set for %1$s" "Delete" "Disable eSIM" + "Can’t disable eSIM" + "The eSIM can’t be disabled due to an error." "Enter" "Forgotten Pattern" "Wrong Pattern" @@ -65,7 +67,7 @@ "Draw your pattern" "Enter SIM PIN." "Enter SIM PIN for \'%1$s\'." - "Disable eSIM to use device without mobile service." + "%1$s Disable eSIM to use device without mobile service." "Enter PIN" "Enter Password" "SIM is now disabled. Enter PUK code to continue. Contact carrier for details." diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml index b6dc72b52bfe92e56219c3a2278d534fa7af6db5..57b98fa47238d3ae22d5c7eea30f0b7ff0e810e0 100644 --- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml @@ -53,6 +53,8 @@ "Next alarm set for %1$s" "Delete" "Disable eSIM" + "Can’t disable eSIM" + "The eSIM can’t be disabled due to an error." "Enter" "Forgotten Pattern" "Wrong Pattern" @@ -65,7 +67,7 @@ "Draw your pattern" "Enter SIM PIN." "Enter SIM PIN for \'%1$s\'." - "Disable eSIM to use device without mobile service." + "%1$s Disable eSIM to use device without mobile service." "Enter PIN" "Enter Password" "SIM is now disabled. Enter PUK code to continue. Contact carrier for details." diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml index b6dc72b52bfe92e56219c3a2278d534fa7af6db5..57b98fa47238d3ae22d5c7eea30f0b7ff0e810e0 100644 --- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml @@ -53,6 +53,8 @@ "Next alarm set for %1$s" "Delete" "Disable eSIM" + "Can’t disable eSIM" + "The eSIM can’t be disabled due to an error." "Enter" "Forgotten Pattern" "Wrong Pattern" @@ -65,7 +67,7 @@ "Draw your pattern" "Enter SIM PIN." "Enter SIM PIN for \'%1$s\'." - "Disable eSIM to use device without mobile service." + "%1$s Disable eSIM to use device without mobile service." "Enter PIN" "Enter Password" "SIM is now disabled. Enter PUK code to continue. Contact carrier for details." diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml index 97d16c6ed0a592bfa007d21510420957d2c75dca..d27d204165e0c93716c26850cf6f04faddb88c9f 100644 --- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml @@ -53,6 +53,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‎Next alarm set for ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎Delete‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎Disable eSIM‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎Can’t disable eSIM‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎The eSIM can’t be disabled due to an error.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎Enter‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎Forgot Pattern‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎Wrong Pattern‎‏‎‎‏‎" @@ -65,7 +67,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎Draw your pattern‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎Enter SIM PIN.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎Enter SIM PIN for \"‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎\".‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎Disable eSIM to use device without mobile service.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ Disable eSIM to use device without mobile service.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎Enter PIN‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎Enter Password‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎SIM is now disabled. Enter PUK code to continue. Contact carrier for details.‎‏‎‎‏‎" diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index ec36fd73966f24f94545b3d234bac671faa3ed6e..780d8d4b53ffa0c099ab681fe851c5b3a9fe45dc 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -53,6 +53,8 @@ "Próxima alarma: %1$s" "Eliminar" "Inhabilita la tarjeta eSIM" + "No se puede inhabilitar la tarjeta eSIM" + "No se puede mostrar la tarjeta eSIM debido a un error." "Intro" "¿Has olvidado el patrón?" "Patrón incorrecto" @@ -65,7 +67,7 @@ "Dibuja tu patrón" "Introduce el PIN de la tarjeta SIM." "Introduce el PIN de la tarjeta SIM de %1$s." - "Inhabilita la tarjeta eSIM para utilizar el dispositivo sin servicio móvil." + "%1$s Inhabilita la tarjeta eSIM para usar el dispositivo sin servicio móvil." "Introduce el PIN" "Introduce tu contraseña" "La tarjeta SIM está inhabilitada. Para continuar, introduce el código PUK. Si quieres obtener más información, ponte en contacto con el operador." diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index 2b14e3c977bcc9eaad58ee3d6c5be6913e328b61..44aab01c1052ef5e2ece90c430faad396ec39c57 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -53,6 +53,8 @@ "Seuraava hälytys asetettu: %1$s" "Poista" "Poista eSIM käytöstä" + "eSIMiä ei voi poistaa käytöstä" + "Tapahtui virhe, eikä eSIMiä voitu poistaa käytöstä." "Enter" "Unohtunut kuvio" "Väärä kuvio" @@ -65,7 +67,7 @@ "Piirrä kuvio" "Anna SIM-kortin PIN-koodi." "Anna operaattorin %1$s SIM-kortin PIN-koodi." - "Poista eSIM käytöstä, jos haluat käyttää laitetta ilman mobiilipalvelua." + "%1$s Poista eSIM käytöstä, jos haluat käyttää laitetta ilman mobiililiittymää." "Anna PIN-koodi." "Anna salasana" "SIM-kortti on nyt poistettu käytöstä. Jatka antamalla PUK-koodi. Saat lisätietoja ottamalla yhteyttä operaattoriin." diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index b033311f37b966296d40625eb4ad3e035b8d3144..e0b14b9232fcf2abc827d3032a7e5cf985e74e3c 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -53,6 +53,8 @@ "Heure de la prochaine alarme : %1$s" "Supprimer" "Désactiver la carte eSIM" + "Impossible de désactiver la carte eSIM" + "La carte eSIM ne peut pas être réinitialisée à cause d\'une erreur." "Entrée" "J\'ai oublié le schéma" "Schéma incorrect" @@ -65,7 +67,7 @@ "Dessinez votre schéma" "Entrez le NIP de la carte SIM." "Entrez le NIP de la carte SIM pour « %1$s »." - "Désactivez la carte eSIM pour utiliser l\'appareil sans service cellulaire." + "%1$s Désactivez la carte eSIM pour utiliser l\'appareil sans service cellulaire." "Entrez le NIP" "Entrez votre mot de passe." "La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Pour obtenir plus de détails, communiquez avec votre fournisseur de services." diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml index c62bab8616863ffc512a973927fee2e3f9b03d3f..d2e6c023d3f5fb757eaaa48c995fd326558feb4e 100644 --- a/packages/SystemUI/res-keyguard/values-gu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml @@ -53,6 +53,10 @@ "%1$s માટે આગલું એલાર્મ સેટ કર્યું" "કાઢી નાખો" "eSIMને અક્ષમ કરો" + + + + "દાખલ કરો" "પૅટર્ન ભૂલી ગયાં" "ખોટી પૅટર્ન" @@ -65,7 +69,8 @@ "તમારી પૅટર્ન દોરો" "સિમ પિન દાખલ કરો" "\"%1$s\" માટે સિમ પિન દાખલ કરો." - "મોબાઇલ સેવા વગર ઉપકરણનો ઉપયોગ કરવા eSIMને અક્ષમ કરો." + + "પિન દાખલ કરો" "પાસવર્ડ દાખલ કરો" "સિમ હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો." diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index 641c0727085a66645a6badb5d02a125e1b6f1895..dfd06b2824bd291535337f0ce540036d28a36c8e 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -53,6 +53,10 @@ "अगला अलार्म %1$s बजे के लिए सेट किया गया है" "मिटाएं" "eSIM अक्षम करें" + + + + "Enter" "पैटर्न भूल गए हैं" "गलत पैटर्न" @@ -65,7 +69,8 @@ "अपना पैटर्न बनाएं" "सिम पिन डालें." "\"%1$s\" के लिए सिम पिन डालें" - "मोबाइल सेवा के बिना डिवाइस का उपयोग करने के लिए eSIM अक्षम करें." + + "पिन डालें" "पासवर्ड डालें" "सिम अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें." diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 813377aa961ad4af6d0b5c3cdd5b73ae4feef62d..96bcb1097d05261b0a1b85a487e3b45c96177373 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -53,6 +53,8 @@ "Prossima sveglia impostata a: %1$s" "Elimina" "Disattiva eSIM" + "Impossibile disattivare la eSIM" + "Impossibile disattivare la eSIM a causa di un errore." "Invio" "Sequenza dimenticata" "Sequenza sbagliata" @@ -65,7 +67,7 @@ "Inserisci la sequenza" "Inserisci il PIN della SIM." "Inserisci il PIN della SIM \"%1$s\"." - "Disattiva l\'eSIM per usare il dispositivo senza servizio dati mobile." + "%1$s Disattiva la eSIM per usare il dispositivo senza servizio dati mobile." "Inserisci PIN" "Inserisci la password" "La scheda SIM è disattivata. Inserisci il codice PUK per continuare. Contatta l\'operatore per avere informazioni dettagliate." diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml index 2c291124aa93743637dc25c7d0102341efe24f09..690ce658845cd2c4fe9f5c41f313d9d60ddc6d9d 100644 --- a/packages/SystemUI/res-keyguard/values-kn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml @@ -53,6 +53,10 @@ "%1$s ಗಂಟೆಗೆ ಮುಂದಿನ ಅಲಾರಮ್ ಹೊಂದಿಸಲಾಗಿದೆ" "ಅಳಿಸಿ" "eSIM ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + + + + "ನಮೂದಿಸಿ" "ಪ್ಯಾಟರ್ನ್ ಮರೆತಿದ್ದೀರಿ" "ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ" @@ -65,7 +69,8 @@ "ನಿಮ್ಮ ಪ್ಯಾಟರ್ನ್ ಚಿತ್ರಿಸಿ" "ಸಿಮ್‌ ಪಿನ್‌ ನಮೂದಿಸಿ." "\"%1$s\" ಗಾಗಿ ಸಿಮ್ ಪಿನ್ ನಮೂದಿಸಿ." - "ಮೊಬೈಲ್ ಸೇವೆ ಇಲ್ಲದೆಯೇ ಸಾಧನವನ್ನು ಬಳಸಲು eSIM ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ." + + "ಪಿನ್‌ ನಮೂದಿಸಿ" "ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ" "ಈಗ ಸಿಮ್‌ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ. ಮುಂದುವರೆಯಲು PUK ಕೋಡ್ ನಮೂದಿಸಿ. ವಿವರಗಳಿಗಾಗಿ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ." diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml index 545d32a249d118a42bcb3917a77f3fc80c4f362b..10a81d03200acb10246df4ed41558996968b4863 100644 --- a/packages/SystemUI/res-keyguard/values-lo/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml @@ -53,6 +53,10 @@ "ໂມງປຸກຕໍ່ໄປຖືກຕັ້ງໄວ້ເວລາ %1$s" "ລຶບ" "ປິດການໃຊ້ eSIM ແລ້ວ" + + + + "ປ້ອນເຂົ້າ" "ລືມຮູບແບບປົດລັອກ?" "ຮູບແບບຜິດ" @@ -65,7 +69,8 @@ "ແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານ" "ໃສ່ລະຫັດ PIN ຂອງຊິມ." "ໃສ່ລະຫັດ PIN ຂອງຊິມສຳລັບ \"%1$s\"." - "ປິດການໃຊ້ eSIM ເພື່ອໃຊ້ອຸປະກອນໂດຍບໍ່ມີບໍລິການມືຖື." + + "ໃສ່ລະຫັດ PIN" "ໃສ່ລະຫັດຜ່ານ" "ຊິມຖືກປິດການນຳໃຊ້ແລ້ວ. ປ້ອນລະຫັດ PUK ເພື່ອດຳເນີນການຕໍ່. ຕິດຕໍ່ຜູ່ໃຫ້ບໍລິການສຳລັບລາຍລະອຽດ." diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index 095178739d660c8290904b5ca13b2d598625a078..d060ff421171949dc8468542f6977102423595d1 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -53,6 +53,8 @@ "Следниот аларм е поставен во %1$s" "Избриши" "Оневозможи ја eSIM" + "Не може да се оневозможи eSIM" + "eSIM-картичката не може да се оневозможи поради грешка." "Внеси" "Ја заборавивте шемата?" "Погрешна шема" @@ -65,7 +67,7 @@ "Нацртајте ја шемата" "Внесете PIN на SIM." "Внесете PIN на SIM за „%1$s“." - "Оневозможете ја eSIM за да го користите уредот без мобилна услуга." + "%1$s Оневозможете ја eSIM-картичката за да го користите уредот без мобилна услуга." "Внесете PIN" "Внесете лозинка" "SIM-картичката сега е оневозможена. Внесете PUK-код за да продолжите. Контактирајте со операторот за детали." diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index d62537dcd65cd0eb959d3f424c4dfed0eca497d6..7e12a227bff65c895bbec514292881b0c31fe21c 100644 --- a/packages/SystemUI/res-keyguard/values-ml/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml @@ -53,6 +53,10 @@ "അടുത്ത അലാറം %1$s-ന് സജ്ജീകരിച്ചു" "ഇല്ലാതാക്കുക" "eSIM പ്രവർത്തനരഹിതമാക്കുക" + + + + "എന്റർ" "പാറ്റേൺ മറന്നു" "പാറ്റേൺ തെറ്റാണ്" @@ -65,7 +69,8 @@ "നിങ്ങളുടെ പാറ്റേൺ വരയ്‌ക്കുക" "സിം പിൻ നൽകുക." "\"%1$s\" എന്ന കാരിയർക്കുള്ള സിം പിൻ നൽകുക." - "മൊ‌ബൈൽ സേവനമില്ലാതെ ഉപകരണം ഉപയോഗിക്കാൻ eSIM പ്രവർത്തനരഹിതമാക്കുക." + + "പിൻ നൽകുക" "പാസ്‌വേഡ് നൽകുക" "സിം ഇപ്പോൾ പ്രവർത്തനരഹിതമാക്കി. തുടരുന്നതിന് PUK കോഡ് നൽകുക. വിശദാംശങ്ങൾക്ക് കാരിയറെ ബന്ധപ്പെടുക." diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index 7d04edc8b785675245f72483052f47e5c45bac0d..daa40c60d99b8745a191cf0bbbe8520169a8eeac 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -53,6 +53,10 @@ "पुढील अलार्म %1$s साठी सेट केला" "हटवा" "eSIM बंद करा" + + + + "एंटर करा" "पॅटर्न विसरलात" "चुकीचा पॅटर्न" @@ -65,7 +69,8 @@ "तुमचा पॅटर्न काढा" "सिम पिन एंटर करा" "\"%1$s\" साठी सिम पिन एंटर करा" - "मोबाइल सेवांशिवाय डिव्हाइस वापरण्यासाठी eSIM बंद करा." + + "पिन एंटर करा" "पासवर्ड एंटर करा" "सिम आता अक्षम केले आहे. सुरू ठेवण्यासाठी PUK कोड एंटर करा. तपशीलांसाठी वाहकाशी संपर्क साधा." diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index fb85589898680ac24b3e1559cbe9ce73532e6baf..a7236cf976bf93aa8a1325df37b8b0ac59c85aec 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -53,6 +53,8 @@ "နောက်နှိုးစက်အချိန်ကို %1$s တွင် သတ်မှတ်ထားပါသည်" "ဖျက်ရန်" "eSIM ကို ပိတ်ရန်" + "eSIM ကို ပိတ်၍မရခြင်း" + "အမှားအယွင်းရှိနေသောကြောင့် eSIM ကို ပိတ်၍မရပါ။" "Enter ခလုတ်" "ပုံစံအား မေ့သွားပါသည်" "ပုံစံ မမှန်ကန်ပါ" @@ -65,7 +67,7 @@ "ပုံစံကို ဆွဲပါ" "ဆင်းမ်ကဒ် ပင်နံပါတ်ကို ထည့်ပါ။" "\"%1$s\" အတွက် ဆင်းမ်ကဒ်ပင်နံပါတ်ကို ထည့်ပါ။" - "စက်ပစ္စည်းကို မိုဘိုင်းဝန်ဆောင်မှုမပါဘဲ အသုံးပြုရန် eSIM ကို ပိတ်ပါ။" + "%1$s မိုဘိုင်းဝန်ဆောင်မှု မရှိဘဲ စက်ပစ္စည်းကို အသုံးပြုရန် eSIM ကို ပိတ်ပါ။" "ပင်နံပါတ်ကို ထည့်ပါ" "စကားဝှက်ကို ထည့်ပါ" "ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ်ကို ထည့်ပါ။ ပိုမိုလေ့လာရန် မိုဘိုင်းဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်နိုင်ပါသည်။" diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml index ca51c968b410790b27e625e7209bdc43ed2a10b5..2c0e3d6c4c3a61a427bd3249d77f2c0f5a510ad1 100644 --- a/packages/SystemUI/res-keyguard/values-nb/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml @@ -53,6 +53,10 @@ "Neste alarm er stilt inn for %1$s" "Slett" "Deaktiver e-SIM-kortet" + + + + "Enter" "Har du glemt mønsteret?" "Feil mønster" @@ -65,7 +69,8 @@ "Tegn mønsteret ditt" "Skriv inn PIN-koden for SIM-kortet." "Skriv inn PIN-koden for SIM-kortet «%1$s»." - "Deaktiver e-SIM-kortet for å bruke enheten uten mobiltjeneste." + + "Skriv inn PIN-koden" "Skriv inn passordet" "SIM-kortet er nå deaktivert. Skriv inn PUK-koden for å fortsette. Ta kontakt med operatøren for mer informasjon." diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index 90d6c5cfc00c45d5cea75c631ec32eb4acdff344..dcb309f59d04f1590cdb8a76d1245101c9544fda 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -53,6 +53,10 @@ "अर्को अलार्म %1$s का लागि सेट गरियो" "मेट्नुहोस्" "eSIM लाई असक्षम पार्नुहोस्" + + + + "प्रविष्टि गर्नुहोस्" "ढाँचा बिर्सनुभयो" "गलत ढाँचा" @@ -65,7 +69,8 @@ "आफ्नो ढाँचा कोर्नुहोस्" "SIM को PIN प्रविष्टि गर्नुहोस्।" "\"%1$s\" को SIM को PIN प्रविष्ट गर्नुहोस्।" - "मोबाइल सेवा बिना यन्त्रको प्रयोग गर्न eSIM लाई असक्षम पार्नुहोस्।" + + "PIN प्रविष्टि गर्नुहोस्" "पासवर्ड प्रविष्ट गर्नुहोस्" "SIM कार्ड अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड प्रविष्ट गर्नुहोस्। विवरणको लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।" diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index d5d27cacf525921783778a89341c88a6d7cefc90..ddb83e980be790dd00662f0f19996b15b3075b7e 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -53,6 +53,10 @@ "ਅਗਲਾ ਅਲਾਰਮ %1$s \'ਤੇ ਸੈੱਟ ਕੀਤਾ ਗਿਆ" "ਮਿਟਾਓ" "eSIM ਨੂੰ ਅਯੋਗ ਬਣਾਓ" + + + + "ਦਾਖਲ ਕਰੋ" "ਪੈਟਰਨ ਭੁੱਲ ਗਏ" "ਗਲਤ ਪੈਟਰਨ" @@ -65,7 +69,8 @@ "ਆਪਣਾ ਪੈਟਰਨ ਉਲੀਕੋ" "ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।" "\"%1$s\" ਲਈ ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।" - "ਮੋਬਾਈਲ ਸੇਵਾ ਤੋਂ ਬਿਨਾਂ ਡੀਵਾਈਸ ਨੂੰ ਵਰਤਣ ਲਈ eSIM ਬੰਦ ਕਰੋ।" + + "ਪਿੰਨ ਦਾਖਲ ਕਰੋ" "ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ" "ਸਿਮ ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।" diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index bb547f1571859dcb0b3e3d1936cb58d1c22dec6d..5c02d4fd5926382279c4aff01684decf217a3aa3 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -53,6 +53,8 @@ "Próximo alarme definido para %1$s" "Excluir" "Desativar eSIM" + "Não é possível desativar o eSIM" + "Não é possível desativar o eSIM devido a um erro." "Inserir" "Esqueci o padrão" "Padrão incorreto" @@ -65,7 +67,7 @@ "Desenhe seu padrão" "Informe o PIN do cartão SIM." "Informe o PIN do cartão SIM para \"%1$s\"." - "Desative o eSIM para usar o dispositivo sem serviço móvel." + "%1$s Desative o eSIM para usar o dispositivo sem serviço móvel." "Digite o PIN" "Digite a senha" "O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes." diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 6a0e6274b161539a5d53a5daadb98831ba7ef874..73f2b7f1e2a7a08a4ed10167beddb1e370dcb49e 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -53,6 +53,8 @@ "Próximo alarme definido para %1$s" "Eliminar" "Desativar eSIM" + "Não é possível desativar o eSIM" + "Não é possível desativar o eSIM devido a um erro." "Tecla Enter" "Esqueceu-se do padrão" "Padrão incorreto" @@ -65,7 +67,7 @@ "Desenhe o seu padrão" "Introduza o PIN do cartão SIM." "Introduza o PIN do cartão SIM \"%1$s\"." - "Desativar eSIM para utilizar sem serviço móvel" + "%1$s Desative o eSIM para utilizar o dispositivo sem serviço móvel." "Introduza o PIN" "Introduza a palavra-passe" "O cartão SIM está agora desativado. Introduza o código PUK para continuar. Contacte o operador para obter mais detalhes." diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index bb547f1571859dcb0b3e3d1936cb58d1c22dec6d..5c02d4fd5926382279c4aff01684decf217a3aa3 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -53,6 +53,8 @@ "Próximo alarme definido para %1$s" "Excluir" "Desativar eSIM" + "Não é possível desativar o eSIM" + "Não é possível desativar o eSIM devido a um erro." "Inserir" "Esqueci o padrão" "Padrão incorreto" @@ -65,7 +67,7 @@ "Desenhe seu padrão" "Informe o PIN do cartão SIM." "Informe o PIN do cartão SIM para \"%1$s\"." - "Desative o eSIM para usar o dispositivo sem serviço móvel." + "%1$s Desative o eSIM para usar o dispositivo sem serviço móvel." "Digite o PIN" "Digite a senha" "O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes." diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml index 341c95297733fb7c6c38fe03729414fd75a88526..f449701b8bcb774f6ff2e3f0902b5ca63cd21458 100644 --- a/packages/SystemUI/res-keyguard/values-ro/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml @@ -53,6 +53,8 @@ "Următoarea alarmă este setată pentru %1$s" "Ștergeți" "Dezactivați cardul eSIM" + "Nu se poate dezactiva cardul eSIM" + "Cardul eSIM nu poate fi dezactivat din cauza unei erori." "Introduceți" "Ați uitat modelul" "Model greșit" @@ -66,7 +68,7 @@ "Desenați modelul" "Introduceți codul PIN al cardului SIM." "Introduceți codul PIN al cardului SIM pentru „%1$s”." - "Dezactivați cardul eSIM pentru a folosi dispozitivul fără serviciu mobil." + "%1$s Dezactivați cardul eSIM pentru a folosi dispozitivul fără serviciu mobil." "Introduceți codul PIN" "Introduceți parola" "Cardul SIM este acum dezactivat. Pentru a continua, introduceți codul PUK. Pentru detalii, contactați operatorul." diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index 1a794ee0a7b4998999fed9f74e47821157f927ea..dbdbf9303554d9c54189f19f0a34b482acc1bbba 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -53,6 +53,8 @@ "Время следующего сигнала будильника: %1$s." "Удалить" "Отключить eSIM" + "Произошла ошибка" + "Не удалось отключить eSIM." "Клавиша ввода" "Забыли графический ключ?" "Неверный графический ключ" @@ -67,7 +69,7 @@ "Введите графический ключ" "Введите PIN-код SIM-карты." "Введите PIN-код SIM-карты \"%1$s\"." - "Чтобы пользоваться устройством без мобильной связи, отключите eSIM." + "%1$s Чтобы пользоваться устройством без мобильной связи, отключите eSIM." "Введите PIN-код" "Введите пароль" "SIM-карта отключена. Чтобы продолжить, введите PUK-код. За подробной информацией обратитесь к оператору связи." diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml index d36e7520b6add26e54ddcdadf601000389971728..a670f16c743e6bda520d8683d93430e15cb7ebcf 100644 --- a/packages/SystemUI/res-keyguard/values-si/strings.xml +++ b/packages/SystemUI/res-keyguard/values-si/strings.xml @@ -53,6 +53,8 @@ "%1$sට ඊළඟ එලාමය සකසා ඇත" "මකන්න" "eSIM අබල කරන්න" + "eSIM අබල කළ නොහැකිය." + "දෝෂයක් හේතුවෙන් eSIM අබල කළ නොහැකිය." "ඇතුල් කරන්න" "රටාව අමතකයි" "වැරදි රටාවකි" @@ -65,7 +67,7 @@ "ඔබගේ රටාව අඳින්න" "SIM PIN ඇතුළු කරන්න" "\"%1$s\" සඳහා SIM PIN ඇතුළු කරන්න" - "ජංගම සේවාවෙන් තොරව උපාංගය භාවිත කිරීමට eSIM අබල කරන්න." + "%1$s ජංගම සේවාවෙන් තොරව උපාංගය භාවිත කිරීමට eSIM අබල කරන්න." "PIN එක ඇතුළු කරන්න" "මුරපදය ඇතුළු කරන්න" "දැන් SIM එක අබල කර ඇත. ඉදිරියට යාමට PUK කේතය යොදන්න. විස්තර සඳහා වාහකයා අමතන්න." diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml index 7e85131783ebe3768d50eb2af4ff4df63e23289c..06acf81d13a7f911d0b5eec107feb235ee8a0abd 100644 --- a/packages/SystemUI/res-keyguard/values-sw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml @@ -53,6 +53,8 @@ "Kengele inayofuata italia saa %1$s" "Futa" "Zima eSIM" + "Imeshindwa kuzima eSIM" + "Hitilafu imetokea wakati wa kuzima eSIM." "Weka" "Umesahau Mchoro" "Mchoro si Sahihi" @@ -65,7 +67,7 @@ "Chora mchoro wako" "Weka PIN ya SIM." "Weka PIN ya SIM ya \"%1$s\"." - "Zima eSIM ili utumie kifaa bila huduma ya vifaa vya mkononi." + "%1$s Zima eSIM ili utumie kifaa bila huduma ya vifaa vya mkononi." "Weka PIN" "Weka Nenosiri" "SIM sasa imefungwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma za mtandao kwa maelezo." diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml index 2ce57a09875c5e504975c7f473c677691f994a12..376c74f293388de9214d2aca9bdfd9ee7c72766a 100644 --- a/packages/SystemUI/res-keyguard/values-ta/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml @@ -53,6 +53,10 @@ "அடுத்த அலாரம் %1$sக்கு அமைக்கப்பட்டுள்ளது" "நீக்கும் பொத்தான்" "இ-சிம்மை முடக்கும்" + + + + "என்டர் பொத்தான்" "பேட்டர்ன் நினைவில்லையா" "தவறான பேட்டர்ன்" @@ -65,7 +69,8 @@ "பேட்டர்னை வரையவும்" "சிம் பின்னை உள்ளிடவும்." "\"%1$s\"க்கான சிம் பின்னை உள்ளிடவும்." - "மொபைல் சேவை இல்லாமல் சாதனத்தைப் பயன்படுத்த, இ-சிம்மை முடக்கவும்." + + "பின்னை உள்ளிடவும்" "கடவுச்சொல்லை உள்ளிடவும்" "சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்." diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index bdee4a3a0b663bca5bdac0d36018b6a536a86e5e..934d6a234ceefee90dc8e6d306300e90333494c8 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -53,6 +53,10 @@ "తర్వాత అలారం %1$sకి సెట్ చేయబడింది" "తొలగించు" "eSIMని నిలిపివేయండి" + + + + "Enter" "నమూనాను మర్చిపోయాను" "ఆకృతి తప్పు" @@ -65,7 +69,8 @@ "మీ నమూనాను గీయండి" "SIM పిన్‌ని నమోదు చేయండి." "\"%1$s\" కోసం SIM పిన్‌ని నమోదు చేయండి." - "మొబైల్ సేవ లేకుండా డివైజ్‌ని ఉపయోగించడం కోసం eSIMని నిలిపివేయండి." + + "పిన్‌ను నమోదు చేయండి" "పాస్‌వర్డ్‌ని నమోదు చేయండి" "ఇప్పుడు SIM నిలిపివేయబడింది. కొనసాగించాలంటే, PUK కోడ్‌ను నమోదు చేయండి. వివరాల కోసం క్యారియర్‌ను సంప్రదించండి." diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml index ca53dfb8fd69b5fdb77be002d40cb412f0a6fb0d..e716ee488434dd18c5ab765d81d4237998a847a2 100644 --- a/packages/SystemUI/res-keyguard/values-tr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml @@ -53,6 +53,10 @@ "Sonraki alarm %1$s olarak ayarlandı" "Delete" "eSIM\'i devre dışı bırak" + + + + "Enter" "Deseni unuttunuz mu?" "Yanlış Desen" @@ -65,7 +69,8 @@ "Deseninizi çizin" "SIM PIN kodunu girin." "\"%1$s\" için SIM PIN kodunu girin." - "Cihazı mobil hizmet olmadan kullanmak için eSIM\'i devre dışı bırakın." + + "PIN\'i girin" "Şifreyi Girin" "SIM kart artık devre dışı bırakıldı. Devam etmek için PUK kodunu girin. Ayrıntılı bilgi için operatörle bağlantı kurun." diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml index 4b79744573d6506db86c52dc6c3e17959af097bb..277b1033e747869781dd4e45d554474df08b08de 100644 --- a/packages/SystemUI/res-keyguard/values-uk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml @@ -53,6 +53,8 @@ "Наступний сигнал: %1$s" "Видалити" "Вимкнути eSIM-карту" + "Не вдається вимкнути eSIM-карту" + "Не вдається вимкнути eSIM-карту через помилку." "Ввести" "Не пам’ятаю ключ" "Неправильний ключ" @@ -67,7 +69,7 @@ "Намалюйте ключ" "Введіть PIN-код SIM-карти." "Введіть PIN-код SIM-карти для оператора \"%1$s\"." - "Вимкнути eSIM-карту, щоб використовувати пристрій без мобільного зв’язку." + "%1$s Вимкніть eSIM-карту, щоб використовувати пристрій без мобільного зв’язку." "Введіть PIN-код" "Введіть пароль" "Зараз SIM-карту вимкнено. Введіть PUK-код, щоб продовжити. Зв’яжіться з оператором, щоб дізнатися більше." diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index cd99c9279890d385245725798a184d91a81e9b6a..28a52c0eb613f35cb9ff31ccf5c3597c0fe5f1c9 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -53,6 +53,10 @@ "اگلا الارم %1$s کیلئے سیٹ ہے" "حذف کریں" "‏eSIM غیر فعال کریں" + + + + "درج کریں" "پیٹرن بھول گئے" "غلط پیٹرن" @@ -65,7 +69,8 @@ "اپنا پیٹرن ڈرا کریں" "‏SIM PIN درج کریں۔" "‏\"%1$s\" کیلئے SIM PIN درج کریں۔" - "‏موبائل سروس کے بغیر آلہ کا استعمال کرنے کیلئے eSIM غیر فعال کریں۔" + + "‏PIN درج کریں" "پاسورڈ درج کریں" "‏SIM اب غیر فعال ہوگیا ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔" diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml index 204bb8b0b7376a7a7df08e3cf5c01c6152746a75..3272cb28aa5b19d0f2aaa751e5988eaa15e058c7 100644 --- a/packages/SystemUI/res-keyguard/values-uz/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml @@ -53,6 +53,10 @@ "Signal %1$s da chalinadi." "O‘chirib tashlash" "eSIMni faolsizlantirish" + + + + "Enter tugmasi" "Grafik kalit esimdan chiqdi" "Grafik kalit xato" @@ -65,7 +69,8 @@ "Grafik kalit chizing" "SIM karta PIN kodini kiriting." "“%1$s” SIM kartasi PIN kodini kiriting." - "Qurilmadan mobil xizmatlarsiz foydalanish uchun eSIMni faolsizlantiring." + + "PIN kodni kiriting" "Parol kiriting" "SIM karta hozir o‘chirilgan. Davom etish uchun PUK kodni kiriting. Batafsil axborot olish uchun tarmoq operatori bilan bog‘laning." diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index 45ab5938a28628fea227b9b1625fa8eb8602d33d..ee234cc916341e8b78c3d3dc58e738eb435e1a07 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -53,6 +53,10 @@ "已設定下一個鬧鐘時間:%1$s" "刪除" "停用 eSIM 卡" + + + + "Enter 鍵" "忘記解鎖圖案" "解鎖圖案錯誤" @@ -65,7 +69,8 @@ "畫出解鎖圖案" "輸入 SIM 卡的 PIN 碼。" "輸入「%1$s」SIM 卡的 PIN 碼。" - "停用 eSIM 卡即可在沒有行動服務的情況下使用裝置。" + + "輸入 PIN 碼" "輸入密碼" "SIM 卡已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。" diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml index 2329320bdf30b25aabea7fe9cdeddcdadedb4ffc..2415bf38101dc8378152696a2e9c708c8fb56137 100644 --- a/packages/SystemUI/res-keyguard/values-zu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml @@ -53,6 +53,8 @@ "I-alamu elandelayo esethelwe i-%1$s" "Susa" "Khubaza i-eSIM" + "Ayikwazi ukukhubaz i-eSIM" + "I-eSIM ayikwakhi ukukhutshazwa ngenxa yephutha." "Faka" "Ukhohlwe iphethini?" "Iphatheni engalungile" @@ -65,7 +67,7 @@ "Dweba iphethini yakho" "Faka i-PIN ye-SIM" "Faka i-PIN ye-SIM ye-\"%1$s\"" - "Khubaza i-eSIM ukusebenzisa idivayisi ngaphandle kwesevisi yeselula." + "%1$s Khubaza i-eSIM ukuze usebenzise le sevisi yeselula." "Faka iphinikhodi" "Faka iphasiwedi" "I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Xhumana nenkampani yenethiwekhi ngemininingwane." diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 3a41681f53e95b1df499999e20186d9f9bc8b379..8a48e7bd935448f8759a4551530d3221cb07d1c5 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -124,6 +124,10 @@ Delete Disable eSIM + + Can\u2019t disable eSIM + + The eSIM can\u2019t be disabled due to an error. Enter @@ -146,8 +150,8 @@ Enter SIM PIN. Enter SIM PIN for \"%1$s\". - - Disable eSIM to use device without mobile service. + + %1$s Disable eSIM to use device without mobile service. Enter PIN diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..551c67258e3acf5c3a2718401f5440f8b0edabca Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..aee2cf25e9432c4f1cc4b10827a862dd1aa3a7e5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..28bdabb4191161c591b3ad4c3d76caab098c2ed9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png new file mode 100755 index 0000000000000000000000000000000000000000..a6d46728e2a0bc13357ec42778d944a30e0d6167 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png new file mode 100755 index 0000000000000000000000000000000000000000..c9a6c8e60edadf75ea3e616ed24687148bccc10f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png new file mode 100755 index 0000000000000000000000000000000000000000..83aa3c74317c8126f8ac8d724cd7627738230f08 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_hp.png new file mode 100755 index 0000000000000000000000000000000000000000..7f86ac3d989de68900a09e7b42cfcf412932911e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_hp.png new file mode 100755 index 0000000000000000000000000000000000000000..46dc18bbcc0618c3a2ea022a597ed79969bc502b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..818e29230fc3b5ede6e6a8bab18462cce7a0c062 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..95866b12e6114233419d7a767a7cb9a6e6082156 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..1aea612799086c9eaa951b7fc46dd0bd9bceee0f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_4g_plus.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_4g_plus.png new file mode 100755 index 0000000000000000000000000000000000000000..6412f337a3209ef823138811d8d7ef2be9a357b7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_4g_plus.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_e.png new file mode 100644 index 0000000000000000000000000000000000000000..016b30b079acc6fbbed7da2324bb87cc389f4078 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ec672eb118e554d831d3c4785d9670f4831e3d9c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_h.png new file mode 100644 index 0000000000000000000000000000000000000000..27bab73745ae80c1cec9e5be9370c0b5535f3720 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_idle_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..66fb60e90364dfec4e3dd567124a722d365ba9be Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..07ea499fb741cd9e72dc4e2f402305f688c27c32 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..879c703f7b1f931614cfd0998a7a0248f28ebe13 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g_plus.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g_plus.png new file mode 100755 index 0000000000000000000000000000000000000000..239bcf72813dc3091eb6e47750ef45824411e45f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g_plus.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png new file mode 100644 index 0000000000000000000000000000000000000000..e39767a6dad1ea5df1635066fadd6dd7bfbba68e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png new file mode 100644 index 0000000000000000000000000000000000000000..47c1fca332372074967abcd7b30d334d39f0adc4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ac80dceeca9f84bee619d3c3eaab3ef420fe8d60 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..c5edf2c19e3f6601e3652d2cf59587149fa3372d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g_plus.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g_plus.png new file mode 100755 index 0000000000000000000000000000000000000000..7ccb9dcae5260a4552461fbe92b7ff67b646f919 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g_plus.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef47018993e97e143e6d965e05556038381d51b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ed02984ef85c950a733aaabd4c070e58bf8dc28d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..f88091b59ffa5b50fccb9b3dd191101b8529c429 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..95bb3cd92510176e8beb5ff0bb4d566ca4924f92 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_g.png new file mode 100644 index 0000000000000000000000000000000000000000..31b926bd2f04962eacb1aa729a88b7ea4bbf8982 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inout_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee5b08ed66098342239e1ad7fff7de5b995c235 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..cac78027f5748a19e1eb635bb4c5884c237757d3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ddf88bedb964135e532186c00b1261a08e3180b1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g_plus.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g_plus.png new file mode 100755 index 0000000000000000000000000000000000000000..214dd07841ff97490fd0e49e9b8d295d0a165032 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g_plus.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png new file mode 100644 index 0000000000000000000000000000000000000000..df6e1952b1caeab5680b8b74368acdb85fb2adb5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png new file mode 100644 index 0000000000000000000000000000000000000000..4a2f867ece4f1034da24a8a3a7c157cb37a2a79d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png new file mode 100644 index 0000000000000000000000000000000000000000..2b4628fcf78b941b265b7c91aad8cb4119a9d018 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim1_new.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim1_new.png new file mode 100644 index 0000000000000000000000000000000000000000..16f8254aec38c7afde233c23c9bc5af36d25e821 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim1_new.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim2_new.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim2_new.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ddcd7225df35d91a0700453be74911a432cc5d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim2_new.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fbcf293f3a018f1ef0dfaeb26198f08c2f029dc8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim_1.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..453cffb3ea7e558901d3e29f1e1f6f412dc1c427 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ec1a23e4efa542e9277b153c67c7eaf772718de9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..a43d8830f3684f0e9c40e5677444d88c69e78440 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..8b2c611e9da0dfa00a11f67b64aa79a235899a29 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..badc93d0241563800f8cfa76d7a1a465802cbdd1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..af716004b0b327c238a2d032f648c54a172b2d7e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..24be33636680b5ce45b9b0ed65c39373fed1796f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3e5bb799fdabbfa63e90db6a47248f5ac3a6863e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..a1102d66787d4f736c4f25bd14700522c375165b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..cee81b37c0bf722208ace1d9b872dbd23f697661 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..453cffb3ea7e558901d3e29f1e1f6f412dc1c427 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..76bf51c52e85392b23862db1caf3d4d59bf9f9b7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..a43d8830f3684f0e9c40e5677444d88c69e78440 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..8b2c611e9da0dfa00a11f67b64aa79a235899a29 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..8f536d9b81adf905f36f2a69f4833fed161863e3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..af716004b0b327c238a2d032f648c54a172b2d7e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..222a65ff1bdcfd9550c76d44e28295a8a4a0f98a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3e5bb799fdabbfa63e90db6a47248f5ac3a6863e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..a1102d66787d4f736c4f25bd14700522c375165b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..42c2b3c1fa2af6baa52c1e3158689fd780888d16 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..6a34d7c0d516938897c030732979cd4ecbafe550 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..4dc30ee90cc92e89908cfdcee20b5b4f2f7d5073 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6ff777ab28ef1128521e33d834ac7e51396b7a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..477dd57aa48560c798a2a9a55c8904802dd44f0b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..94dfff0c827e51327cc25b2aadc68b71d519c055 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..d1bfb5e167e69e8575426b767209199268bb05a8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..40c09721319c8d57e4b68df0bc7f72cf27abc4da Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..52c01e00a08e7fab6adc63c08c0659f1b555da2c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..13e1dadf816e82070e8e0e9f733d5bc77814d665 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ab40c2f2d87d96cf31f249c38fa88f92b2c4079e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f9adf5e46790d5ed5bfb842171fcba2501ff134d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..74c614ccf5e0bcfefff162aa5b5d160ca36ce9de Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..5cb8c27f4b88c4aa8fef907a53e2a6eba83d1ac5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..a47d44dcd08e6ae7855e476b5ae0895f7aec7532 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..3130da3c994b6a1cd8c7b4f17fa591075d79b10b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..70b639a7fb091916aff3b40fdb046f15753f38fd Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..8a267f0112286108e98689460013a5b9c14c60f2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..5ed531067348eccf4558e9b7fc3661c0a4dc4e45 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..7f919e952c6cdc5e6c545141222790c2108b1002 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b3f07ba8725ee1be911731abd7a2e1a39eae5906 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..3de1d955c2a20ea66f8a02658aa462a6211e5888 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..046714bdd11d918c14cd6fdafb92e45418b1c9ca Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..83305772e3bcc924824947c1d03d7bd343d18fe8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..261644a5eb7e046f5d94cabb4ea81ad59c2247d3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..acf7cfe57ec80c4bd72ea452b2775bfb889750d2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f84cd0a40b03f40d6f5dfbf41e851bac6b175869 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..55f57d6fa88a726d3ee06cb87abdb90e625574a0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..0f67463aea94cc9e7433a9ffbb8011e9ffe111d6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab998bd2e3ed3cf947263f3d8e0eddd758676e3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..659efb4877213fcfa126b873baeaf573ded428ea Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f7bfe98fd045c7b9f94f77ce11a6d57dbe9b0b3b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..2135915a2d4fbb084d69fd66fa6f935521bb4db9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..69e649f3571694e65a7968872c3952988ab64e81 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..30fc05b20695a6cbed54e0adb322c1ab8077ca61 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..aed81791eee42765a6f83575b7ac62613b5eb197 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..617af25ae1a1cc6342b030cf6682798695532928 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..33c4abdc300f23cd2985a3a33b25b369bbc391ad Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..6eee46540da70ed863b49717364c3e85ef2d20d1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..4fea813b1b1ddff54909ba8e1204f7bcef4468a4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..e76c53f7a368abbaa916b761a297c5c4a80fad82 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7bc97f16285781b38c391451465e456f667ac1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..97120a9efe77e22adb0f69756b0d10c1807ea425 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..7e1c0618d68dfe3b37a2bcc5885335e78905a358 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..2992e5c4156f52c6c6629a1fab221f18be16e5c4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb1c2c10184bac9c75c50296e666c601522be8c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..e98751c7527a5ca68b2e3a117d0216e9588a43ee Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..f3419fd7b89cb26d68b92278a54ce696f63fc7d4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..262eda94bb033581bb5608254eca21128f095d91 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..cda6d0a06818ce540daa98f6e5825f68ecc5cd9f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a0a601d2ba0ea9e0834b1efc122078b29f0cd9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..e9fd96af3c0a4ec3d7e5ed527a980cb5430a5f66 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ca418cae77e16b6c13081d59343c549329241df2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3a2152119d93875c1e8caecb5997be5cbd4bf91b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3f81c016454444e42fe934cc84f47ad3520a54 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..a9a71911a32917b71b928206242c7598295986e3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..44284d83c0c2c82ac24b603b13e859cc1fd888ff Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..a8c6c32031dc955f286218bb237d2d712cc12900 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..429253844f30e379f52b03a9df1f7bf9a9cb7943 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..65c0e2da46ec5a3d0df8d3f2f0ce016909022e7c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..bdf6790e11c5652676ac08b56398021baeac8b14 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..7993fc24bcf7db4a43e665d7cba37730184fc19a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..849796a846dc24a3f1d2a466b2f398ffa8fbadb5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..0eae5efc86894a6860a0acf04bb50f2c6bbe4ed1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e7894dc632ade35cd179e0448fecb56a683bc836 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..0d55f93cbfc2cc89fdb75fd589713397d81569d0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..a21eb1d7b803da70ad6f6634f254ae284172a357 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..012eb8a363780b38225ec39a25a2973c6dc55fcf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..cd37c329283952536ad91da42ae7852aabd2c13f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..1d77c307aa651b71387790f6e8323ac83dca9f60 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..978c284c55943a28f60af4912d9d7c3d28b3906c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..aba3a69d2c63df823cce48ef24d494c1036bc5a9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee0c634990073d165d5e7c67be6662dbcc78dc2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ad17c6115e72cf506eecb5e9ce0fb7acfae17762 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..9d710b1a94ef87e4535fc1415c3dd66adee8eaa1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..73c369ff46a463012130d66d2f718e247bfbfbf4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..06416c3a309eea9ca59790a206e2947fb1f91f35 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..247978347aeada8f28a8517eb81192babe6a33bf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..61f6a884628b16b4108dce5c2fcc98e4b955cedc Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e4441e38caad0e9bf8c5160297dcda7c4586a269 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..8503fbfa901c4e1ec3a8c4f3050acd0807553930 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..e75b98f3a1fc85965d60f9457f3307a71d980a79 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..e75b98f3a1fc85965d60f9457f3307a71d980a79 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..5b074682bab83d16f384f037114d49c50afb7b22 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only.png new file mode 100644 index 0000000000000000000000000000000000000000..b93b0a02528efe7ab884af0ae696120399b07dbb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..b93b0a02528efe7ab884af0ae696120399b07dbb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..5103f77214884dd3f2569b545c61917bf9b7badf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..5103f77214884dd3f2569b545c61917bf9b7badf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_only_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..5b074682bab83d16f384f037114d49c50afb7b22 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_1x_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..79aabb75cfa843de4fe3c96729b82e523fdd1a82 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..750b8db42c7af8ee27b088e8e9c5f21fd1d452b9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..e9236b050d57f7a7e47e380ce39e58e472083aec Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..3cf236d8b463446c3e7368532fad48089e9921e3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..9550ab5ad4bd72d00c6624081f65738ec5c344f7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..6339bc37783fab966741930c0e91256d230897bb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_2g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..e11d0b1dc8f5e422c7876d484b280e2bd780e459 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..bb68877e28e52baa7881c8f556b67fad940a4f12 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..bb68877e28e52baa7881c8f556b67fad940a4f12 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..917f6cf9e8a8c27c6db5aca531c1283f258e3bfb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..917f6cf9e8a8c27c6db5aca531c1283f258e3bfb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..e11d0b1dc8f5e422c7876d484b280e2bd780e459 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..bd76da867e3d5b0110e7514f69387eaa759ffd8e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..bd76da867e3d5b0110e7514f69387eaa759ffd8e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_3g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..f5f74f925a2d880bf99fbfd822283fc91a449c13 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..a33ac2ee62810fef4aff5d1b4f7dfc0cf2d11b29 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..f572200aa565bdbf59809f34d17134c9c48e8755 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..44736da6935766649c4e5f5a31ed2df593625fa9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c09a1c023328f6b1046795b371a22824919e8b12 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..d5c25b3d551c03167d905aef44b92a4ac35e6948 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..fb6cd9d2fd6b62c4a20463daf772118c58442045 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..fb6cd9d2fd6b62c4a20463daf772118c58442045 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e.png new file mode 100755 index 0000000000000000000000000000000000000000..651b1ad07875b8257a070ab86dbfe9ca53850853 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..71059aa310e8161cb13da0bade4b31c82ddbd578 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..ac814fdaea4e546217dd1668130677245e28e843 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..e8826aa61d53533160140870ac087b28c16c551c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..0fd09d745daa99e25b5fc666548e9c11851859e1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..8276cc945ba7c9ef3812f634fbce340cf8583d4b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..68c871a8c0f75a2812bc113b4e4fa8f95a24739b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..189c78ab08b5d16081226ec339efc1d78726e4bf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f889b570ec6b4309d09150f967a93fd7034547 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..11e32c07f680de52976f509b5cbf5447bfc34e19 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..15edf6703425cde443e0707afd9f4568907a6910 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e17d4580a2ef2f1db990dea62bf1bb0b5439b644 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..36b847ea7362c182cf1f3c5b1b998cb6fc04f914 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..7e43f762194a913dc4b7ca879ab1aed0f58636bb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..63fe13d87f03ecbdbedcb8fb4884cc8f424aba35 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3145814c2b41864de1f8e2773b7511b7ee4f006a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..3145814c2b41864de1f8e2773b7511b7ee4f006a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..106e546b75f90ac037ce2c73ddfcdacceb3431e1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..106e546b75f90ac037ce2c73ddfcdacceb3431e1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_gsm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..2a56bce6fd5d96bf324f749567107e65b7a8255f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_gsm.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_gsm_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..415658bdb5298320a1f3243e875ec2c80f921243 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..da941c8e082550f3eb601636a9856b7f1a7fa564 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..8276cc945ba7c9ef3812f634fbce340cf8583d4b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..80dcbe27916cc0a32f43779f2fb9839531da4c7e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..189c78ab08b5d16081226ec339efc1d78726e4bf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f889b570ec6b4309d09150f967a93fd7034547 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..abd7f922f1b5a802f1cdc0a732d0d2cf2ebeb97a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..15edf6703425cde443e0707afd9f4568907a6910 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..386a1aceddba49608eaa684ebe8100fda889397e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..36b847ea7362c182cf1f3c5b1b998cb6fc04f914 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..7e43f762194a913dc4b7ca879ab1aed0f58636bb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..c9daf031a153eb85d9c3350d06653c392afc4053 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb12346aad4b4b7c845624b90176cc470b1e61a5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..5714b95864ef2113dc5e7c02ffcfba1807b15e77 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..5a8271c556bba2e00031495aaf8505c13cc1957d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only.png new file mode 100644 index 0000000000000000000000000000000000000000..e40825e27293c78e63d3a0077b697c0d59efb07d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..a69eca45851d9f3c5670c9bc52aa1334cc44b2b8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..022ec4a60a17a247309c96e5ad9d3c9a6d8b0758 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..1bbf43224f1287604854359870e6533fb91ff484 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_only_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..9e4ce76e1ed3a79790adc7b91b142ecdffb864ca Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_1x_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..87844527441fe54b092fd4594f5b5aaf1ba049fb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..8bd678690122528e73325e2366bae20e502a203f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..38f5704395038092eccdef7652ac85a6e1366195 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..48f1af95c79532a8951394c54f8aff48cf2299b5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..d82154934f1d054d87c85d565559a3b7f25a7800 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..e201a00f7fbb22a6b9ecce3a1dc63e2ab6f1c795 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_2g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..368ada3b135d72313bd572e9d068cfab6856792d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..4bd8efb16795c26a03064b9aa8b24b04ee92ef85 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..f36be76852489ba45ef2c55bcfcf43dbbf2eafb6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..55a7b405c474e47e62c27c837b6553e58bd6f72b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..daed7823bb8c5c79d1d89dea9f6048a44d4ab410 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..bf644deadb55167ffd7add5891604f0183f28daa Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..a0004f042b750811c8bbcb77c971756210ea6e4a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..eed77ab60a4ba03872da30086b7e22aa2d0f142f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_3g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..c7d855e15c6c53987509d073675e64d2352519f4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..42ba3f9b60469822038422ce3ee831aeecd3b858 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..009fd7d365e33916ed86b3b45a01e922c050d7c0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..d58b9a3601dd1669656c422e2128815315b45487 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..3ae325b4330096a82e0831c7ae7977a3298c437e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..4ca959f74c3fb2cce58d79df974e57ec614a0ee4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..cce1bb4189468046068cc5856b04b8a861fe4b4e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..41791cb361da5d30e8da604ec8ac70f5f99f318c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e.png new file mode 100755 index 0000000000000000000000000000000000000000..660842f7d60890adf30ecf135d536e09b963d3c2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..da72330b2150c7ada94974cd25f8bb80a5024b97 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..be05ea644bb591e2752df66a5822ab06869812d9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..cb3ec07f5158d78d18c1599e04349ef55402bec0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..fe7189308ed4ff1a523949c14b8cdd0aea701439 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ec4e72bd3c23f4f01381667ccc63056b6ec63f74 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..f4327b89dfdeaff99a521ca20d8f22da04db2499 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3b4e528bcdd4766c3c27ed69ac76459ef9aee516 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..939ae38a33518e6aba5949070cfc0cb80a5294df Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb531ea99777ccee2d9a8bcc2d6408b7eb4ffc1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..3ee5d1ee39b9366e2e03b52ee29255cdf4188425 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ca4769a084f4713e049f51f9b1ca1cde65c45679 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..6bc60e83dbd8383ac10d8abb96e5069522bd83a3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..1d4949dddefe57b62f18a3a5cb1a3b070e32ce10 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..950b936ebedcc58210d6b53b84325000ae6d1496 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..d05e974e681c6f7684928cabf758341326b7e83b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..f0656f397cb52078acc750b443b1772a3a78aab5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..49dee6d3953a553911e17d1373775de9a488ea75 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..dab2dc7f3b208f424f89201b334e63bdcbe44c23 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_gsm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..16286326c39458b23c495b85d0a032cc2962a72a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_gsm.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_gsm_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..7526746b32c701ecfc19d2b520812f797c062675 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..fd8d2f28dc003e6f56a4dcc47c69b564cc309d60 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..8771fa083f9e648156c9797cbee09f48db2f7359 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..c8bdad77d8a4412e7675fbcc71a9f0607d975629 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..57038ec38a2fd834823d0a40106b00d4a2fab69e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..9f6a51439045ea76a5c7e9ca5e7ca1e85ed66129 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..3e27781a359c3172eeb7fba5922a19eb3124fcda Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ce788e603aaa654e2abe7e1e4588a4c55cc9fc66 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e917bfda3b91415455e92442e057b6bdfde2dcf7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..99edb6a0fb8732a3094f8b03cc1540495302f0c0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..9660faee2d935d8fca21d714022fecea90ba55a2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..6eaa344719bc2f686b7396819a994d2803d5ec4c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_in.png new file mode 100644 index 0000000000000000000000000000000000000000..6a16578f2bf72b91ca687d2c8d72a9177571488c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..172379308da5e2d3bee0ad8774d85073e6a682a1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_no.png new file mode 100644 index 0000000000000000000000000000000000000000..893033adea56923095f9afbb330f291fb725035a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_out.png new file mode 100644 index 0000000000000000000000000000000000000000..bef52117c65cb7542bac3dcdb1816f36a39dff0f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..f5b898edfef86ccee6b72d69bb3addcf8c911e40 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..363a1a93ceb494f917656df28633d48f2bb162e2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..acd014d3e6159aca7021bb377e665f8d954337cd Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only.png new file mode 100644 index 0000000000000000000000000000000000000000..825eef48e8c2014f95dc431978ed91accf24c069 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..0696fea9e150b4f95312e89ce573b40fe0455185 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..887c6c6e757b995dcd8de0bbea5d173e213f6bbb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..892168722b730ffa2314b92f1da77b96f22114fc Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_only_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..ce372b73003f2e13067cfcbf652a4a84d62367b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_1x_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..7f18a2e1ff75115f931a4a4b9e9f2ed5c39027a7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..668425518b4200d58fc9031a9371e066a73722df Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b7c808aabf1bb9d85b51f24bf19afd5f4def6f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..37d6b53951d0b28403b8029dff7a00f2a0e09978 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b971b3c5a9c5c11001799963ef8740ac1f891ce3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..5f41237698bfb1fa0ec9340b835a61b8485d4d5b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_2g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..e3271675e69f1fc4b2e0d55edeb141c0a4118b37 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..9cdff01612cbc389dce368845df201198beb14d8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..b7b21d388013102b3898b797a133ec7abeefaaaa Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..05068b2938e2dabdd35c18fea3a933e7ac301e25 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..c352e4fcc28b48bb7423017d276082d01ae3848e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..4f22987e770f1d95042f1abcfe8fa2480fd31c9d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..b5760f04ca3d58f844666f6ce1b7730a331b23b7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..ee1b26f5d266b5dd42dfcc9edff7377a8586b93f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_3g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..2d574bf3031796bbe9dcb53b24d065841f0a8a26 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..588b5a99871ca53da00acb9f52325c8b83782993 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..3cb4ee0965124c04b8c6cc8b8c31d1e674737d23 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..4ea7ff2e20f20302904b64027ad29f8ac078c3b3 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..e4e842c4e7f052614ff7842ec9fb3d92d4d89912 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..758fc22d512b87c947132687ea42aa5c4f55abf6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..a1f78ef27f6e9b18cc25076a3d432da798d7578e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..74d45b6bc0b32d2cabc76b67ab630c318f027026 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e.png new file mode 100755 index 0000000000000000000000000000000000000000..f314c1508f98e177e70ede55357db87b1663a941 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..b5cbd0939190d29e17173836372864a334e1ced8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..20c7362c41d5cb28e1acd2086a4535d0bc5bc6d8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..aee5871b60a2e8264de1e190cbcfb753cecdb586 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..a6c61fff5df19327b104048d5eb4df3bccc61d2e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..0ca7ff3b76d89fa45a5c2efa558ba64e41fdbf8b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..58be4c92698a1e471e550ad37fbe707505d48839 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..cf39dd5499d88b42286964f301424dbf5beb5f3e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e5a54613fa100d56f9ede591fbb205e3bd270c79 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..55949918caa9a13f30e3cee66a8eefa5e0fa302f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..d90ca3560dcb66f4f1abcfe995b96a397f658f51 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..deea9b42f652e377b816cfe8cf09c2115fc2f274 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3e5de5bf1b91b16f40dba74e3c6a5c81b10c1d53 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..f30da37b633015ab6f8b1fccb390ab42d4288990 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..7af7fe712c14cf6d805ddba3d8740e22e303aa7b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..54a55c61f6043b55744645d2184b90805f94395f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..91cbc6772ff3c7d6bb5bb7040d87fb40439d525e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..4820651befe12b6460702b7ceeaadfdad355eb18 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..736d41cd7b6915c1777a9d806ddabaab107bc88d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_gsm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..2b82165b65cba8324f41db01112b80c90d21c954 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_gsm.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_gsm_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..91aba685b41efa82bb907ad631ed4cf81519231a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..3b4aaa1c67ffd2a98e6082d5fb12a5213d7978c1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..6c20e8bc2a5f8ce5d714ad9e0be22bb378c414a2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e4fa22ed04121dabedeb7eef5ee0688f0c1298e6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..8f0c5f5abae20deeb78a0993883650494454e7a4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..dd0ee243be20cd8857f0375c2abc43826b267cc4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..5a90d1fcd38aea36bf174fc14860a55b18dc78ba Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..51074bee3bc58e7f0dde96feffb43fe41fa22653 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bf393a4e66c362b593676d43629f57f29d27b6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..31e08943df2320d2a3f67a29042cec352d8239ae Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..330aa082eaf4c6b6ceed7fffda35e8c9484c6287 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ed316f050a09ddea84f3dbb944f1e522e7142f4f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_in.png new file mode 100644 index 0000000000000000000000000000000000000000..bce78accc43ca46dd10198af24de117a58ba0860 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..3a90366fe4c9f42b4433480bcd4db90c176c46e9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_no.png new file mode 100644 index 0000000000000000000000000000000000000000..49e4f0791f1b253e7984e2fa9141ef1ee58410bb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_out.png new file mode 100644 index 0000000000000000000000000000000000000000..9e45681b6fd1562232b1c2614b148b27c50fb3ce Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2g_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..a7d7d75a7e0d25c144ce8e19a3e5ba25049d1758 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..7b34688067b456436435809de3e1b875469483e4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..08940ce6ee0acdf4103ec0ec766d1912cfc0a44f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only.png new file mode 100644 index 0000000000000000000000000000000000000000..ec12d28076906b01dd81d5d720b986f0e32e21dc Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..5235b7dc95a05cea1f9e1ce2d2d37dd52aa7b360 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..6f5beb47c844ccecccdd021ef4c3cf05c3f4fc8a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c6f29914a287852e8b1b7e086f8c574e569fdd Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_only_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..1362fa3d33b0c1baaeaecb3ffb27c4178429da97 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_1x_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..53552e4e4da36b7af72053f2673402b2bc74a523 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e8eb4cb02718bca1ad951467b9630d06f886c4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..42915954b8f2493a5afa97548abaf34f04037bff Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..19c9a3deca3515885d3bb136c4d80623885f3276 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..6119135f0755c42ff0ed96888b71a757fb9156c1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..6d08ace1312872138348f1ee285184ad755a4c57 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_2g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ddb640d8c50390922141ea44818ad02d12b8f4b5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..39102034e71b83287c30c73556373c4b1e857a8e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..b6b440b202ea1106982b49f7c86c8bafc4976e12 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce09ddf38ad555c42f46a3db31a66c5c163ea85 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..9a0aabfa837e0ace705e625cf0bd72af4201129f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..fd571a06ecc578f75c5cab6b5f3d7cc1bc47e31e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..94c60c3c97472c2f430a1176c064c3295f05abf9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..9d18bf7d5ead6167542a8ab5bf8bcb772b9eff0d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_3g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..5090082386b290c5de156b22bf9c9752ba22c639 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..112011bc4cf930613ade18ec3f72a1ffe646f004 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..34d6635ada86fe79e0b9cc6763c994c85194973a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..7334cb6f067c55396cd6c0ef7d576ca9c7cf6b1e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c6e4917bc740476500d303694406dbe27fc1d745 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..5eaae02615746b9007dd8ab5c515c7d17a4426b2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..ca4db23989ffbae112bf9905d3ab7aa236f0cb8a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..135a41287bc46fdbc93563eefd1c715433dbf621 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e.png new file mode 100755 index 0000000000000000000000000000000000000000..9ea742c22b7714c7ea6deed2bc648a6fa1f273f4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..d708edc2a9b19a78489cf0e3bed6cc69ac15a4eb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..6ffb0328010dc9a1d7026b904309d8eb87a80591 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..61c7e2aefa90c8a3d5c2b95a57434a1a2ca7eaa4 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..ba4a9d9b6c94c0609dd1eba39dd4cd3f0d45f3ef Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..b5e83d4ed6615e8065f311830410495079f8dfa9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e49c37ca41baaec9d16fd9398b257637b0599855 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..2e0fd9abe89e843b53e825b40ca0210764b5fa8c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..d77d3b653cb4bc4c180d6305d693fea105da965a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..52e9bb855a0d3d98a77926d094a9d4d62bd11cb9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab6e83577c56be76369776cf66c428e53255561 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e4ea116cd56f730522913775d4251e3ed0397a40 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..e9e8737e29357599150887f1a6a506021d875f31 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..550e4249a0d208f4e3d9e1b615d2c4a15577476b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..65d87bfb09376da9965d7850784dce05313b3f79 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g.png new file mode 100644 index 0000000000000000000000000000000000000000..05f62dc521a9916a6bb7d67bfe63e3451fcac1f7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..5a3e1fe26e1316422be22ee0356716fff8203b6f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..9fb62093db768538dfcdf631adf9dd7a62e8e115 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..02e605995094b83e325b2d1813a851b0dec7ffa1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_gsm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..84ae508b22e680d3d93388cf6051489fdba43149 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_gsm.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_gsm_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..a141e80647603abea446031824f45107132d6a49 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..873a317c1631b993718b0bcd98bae6c625b15aa6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..79964b37e713190996bf846bae17443e07112f80 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..1efc1e64b07f9ce94cff9c839b8266fe35b81597 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..1238d36c40f11e04663928a1835dead58ec3d056 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..128e994d5b24f490d9646c0e2c1b28b180a403b9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..d737b59d12f7a85e95e5651a83e306035babd2cf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..596d4c767d3353bd10cf2da1dcb70565bfa95181 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..10959856c7445bad8bc2a554992d88b94df3232e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..fb62ca99f6a8b52fdf705b87a8833ad97c91c8d7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..edc3d67d6f15bc518e27577be6d61928c68c0354 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..7da7832cde779d9e3ed45052ab4f852750f5112d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_in.png new file mode 100755 index 0000000000000000000000000000000000000000..fe25c2cc48c43a5d2a08dce581fba9c75be05d10 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_inout.png new file mode 100755 index 0000000000000000000000000000000000000000..316de0532e88fc94412fa76e04fc6173ce20624b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_no.png new file mode 100755 index 0000000000000000000000000000000000000000..5e6b81797af4ca4a5ff82368cfdd4b0cb513947e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_out.png new file mode 100755 index 0000000000000000000000000000000000000000..f001a1163f022fcfefcf4a3d7687833b6e145559 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x.png new file mode 100644 index 0000000000000000000000000000000000000000..bf9cbf7b5387d4c002d404a0323f58c30a754844 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d6f503168257e5f11997970ed153a5ccbd9408 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..3421cfa75e0fdf5affba4bb513fe50a2267566eb Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only.png new file mode 100644 index 0000000000000000000000000000000000000000..f9a950825e78ee1d19dd33d9e0dd7fb056822dac Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..6a2752742d5034eb7280c448b1a51d6ecf1bedfd Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..6c8fcfd9ae6b420444ff4994aeb9de764039183f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..b5ab01b5998df30a445a431739d38b2c577a0eb0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_only_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..633e933d328fea44d70d5578bddd0821b464dee0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_1x_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..29d6f9d87807383333430401dc8309846f46d7d0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..761685de02e0555b8e30fb9efa70f62c0369e695 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..7f37ccfd2d1a7ae105fcd2387af2c5e5ddca780c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..dbde94f46b239457483e4dcbffa0d8684fb9f796 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..77bf21f65f329bf22ff1302d975c10597b3255f5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..1f4076cb10529dd723684fcfa1c891dc6600fd72 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_2g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..df37519963f44271c6abd01b0bbb55bba0935e39 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default.png new file mode 100644 index 0000000000000000000000000000000000000000..a203298dd2773b00b8032ca8a2fc90e5f2610701 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..caa4a4dbabc5a68ba01c094a907b9789c0f66cf9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..d4c907ebe51200b82df698057504d475f4fd7e52 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..43fe7197fd622c43f272248e36aa77035ece7a64 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..12be96ae6d236baf752ea35fe032b07507cc80e5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..69bc10346f26378e3ffd7fc530323fdae3be9656 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..5c5863d30513ba0aee42887cff688befd828a57a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_3g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..a3812250bd4747fe1e3730728579fddeb7a44d7f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..b3df2c9787e3605243fdbc971b0b31f1797c6e14 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..468c0f768638df1d53cdd2fca3159d4d2b964f5b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..7332ddf73a64337466bcbce4975d704adad16a24 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..dcce91261c4a350e05684972d9a25d0251dae11a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..6d4f3578d4e1417155c8fab16cec815a4f4f9c72 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_default_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..76a1301f54ce6023faac1153448dfe88f90ca0d0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_default_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..03ff3b65e186ce808332fbd0f79075b25bd6a9cf Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e.png new file mode 100755 index 0000000000000000000000000000000000000000..7d5bbfd8c5cde0772b0e357c49dcd97728279e14 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..c6657fb73fc06547bfdce34e2e7314a0576edcde Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c1e71a57cd5b045e79df8cd806eddde775d312d8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..64485e5519e6c020deb2e72f2377c7e88e41f8e8 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..79c2ec16a29dd469b8d089730b043d6b51dfbf83 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..76fd9895601bf646508e6b5b4f3e08c02532ce7b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd8a689347fa9a4fe7292fd4164220da1bddf22 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ffb5d5033db3388085dce97b09529197be2fbff9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..f1a36a323e159f74bc043a44460958aaefe5c6d6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..d33b99b1ccec7abf72b5c3292a5b32c571367673 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a662182c392e0fa96f5de74b193fc05ec1940c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..df1395d598235f35a40d0dae97ad07f2032ecadd Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..36f7b33758d31c4e2bca403fe9a0ad1726fe3a5e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..07d5e2eb110d8634002690ba44bfd1c4fdfbe809 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..51ed57e54f94e9cccf00345c5d2f61087009eaad Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce7eeb6fb4b7fc43e9438e587e794f0eb083b2e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..abc5155fc94e626320c02a39f71919b7fcfb2898 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_fully_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_fully_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..4665f0155fe27f6562942521dc67fc217afd5153 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_roam.png new file mode 100644 index 0000000000000000000000000000000000000000..4c496a7e4b93c3b685c52864ca554ac85658e098 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_gsm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..eaa6a534c26d45c511640c295440fceeed0fca19 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_gsm.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_gsm_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..c97f73828183a1a0323e98a0187e7260f6adf576 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..d2381fcc5393d9862bf4911995cf431f42a70f2f Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..a4a217ba278d38a40c87af2d2ecd85d5b0aa0df9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..2585797e40b998723c601fcd8bd62836ebaf202c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..1e5f672d1c5c1bf9a9c6a6b062c956f3143e1f40 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..d166694dde250597fb67a3bdbc63742dd7958605 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..1ece3224249a48e576cb59deb07e03b1144f3bc9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..9d138912297d6fa89889b1478085cea9331ae390 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..4ee5031891e5c75169522f20391a8b2120064069 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..d2058d20bf82b5f5ba3c3341f48112e1c11172f6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..b6695bf9e9982393d9593b1382ff392e6862dbd5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_hp.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ff9ba0b4095d10d8bdfaa3adf0e88b07a620e5fa Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_in.png new file mode 100755 index 0000000000000000000000000000000000000000..7ccf35c00ffa2a9e0a3a6b6ec43979337ee585aa Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_inout.png new file mode 100755 index 0000000000000000000000000000000000000000..ad684092ee9aaf6c999b16a4acdf46831ecb8a26 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_no.png new file mode 100755 index 0000000000000000000000000000000000000000..854f9e35fa9d8f42afc6665d5f23f03622551f64 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_out.png new file mode 100755 index 0000000000000000000000000000000000000000..abe5ceff9c26ec684db2ebb1a541778b0bda03a9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_in.png new file mode 100755 index 0000000000000000000000000000000000000000..c85c7b25d6efa4d6d88dc9b09a8184c37c4329e5 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_inout.png new file mode 100755 index 0000000000000000000000000000000000000000..cb4214de9133778700a7d23afe50439714341b41 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_no.png new file mode 100755 index 0000000000000000000000000000000000000000..c5c9b2d2169ca01f2d7906f23bafd1230e4ba6ea Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_out.png new file mode 100755 index 0000000000000000000000000000000000000000..9af3c47980360eddde543f1cfed6b8b58af8c902 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g_plus_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_in.png new file mode 100644 index 0000000000000000000000000000000000000000..a037253c6290c027667532cec4c2bc1a20baa32b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..1c71f83b67b45854520fd829e23bfe257c8f3158 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_no.png new file mode 100644 index 0000000000000000000000000000000000000000..cd94520e2fefe0d6561547e825f1a62f9b5a44ed Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_out.png new file mode 100644 index 0000000000000000000000000000000000000000..0d73b0fe9a54b8713f30ae9621050e5a7d97242c Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_e_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_in.png new file mode 100644 index 0000000000000000000000000000000000000000..1a1342c100df6061f807f16f1a2e31feaf63f80a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..54f349d4a22d12dfab59ed4a11b7668358c44ee7 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_no.png new file mode 100644 index 0000000000000000000000000000000000000000..008f13c15d6c3428640c86350dd8e5f64b9b4461 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_out.png new file mode 100644 index 0000000000000000000000000000000000000000..d88733448c650a15831d6c1c656f8a8b15656706 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_g_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_in.png new file mode 100644 index 0000000000000000000000000000000000000000..59b33c1bc355c39c912a5f98b6704ce2331d49e9 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..31a27e9937df52e5592e4396cf9224619e326602 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_no.png new file mode 100644 index 0000000000000000000000000000000000000000..14443bb44676a7cb774542ebc727168356526c10 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_out.png new file mode 100644 index 0000000000000000000000000000000000000000..d0cda1878d4b861207aefe71598821f50270885a Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_h_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_in.png new file mode 100644 index 0000000000000000000000000000000000000000..2a484a7cdf7566c987b98531759898eb43188fa1 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..e1847b2353f3c06424231aaa513abc5b2675bcb2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_no.png new file mode 100644 index 0000000000000000000000000000000000000000..25d1042535a6d783f26eb00f1761010e47e97c4b Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_out.png new file mode 100644 index 0000000000000000000000000000000000000000..1deef41f74a854468d08d73ff60a17ed74ba39d0 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hp_out.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_1.png new file mode 100644 index 0000000000000000000000000000000000000000..cb3e63074dd2b3d02d372ea2222cef3756d43a58 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_1.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_sim1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_sim1.png new file mode 100644 index 0000000000000000000000000000000000000000..2ba7fd284106e028816e2d35c7dc1950a2ea685e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_sim1.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_sim2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_sim2.png new file mode 100644 index 0000000000000000000000000000000000000000..834c80a9b962c8d7cde6fb4849eb4f842654bb35 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null_sim2.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_in.png new file mode 100644 index 0000000000000000000000000000000000000000..cc59f7c6bd9a524f2bd8233c7f92ff29adf7ae1e Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_in.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_inout.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba3dd2b8ff78489f7f8d19903aa407f79217bb6 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_inout.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_no.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_no.png new file mode 100644 index 0000000000000000000000000000000000000000..29d4e60a58b55a01eb8f7fc16f348cec19e7264d Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_no.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_out.png new file mode 100644 index 0000000000000000000000000000000000000000..db3889be5e2e317bcbfabc3c98d3b8ac42f288c2 Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_r_out.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..29ff6fe2af81cc12fe5caf33ff67cb28bff4be8b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_2g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_2g.png new file mode 100644 index 0000000000000000000000000000000000000000..5bbfa6f95eb5f7a4fd12c4c17f0256c932e67cf8 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_2g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_hp.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..6e88bf9b5fe48952b29c4a1948cd3763f12f38ff Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_hp.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..59c0e9f7862ac0a55eec481c8564a12c845079ce Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..5076cf95203bf0b062e39e020c18666e7792e297 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..3ab84708d17066e4367bef16f761081ee1595702 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..83538d463d4fd984567e3ac8b45c7ba7137989cc Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png new file mode 100755 index 0000000000000000000000000000000000000000..aa011ca08219d424d54c3256415bafb31b47f922 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png new file mode 100755 index 0000000000000000000000000000000000000000..4cebc4365e278c7e8a7f41ff25679c8be101484b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png new file mode 100755 index 0000000000000000000000000000000000000000..bd2b4ed6f1ca34c78b6dd8260cd2e44eb21c79ac Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_hp.png new file mode 100755 index 0000000000000000000000000000000000000000..dd99d0321e09d5a17097e13752a2cc1bb1883842 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_hp.png new file mode 100755 index 0000000000000000000000000000000000000000..eca60006f6ce4bbc90be9603b00f5aaa8851f08c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim1_new.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim1_new.png new file mode 100644 index 0000000000000000000000000000000000000000..f4d46856438ac183fc017defd019dbde95ff7a1d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim1_new.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim2_new.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim2_new.png new file mode 100644 index 0000000000000000000000000000000000000000..929c1f4a588d515df9667a725ea332374dced710 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim2_new.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim_1.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc627c2f10ba0e2e81b83410e2e6c47a989a19a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim_1.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ff5c6af9b10d9d60eab9110d020d3191ac8d8411 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..68bfaa9c46df5ed353fb1d07f84aad4baefab4e6 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3af557fa16e605de4fa065bc92c2733187c9f3b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..162393fcb61228089cb2df201395cc3168fc4fec Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..f1163cb6f25c418fabf23722c4439f722de84b17 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2607f6954051b9e830d5ccd5d5b211875b8c59 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..42b98899d754e22b6be9cadafc769cb256e56e93 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..65c1f2972dd0a9b3d111246fb7cd22cd57bcc00d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e4485b93d41b30c273637c20b044b122080e4274 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..669a65d4aa6c3a1eb40255bd643264a8499d428e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ff5c6af9b10d9d60eab9110d020d3191ac8d8411 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..4dac80fcb675b68be20ba5c5d2726d2b90917d0b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3af557fa16e605de4fa065bc92c2733187c9f3b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..162393fcb61228089cb2df201395cc3168fc4fec Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9deb1e7d791b2ece98028b75f2a9025d04bbdf Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2607f6954051b9e830d5ccd5d5b211875b8c59 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..d598aeaa6943ceeae3e356c37769dccbf1828da9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..65c1f2972dd0a9b3d111246fb7cd22cd57bcc00d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e4485b93d41b30c273637c20b044b122080e4274 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..3a449e599bf419033f0843e08e0656d55bb79435 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..5c730cbb7d99f7a6b2b8459349d2d794a5e0e10d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..61bc6cdb030e286e80180fef382458efa20b381b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..7c6f6dfebbf56e44de7f09209ffb6642afb29d3b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ba81c495b9961153ead3bbb1475b963fe549d988 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b82719c2f48fcc0a0b0fa66dcb721fb690a1efde Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..243737d4649385c1bb5ce55a41e66510309d9cc0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..36f76c4a403de205c7806d020d2d5cc29690a59c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..b1254cbbb59fda4e7133164bea0e32d81c3ebbd2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..bcdc84116b6914680b08aeab8f5b30588c72712d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..8128273a791785010f0b854c7cc6c66bcac2a2b1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..31bc62c93310ef21bc4b7a2a10c888ce2e957726 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..b34834c915d4a64ef10a8203c9c16da3589eedee Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..b988e00e55853845c6f0f346f1119ecee97dcd98 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..70243b168ea5b656a3a183e093776be19d048a9d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b951e162e90e4395fb4a0ff4570b4e7b66b7960b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ad1f04c82589df41608ad3f3053283c1575f367a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..601cdb1f40d08b5c258812da86374091ddde1ebb Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..61b14bb9db30088deb7401239bcc23b5f5de8159 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..063458f20d1a04225eccdbf6fe13cde050b433a5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ab7b1a16679068aa271ec5a4eb9e335d7be73cb2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..82d26a33452bf897985534006a7220c16fd33c2f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6ee0e6742e982f461750ddbcea9849fb84c8e1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..83aff3ddc3db694f655e24c2989444227b8d78bd Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ac043125258e00ab066526443697875e11b22d31 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..cac2e1b96615aa3f6c5217b34f7a8218fdfae27c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..5faca75e4978225765267d44a98b9f787cfe7834 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..67b074fc6f5c6277a30e8280b12a410e7447f604 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..95c2e069371a5b31beb87a269bc16dbbde0ceebe Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..891f9f4cee88d691e4cfa6c4ee5af8281dbaccfb Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..647006efc967fbc432a278e0232759e32c0be2f3 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..db434811325276c7a040e046ed0da4f191352af5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..7a9dba2633db8a774b242686da0f3bff3e0cfff3 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf18d3ecf03fb14f8ac988b1c7179ab31891660 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e172e18b22e9981795aa4e2dbbe5e3a95ffa551b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..8347aa05766f26cbb82adab133e4a5fabe8144aa Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ab958ab8f06d42b4dcfd813bf36a5abb90ec84 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..097cfc4f26a3029e338569e8ec9928f54324bcee Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3546860670c3db283ac36d9cc4a94be6de79ad8d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..53b74b103771943749c1a8cd756d51ae5221d452 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b7aca12a6094005082a7d088f36d98277250b818 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..bea4818a5fd90b35a52932893fef5323759e5afd Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..5370205ccb33c6a76c55ef9e3832c71722921124 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ec9192189ffb4ad8160897416b721b23decc21 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..28bb4c457e1eb08e84a2c4cbfb24de84bac77df5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..9fb2ffb747f0dddfd58619ae362a426aa88ffd5e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..173188c6dbf1207d5ad99d8361f9d1a714d46985 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..221fae019f63773e16be05851d3f1b40e5b28ee8 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ed3c6b388e461c6d6d03be084a8322e41638e80c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..65683166ab0c27e58c2f11b348a93a925d1158c5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b61f1277cb3e6e27cd16c5663339406f275a4113 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..57929b3511b7daf9f1bea9bd606b7bbe9edf3ff2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..f24da096fd31f99f2405d32a3e9f382848cf2ff4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..7f68ddaefce670cdaab885b50f00336e98521155 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..35b004d00196e07e54e59dfae150a2dbd582b4c8 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f29bbfaa838356b27259fe0e9530e7f8cae197 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..9e14317c14fdbc8aaf0c1c76cd911f35271565e0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..aadbdb36474acda593438e089f27a35c69abb370 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..c8ad01076925a63ff61fc2ffd11c60e69e58195e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..79b145004c7d3193530dda83e630e1e00099fd41 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..48a57c8e6576a3e676a1697752d9bb561ab301a2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..1ab2b2ce9f4f08d747e81b2cd167b1e3876e4368 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..671914f5878689a36710df486773a5a594bd397e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..b8df5cec75cf48638962aba95e7e75c327e7d2a4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..69d8678ac34ad0f109e350e17df8042f7c78026a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..0b18b6dad535634911455a81f17fb93c18d9ac12 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..982a93ee5cbed6a11d87b271b1fbbf5c70194dfc Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..3fa66a2cfcc9aff9f5c68fdf7f480c4cfc15e728 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..64b3ecd883e1daf716cdbde7c889405fa87bbb7a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..02004e70e216a1b44694424ea966889571faf088 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe7e3a93c850493658c8b352aa2e8339646da80 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..71463be0507472460fff2e58c3ce5024e22506b7 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..d61ff7ea0fae8eebda8511cab55558c7d70d0ba3 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ef30e4329c501631b16d4a1f36cd71df88582507 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..2504ed7fa3921e36130965c174de4178a67cd37c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..07bd8b167c28e9f2453c4a2f983f0e1e4e59487f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..1d813efbfa26675f38878a52c4ac68b78239e78d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..39309dff3741ac36702c868e95f1fe531e663928 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..c86df18c95f926ae6f42db0bd32ff8a0cf82068f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..1c492e1466d010e18cf1b2775c54cabdd755c45f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..95a3964c8d06e6ea4c27f48ff628d22689c34b92 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..f11b84eb00684d41959624f03b96c999ad5f36fc Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..005b3a434ad6e71adc21fdf3c4b05859f1d74272 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..6be21560b971cb6e1a41f554af780592fa6f4e45 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..738ddec8025ddb3066e436dbfbc85eb6da2affc8 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..60450112a7e9942d029683efb943b74c180ab9ad Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..24cbdaeb565b056c1815d98825e28c25969f3c10 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..0a71f5986287a33b47a248b604511354c51ec99a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..3a4bd3ca186e895c9925f4d68f32120fe90a7edf Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..2608bc1fc22993bccc7f53bc15ea35f942105c22 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..ae85f9363564d6543a7ce49010ecbafb40ac05fe Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..ea320f91b876a42094b60dd27b33224c4d9be316 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..7dbba7db40aef0a1c9c57d7945c2e1fe8d64fe1f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e.png new file mode 100755 index 0000000000000000000000000000000000000000..55521f581f34a82559751665cb8f51b2497ac1ec Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..b88661da7ee3b42d8ef71b7de79c6cf9899a8bbb Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..ad8a117cc5218dc46a89fd8703e070ad92d6e81a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..7358b66b7d5877e9328351fcbc5510e0446845a4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..52263415d30a0c14aca01b82ad29b5491713ea44 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..b0b95813d12b2991a58219e725fc23d7b4316e37 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..429a149fa7dc7fb2410b2b62732d6bd45b767530 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..49b65546c3c1a5d67c9dd462589852b3ac7522fe Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..4b61681adbfff9c52c9b23726285367e7c5d04ce Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..c7385f0c10df07d92cc08c95416ecba5ae907de9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..08f7b495d02cd28daea18ebb0827272eaccbc528 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..9296499ad1c7c54d345499d5efdc02b169d6664c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..8eeaca8d9ee17990d8da4f0bd7dee09842b129a5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..e29348a4c661d66ce28eb51b84f9d6e0dd04082c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g.png new file mode 100755 index 0000000000000000000000000000000000000000..4fca6a3cfdfd5711fca23daf9bf65774e434f095 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..e77a91aa369e633f8e6ab8f1a074fcbaf8ecf393 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..7d0d206e59830215c8cd5f8dd6ac44fa2ecc2470 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..e77a626ef6f2f0d6aaa8abeeca95b9bce4a17d0e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_gsm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..b581f5d5ab37af67783f63b8ac15d55447577b64 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_gsm.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_gsm_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..370fa889b56b1aa9f9817521f059b61d7344a75e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..52263415d30a0c14aca01b82ad29b5491713ea44 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..85c241e7f53b664a7cf6804eeef3583beb95e853 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..429a149fa7dc7fb2410b2b62732d6bd45b767530 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..49b65546c3c1a5d67c9dd462589852b3ac7522fe Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..6158001414a66610c4e77c0a6c1f38083ddf5364 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..c7385f0c10df07d92cc08c95416ecba5ae907de9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e3446dd3aecff24f9ed528d556c01c161dc5b9c2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..9296499ad1c7c54d345499d5efdc02b169d6664c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..8eeaca8d9ee17990d8da4f0bd7dee09842b129a5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..67ae5899fd017719e5200a83e3f2cc2d8e779226 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..c5dd2c50e38c75479b3611312db519667efce397 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..39218a01ae1f91dd5b89a675a60082596b6ef578 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..eebe87d39a4fcfb5627eb53cc259d7dbf6ef15cd Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..946e832fdeff35e0699790d14c62244a8df6a02c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..9c8d910e60edcb980a575d2f68f1f5b11ab8ae71 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..25d9d069491f79feeb4d111808c9341d47f51d5e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..7dbe663bab946d40b59597a0a7b3ee2d24aee7b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..16d093dea63ecb30aa98ac3f54bc5f4e6f96268c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..187e0af0ce478832f6faa08f0d772ae951c051b1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..652cdb087f007e7ceff8e0e12098fbda5dbe7787 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..eaf6a27f4f86ed7a54037bd5ffe0307c05ebf998 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..c591c856900d2769a8f9697753845baf0a1b6128 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e.png new file mode 100755 index 0000000000000000000000000000000000000000..d79900c3374c8f93ee3628deb0ed134458c95bf3 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..7360d59afcb9d792489e614db34e59615fdc303a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..05af68eec1ecef390d7c5d07291c066e559a9bd0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..f085372b827a3f87fbe4d47f6b4232a42cf8683a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..a31472332d998e0ebd7d54667fdbdc40f973e4c9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..213194917084f6b708e281f37626ef1706103f16 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ec6ce88324f854afac8288d085cb0e50610e54d1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f00f7ff38fa7ea37fa5e82d3c12204b793012a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..41eaea06d362f116e357a0fcc8d469ce2ab78725 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..86ec69084c9302ab426c798d468acc9a4da56d44 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ffa6b71ab07b6b96581663a1a9c001c1c440a9c0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..77ee8e48e79c4665fc08fb32ac5d64a2c77fe04f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..bead621c91f4b11dd834f8b3dcca51f475c9813b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..0d3434045fb7bf61c0351c274ab13deb174604b7 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g.png new file mode 100755 index 0000000000000000000000000000000000000000..7c6ef450180181b9efb3b392dff6c2a8b573b0d8 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..795f722b5f42506d96e9fb72bb8195ed2dd89257 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b09dd9a1f0d7540fefe24a4fefba7a858a6c644a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..2bd02be4f520a0a3af54ff9ad0f8c78ef2844c98 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_gsm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..9b068c1bf42d90e4f1f31699545b4971b0256c6d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_gsm.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_gsm_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..3a0f4f453ce8d24a21096d28ee22926f731e40e9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..43053510881aded0128758ce8bfc8818f942b8d9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab76e819cb01e5a0829029cee9c1373d5c66069 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..eadf88879093cff3d8cd9428cc48189a85b521c7 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..00b9a24f7f3b55cfc42a9a9cb685a3ebaa211529 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..9620a0f81674fe58e13d1f63da11cd611a54530c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..487cd1ff5b7d0ac082935b39b628d6624831e0e9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..dbfd0210d33f199770ddb28267a89c37b3cccc77 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..c9555030d89bf915cd1edea30145b5a3cb9448dd Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..ced6d85ea219f4a2cc24e623f432f7d81bd0baa1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..b5ad7ca900d409fc0c10b78956808bff7887cb19 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..254211d4cb4e9288e1f5eaaa4878d2ed6101220d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..c715e53a9be693f231e6a8f3f29df731c5d7546b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..6a6a34dd90132b2a5613c5ea0fb3226b304d05dc Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..2c2ee21e9e56dc8cdab8647271717df7693de151 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..e2cd61e27c441675df9f512174b59fc5bf93aa4e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..331e52f06e6cf8311973080a147e8e8240ac0e97 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..01b735868baa983af3d0609effb386c4ff447e6f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..a79913f98e9eb6b8bc46a0ae8053b5965e1e0bc1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..89a8720aa280007b7953b1d8911ec70497b0d6f6 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..de92e6d81139252797fc9331fd87be576cd75cee Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b95eb22f9d7f1e38fbcfc5ff3f3acde00685712c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..9ddf4291fd6843425c4b0532ed33a583ac94e91b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..06f5ec9d66006ec9a92a62f5c0cbe59cfcea9b9f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e.png new file mode 100755 index 0000000000000000000000000000000000000000..06638f33a307194e09ced926f18728c1d884eb2a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..6076075e094f7ef6da537fafb54889660c708356 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..d040a2b6d2202b062daf9d0049165f6e4fd301fe Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..fe9f905e60931b859b3d4d8c53ae286b73f4ca56 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..e322672b6ed9d8568cdf44f270937e78be130129 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..946ae176caf363dbb6e6e46051a650abccbff2a8 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..6756017716c08db84788e01de6032a33933edd2c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..7f8f8a4a5fa583b25e750ca10267b0671e30ab2c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b9304e7a8965ae4ad05d566f464d79023e6cd121 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..dfde6cab7accda58261f43204ee38d7e5914db12 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..180eec96067265a22190dd2ccc1fa625af4d0d10 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..4316eff76b5383229a6129c87b79b71069872af1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..91c9a031c90821d9269d538934377368f91f04f3 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..1f6145e7d50df2963c2863e5bfde721a31e355d9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g.png new file mode 100755 index 0000000000000000000000000000000000000000..ba1ff45283b3c77493dc2b1515265b41a85cdc2e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..f7fa38c7e3b74a1f82efb9775d3014022ae91481 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..8355a4a9e593cc9ceda99630ec6bb40578dbb4a3 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..91769b93a4939109ec592ea83fa1680a32925809 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_gsm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..2e6bc18c8507e0acb0bbe8ed4503280af28d2e1c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_gsm.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_gsm_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..68c68fcaf552762d53a2e5fb01200c2f390b8399 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..beb641bf20be82823292824ce7f1c312714ef25f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..37633888f0f7aeb841153d75c7e6aa1f16ecf621 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..88645bc12df5ad9f9cf6836b846a2bdce9db3cfc Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef1e120a6f0d6c622a3735f922dff3c10031aff Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..266fa295fe2d394791972eb362ff4e6726f41562 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..fec6ead52acf17cf983b532b1dd1b8017de51be0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f92c9c237bd8b3b6acec890068d30b3a7c0b85ea Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..5d6645b792aa78e57e2364e5b1c6a14397c0a392 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..fe80330cf1237fbcb2a0d3efda6973955422342c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..019e3825d93b98544e0da4e1bc156afecb8f1aa2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..003737d95ef11f7c1ee32e06dcb5193eef3b369c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..6875565fc04e3a026c61c89bb419d77bccf3aaf7 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..56f83dd77129be0cff8f4bf317e22a7d2f273bf2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..42935b6b8dcc2bed30656a5933f39b680c1c652e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b8742a027db1e6f5f2d3706d9d7b794b58002690 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..cf04633d1cfdd925fe08926cbddff4350db4d1fd Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..b0073c2dee67db4f75388f905eb9ab56e876c988 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..0d9358064e0a5560367e9dd0a90a728d3f36b78f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..bdbce47f9ab5faa1bf28ad25911b2d565b88cdd2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..347ea6b772221563fad67a909ed3305cc0add7e5 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..0ade75815f40b7b81f3b0ad06641a27f189fa8fe Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..69d763da2d844fa4dd91b33da54a2aea164547e4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..841da56a7d8c7cd920db309cb4495aa45926437e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e.png new file mode 100755 index 0000000000000000000000000000000000000000..c684a5a720082b477ba96ad71fa54ec9823fc244 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..d71f85f0aba7d0ec60b6f1b21fbcd334de19762d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..0e3d718715baccc5a8fddaa989de4cc6e929093e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..39fb603bef88ed06b7fe4ba9315430a43e9eca5f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..77c354a3fe54a897001a7304f7ab9b031d185525 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..14926a314e9c6c60b533e4cb1f85e3fcffe57112 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..4bcdc7bab1e57fde26ca9f8a7ae82fbac12bf07d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..1107844469a16972b0a8f679d47660dd0f5b6af0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..47ff33dd31754855e0c683b40d62d75c35734fe9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..04e45dc84cff14f574b07edfa8160dfafebd35a4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..d6078c6e1b99a524144ea1d07c3d19ea2c8d5ab9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..3c3a6b3491fc4ad4a578bac0d9dbbc8c7a8eb712 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..9871304842f227b5f8a133fcbbd1a8f48b70d64c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..7272c32dde1891633a4f4b215b9d81fe79d781e1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g.png new file mode 100755 index 0000000000000000000000000000000000000000..d6e3cac5c96bcbf8f063b5148d5616d5bc431b66 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..949d58a6b05ad52b5e1d7e9eb6cd80fa5731f598 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..407e5c1ec19fd39bb0d045f2a7505083d99d3e7e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..5f054488901cc1211fb0e8065044f154f4c17063 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_gsm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..9284534bedb1b479f67ef61ab23b3754bb8ba40e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_gsm.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_gsm_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..f7e1a13760bb446b9a9c311aa354329d880762ec Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..a4028cd2602aee1b7bd4bd880a35d607efb85e1d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..4a894f14e63ed76485846731de874807d4936b60 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..51a0f3c1ef6830d7586a622506fe996be0b22c41 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..6fa75b121d5b1a537c972ae2fefc77b374a8487c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..aed122271df917beb86948c26106e4976fbf86e4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..49c02b33b9bb1ffb2f1691704ae8d0c986ba54d7 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..358eab95c12536fc14cb941229ed8fa522c11514 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..a9ba830e85dc6c629e6dd3d9f87721297596f979 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..923555858ee6e87b9163a8191d412ac859f47049 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..bc260dead41b42edd36c754741709b8554ea93fb Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad18f03654d4f54295e97e1269f2c16c7fe989a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..86fc340c3352d7e13e6173aa45d27f66ae8eb36a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..84c46996c1ab6b8c99561a1166b15c1d9ff05dc6 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..8e7ac74bf950c6c5939d94b9a38e13e733dc15b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..fe492fdc32fdbe56eeb708e8c98d4d96cbe64e4b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..3ec684e994a020b21c3e9bfb32fde3474d685c21 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..96bbc46b6e161c82e6d485474338d9b5469bca6e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..5c4a61eedb5e7e160aadda613dd20f40bfae9b7f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..86b9a8877adc6967e816a4c3c75eb3ee9006faec Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..adcd352780ee449acd46ffcd80943441abe783a2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..f545efe222b865095fa260c94baba0cb3e42b821 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c2d055a9a96207edb6977c06c96b26e57088e4ca Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..716581fcaa6e56ae865cf2832d2dc09a183e8e17 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e.png new file mode 100755 index 0000000000000000000000000000000000000000..de3917d63a3ee6c6cbad496ca85cb2298bddc83b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..f5e59582ea4b1f1ec20fad2b26408b08093f9e86 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..de44dea1e13613ecd22ae5d812c558cea5e9e8c0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..cb068da3473b71a6b8aa61729d822f16f49ced1f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..c9eb96fdaf7e125580dd0e50a7f18b0298aecbae Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..72eadc0a0cbc13e9661897d803e5ea94ce6a838b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..fb4d39ec5f5893aad09af2c4008bee1e70e87306 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e215e5cb01281959e66274a0b9497a01079ecc Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..b47d04f71726a8e61f5caee7228fb6fdfc7f6ac1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..f80b324a8a29782a39dbc1373fdfc48b0ed99d17 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..63ca13c8f2c25ffc7fe4a8f6a4bbb9d5d73e837b Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..421e8cbde356bcf877c163d2738967116b419c93 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..86748c3d06f6701ddb994d456e0a814cd1be3479 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..3bbc885a8e5332ee8d68cf7fb27f88717ace57ca Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g.png new file mode 100755 index 0000000000000000000000000000000000000000..f54d21fbddb230d5a587b0d5306d69df17af9b6a Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..474f0756522118b85fc157f38db1dced28fb2961 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_fully_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..5c7eaaeeffe685294e24731fa26d64fe84541bb2 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c65123d84ea51868786e1b8195f6d75c5e2126e9 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_gsm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..2a86141ebf22167204629314d0b19b0d0e2edd85 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_gsm.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_gsm_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..02f3b831c1c9a2038757a20a79717b3fc00e4d39 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..b5ed22becc0e5ce1126f4a2720171773a226546e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ffd689d176cb35e31cc31676f1153c878f0d94e0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..b3eb6d9edc339a4d42bcab412b8eb146aebfc9b0 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_g.png new file mode 100644 index 0000000000000000000000000000000000000000..1abe466d6e4367f3ecdb039c8db816885fa380b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_h.png new file mode 100644 index 0000000000000000000000000000000000000000..e36e6f23405c6658eba99c22a9b2421069fd3def Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..ef872fdc0e7b9c8a714e6afe10e0359b1822b212 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim1_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_3g.png new file mode 100644 index 0000000000000000000000000000000000000000..ccbcfa0e40eb0e087829428a51a7d5f403d1569c Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_3g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..02d8244e9a9ba586417014050b41e5fd137b9d4f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_g.png new file mode 100644 index 0000000000000000000000000000000000000000..83296a53a5387507cba6fc46aabc72d5da78aec1 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_g.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_h.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf107d424ed3a1537d7f4f58d45395e902fc460 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_h.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_hp.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..6c34eabc74e9963fbf666fff5e0cee8d6b2a909d Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_sim2_hp.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ade182839043215eefc071732d591fe02838c165 Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_1.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_sim1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_sim1.png new file mode 100644 index 0000000000000000000000000000000000000000..782d5901a603e5319604a58f905463ee3f5a004f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_sim1.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_sim2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_sim2.png new file mode 100644 index 0000000000000000000000000000000000000000..61317a6034fc4d03d8b09dd45e238ae383618c5f Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null_sim2.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..bd31253073ce5fca48005914a54fcc43de366a5f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..5ed365cb371dfd99dfeb4fe04065d708077fcd21 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..5b22d20ce8f01aea50877c4efa6c499069d38451 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png new file mode 100755 index 0000000000000000000000000000000000000000..b156b06e3730011344171d76d20623d317c4de9a Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png new file mode 100755 index 0000000000000000000000000000000000000000..f85047725b6397ecf0839bae54931d86b53056bd Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png new file mode 100755 index 0000000000000000000000000000000000000000..b261c1e35ea00b34efa69b243e3433a11874cb97 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_hp.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_hp.png new file mode 100755 index 0000000000000000000000000000000000000000..65773655c7dc4ad6faedf62bf3ad5dd5d0f2f137 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_hp.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_hp.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_hp.png new file mode 100755 index 0000000000000000000000000000000000000000..4172082efebcf0e9ec802d1a6ac9cdb77267cece Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_hp.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..52569edd7e9ca1697e57b106547c16a5bd4d72b8 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..034a68220b9761b4829b0e54ed60d49d475a4ec7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed366e8b49ea2e3096472716a5363135ddc383b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..18fe2a2545ebdaf4906523feef0f4d42f0b7325c Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..175020cb7a3837cf8747380b363598136e21e9db Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..10e733a90850f26f96a3271465f653da9656ea9f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..295e678c94a80b385b280c4446244f84b76c2fb2 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..d36720a0e5f048a3e8d13617010705bff99cbe49 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..8044a22f08740a4244b4d3437c62c6525f8ef38e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..256c8d322bf7fbd6e58a84701099101e0b275286 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..0b4d9cf010d10f9b9926e1e79d087b597673b6a8 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..d347e534a04766b71e7c3fe189fd46f69a3f754e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4e28ef149a13a7097b1505969494e0a818968f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..c04653525fa151c7059865fa0fbfdc2b87bb5281 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..976d87e8e0f5edfcb417d4e533a6c60f64bb1917 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ae2c1b0f78ad01b7c433f48674a13fedceb96dfb Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b3408c10b891df1364e6da8b6149f3e0e376a5 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf9fcf1b10f36584632876a7695daeec4c5c943 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..92d6840bac66beff09ea6d6bd6da600494d8050a Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..bca3ef687d9a3212e89ff27cbb39f5cee7cb80bd Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..ec1d1049881124791509c7af4554e3dd30c4108b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..9f1de41ca85b2c60acce0f1d58a5215c30322d54 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..b5222fcd516104c3332bdbec06f28d4fc394b2ee Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b12b0edd37b8c970c16cb888b6a84591aeb10a50 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..f333138a307ab32da69af5a529b4ab4fc0adda94 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..12f8875805fe443745761a7e30d4bce3e3565f24 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..9b03d1852051d3c1c5ca83c210e192597bcb76e7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..ffdc80f9d8545075e9152608b7e49f2a470b0153 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..ae3d75a7dfe0e5f8042a931f1d99caf1ef72df4b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c67bfe789f1c44a78428eee6bb8ca57f93569fd1 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..66019f809430909ad06617c8b539b0fa9007431c Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..d14e6890499369ba9d5e43ba23d872c2139051db Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e.png new file mode 100755 index 0000000000000000000000000000000000000000..281afe08a4c1d9fb7dbcd2a46703a1f965ca7d7f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..083889e9ff691731e04c590bea6e157f7fac1e2e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c3efed13f571a445c8c909376983beedcbd2ed11 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..3fab702985a28433c59ec104d70a4924be19265b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc6d0e0ba9a270c3014a3d4176fcb6bc46cca35 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..e28b6f02960d064ead82afb05e33af4a2fa2bb1c Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g.png new file mode 100755 index 0000000000000000000000000000000000000000..651ea7b8d45b97aa1ce7ff4e3f2f7032a1ac88d3 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..5942471029aaa02836a9f3d1c32ba33e942fd4ec Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..9699a3abcf97632a829468160c0148f0c3e50764 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..d976f3dc5611ce015c59c15a95a7b2690805f9e6 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_gsm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..1422d93606a67c73559a9622c0f90681f80a753e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_gsm.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_gsm_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..0ef879b64ed26c0e67b93f3e5eba86533c261c9b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..dfc663d775bec91073358fcc467ec3d7edbb1b3f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..27be3f89459851c1a2b9779c223e1a33038d80c2 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..8ff5ac893d90fc7c966ca2de3e1b2129854b2bd9 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..655edc3a4c592825dbe5de091e4898098b27e861 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..e151a7e2f7568039f0dd52ed1f7d241057c3e027 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..9dc081b0f5fa4a14f74ae30afc1c6a70593fc243 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..51761046ed1cb470c537868a377313d71874b789 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..1c929281ea0ea13bd1e79ce86ac44c624cf934a3 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..7ebf56c85f688ea1df70289b1e7d2d528e2b9272 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..d7819349b5ad2af11cb690148741dfae0ca75c76 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..71aa042a743c4a3aa33e65e9d0de5c9157e9ddde Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..3091f56d6bd5501ed8bd6e2f2796758e07eac61f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..60344ddb025fa3267cc2050d965c26d7265b3264 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..b6689b5904b81b5e8cb876deb5fc4d27858a9f06 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e.png new file mode 100755 index 0000000000000000000000000000000000000000..79ca14f55e0119810cd82bd84b9df6cc987c47da Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..e049773ee3e76432ff7a6048c539b936ce857bae Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..3d5e5982b11097cef34abc025cd079460c798174 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..5bec840085114cb99c49c99badbd70135e466df7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..3c33f6d592c6a791803b52fc8c7365b31af3cc94 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc774bef3e9a6705967ab2936f85e03e86e3632 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g.png new file mode 100755 index 0000000000000000000000000000000000000000..51187f998e5874e2ccf9a08f2913cb3bc4bdbc31 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..ea5baa13ef34728b6b83629301d1f0f8549d0355 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b3a322cab7edd194eedf605a47b69563987838e9 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..5ac30c8e2572d9395f65bf573c265d9d4d3d7a0d Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_gsm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..b5b3611d5a2597e06527365682de4c0fb596e907 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_gsm.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_gsm_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..7f3f307c944269cc2ad4b5fb4df074ab290477b7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..9943613ab35be6659e45b42a863ad3e1582a8f3a Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..40096e83ab4ea6055a4bb17462818b685dc9baea Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..5a04863315b03977bc4f7bc60928a2acf0453c5e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..12a75c698b1e1777b677807b2bd50a60d8f57d12 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..078f837a4a146c7ad4ece3e526beb6a84e91cf96 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..f4a0cc24f03574eca06ca2dc699bb6767ba773cc Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..20581f703207bbd867ff73355c914a2381618112 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b03871f85e9de85d355424128c544b677d082b01 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..9583d93f29f250cde1ceee2ea4693cf445112533 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..e9313ecf65b6e72295128c778ef79be451148d30 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..5a2000b66c39eac7a2522f808df34028e20b0e74 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..91460b22d30ac576fd3d94d11f5a853ac5d07343 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..b9d52280b51f2f94e5bc9c7c043146f7b35a94c9 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..6f6e6f86fbe8781d15690bd38f2ac6b36483e7d5 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..50cd5b49e75e83b7d15bc21845b5226aa7f416ed Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e.png new file mode 100755 index 0000000000000000000000000000000000000000..8439cef1d08326c582559dfc5c52d3418a0d4f67 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..77931bce18ed2d741589bb410784e165fa01c886 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..2e662e62e371e09cc338e2518dc8554a956df1bb Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..31f52ace01edf159b969b9b7560198ae846eff64 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..a9b3b1921690ebc987986b0088e2a121d4f9cb5c Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..736c19192072c81dffe0be74c050d96410204268 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g.png new file mode 100755 index 0000000000000000000000000000000000000000..f3ffb3be17f44bb0429f09702adefe1e0af63094 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..636020289f58457b9a377732f4443ad7c2a54e02 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..609797132504d265d244f27fdb3b86f48bb7c5c8 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..64cdc95a5d93ca9a2f14a9d7592da07c1e926888 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_gsm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..6486bbfb8d27f315c1fa5279e11a402e590cbf84 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_gsm.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_gsm_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..95eb1f25f2a0f3b267cea5aa8ba69cb57ccec8cd Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..1fc177529fd5bb72775cc3537c0c4e11c6711cf0 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ed09e62d33de89319bf5febcb182050b73cb63aa Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..ca2472167a02b9e8c2616ed736c34d22bb3af4f0 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..61d2d85abb8dec0d89926ed6ff40fa137f93c84a Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..69fdc6218c14ad990e5f1fd661f6c077aa85f7d8 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..13e60904fec0dcf1ff51119e0bd1be93f362ab96 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..a3310a04b1465e8ad50287af02e09a41475ed7c7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..a26b0835e4cb4bd9dad86a599d5a78f999b03262 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..fd3dd306372ff2c839b4f35c6df64b084bcd6666 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..eb38bbcae09bb7da63c67c30abdbdbe4c383587e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..cb8fc4f5b9cc9d4e85e0d3a3339504990546cad4 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..fe055c75ad831854d306f9f086e4f87a02ea1411 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..dcfa90422140da0075a4e3a4fa7f5464f1d97768 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..e7ef1dffcadb2c85f6887263faaee61d0f1af69f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..e16de169df97245393ce6b1e0bb8f8a49c8e6049 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e.png new file mode 100755 index 0000000000000000000000000000000000000000..87e96cc848faf6ed152f186214d44b89e69f9b80 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..a2d0faa37eb360ffcc4cd6ea471c959cf70bc97a Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..6b52c5f3e1946aa15eafea5a28dec26be86f921a Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..477a5fe8df11fae3b34733856c61099b542be31f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..52726fef215f08459dcef1c59ca586710fffd9b2 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..47422b3803e58a5e83529d8d8016c57cf8edf57e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g.png new file mode 100755 index 0000000000000000000000000000000000000000..b29d75ef12cabb19fa23d2e1ebd78b4535b9c9e8 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..8920122e9e80af2eff7feca9c8e53fd4bc1b84b4 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..5769b5865392573a64d485d7a962960c90960eb6 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..1487ca7613d2b3438a031893eeef93d738e9ecae Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_gsm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..e0f48e1bc5c6f8ba0011ffafa81f8d3543ff1f3c Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_gsm.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_gsm_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..11b6c41ec44659897bfa6c9a8cd2a4a9c9236a46 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..82b9741bfed4ddac6d3070422a7e53add672270e Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..542884b084367c034dda65ca33f15bfaff93f7f2 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..8e5f6087d7a71543b2a0108020053b81002f6b56 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g.png new file mode 100755 index 0000000000000000000000000000000000000000..76893c3806f1a6e730cf69a77c2daf062d094973 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..fe5ea012fcb4242c70ae36706cd588ff03b665f4 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..7576cddab88f3e6808390890e832f56694546eb9 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..7cdb571f9ee54c76080d0a737036e38ee9b1f83f Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..0799418a83bf5e57d8291579ed36c6cb187abd92 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..82577bedd6d1d02043ecb0e8ddab908ed1e22438 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_3g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g.png new file mode 100755 index 0000000000000000000000000000000000000000..4f3494cbab0becb18f203f190f6951a9bd6940f4 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default.png new file mode 100755 index 0000000000000000000000000000000000000000..39d3beee7100610a2cf375236fc1f110cec5738c Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..38c1a01e4002a18ed5b3fd3cf17e63f1a2184b52 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..c2452a91bf1457e6e2f52a70c1760b004b097d70 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..77770e493b89fe6b61436ecc275f07ff414745be Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_default_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..24c59105c5e376833753c69326dece912a4cf15b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_4g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e.png new file mode 100755 index 0000000000000000000000000000000000000000..cd10b05f69383ba927a689675903e270958568ce Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..d24e199e047278c106941bfdf4b2fade2b57944b Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..59da70a129c584dd634fbce95e8e9c8746c76109 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..ac30d5e56078fb63194c2be528fe05707a82ccf4 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_e_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..0338d28778ab6a2fcdd5ffea0e0402f236b5de18 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..231d3c51b9e5d59aa98f9871eadd0d7a823b5565 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g.png new file mode 100755 index 0000000000000000000000000000000000000000..5b03544481b4368da0b0b3f46a78fb7c0a9656c7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..3ad515cd63b62e0b8a87d9b550037d290e3fd708 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_fully_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_fully_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..21d7c389157847feb4b9e5e7aeefc25406b6d671 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_fully_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_roam.png new file mode 100755 index 0000000000000000000000000000000000000000..5f1dd070a7c07b96eb175d562e759c3a69f20cfa Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_g_roam.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_gsm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_gsm.png new file mode 100755 index 0000000000000000000000000000000000000000..2e929d88e200e3be945056ec8333e35aa6aa9fa7 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_gsm.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_gsm_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_gsm_fully.png new file mode 100755 index 0000000000000000000000000000000000000000..c8aad28e7b70912a6b524334df7a59496ece3854 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_gsm_fully.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim.png new file mode 100755 index 0000000000000000000000000000000000000000..9f4979ce2b93a3b54549b807038b831c297b6831 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim1_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim1_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..185e47715fb5e2dd72bd9a40a555dcc2f38acd51 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim1_4g.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim2_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim2_4g.png new file mode 100644 index 0000000000000000000000000000000000000000..6fac79fef148a000179a5708bb13059d9db98576 Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_sim2_4g.png differ diff --git a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml new file mode 100644 index 0000000000000000000000000000000000000000..509cd1fb5db7861baf095f99d3d21d466e535b12 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml old mode 100644 new mode 100755 index 33effba53059f91d714537cbf4e1c56de3221929..014309aa5cef6ba28858a4e1fb300e56691df01e --- a/packages/SystemUI/res/layout/mobile_signal_group.xml +++ b/packages/SystemUI/res/layout/mobile_signal_group.xml @@ -1,5 +1,10 @@ + - + + - - + + + - + + - + + - - + + + + + - + + diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 1dab76183864094e9419f198124a97ab6d34fd74..15b0f002d3b228d75ae6cf730932aa2622632152 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -54,7 +54,6 @@ android:layout_marginTop="@*android:dimen/quick_qs_offset_height" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="48dp" android:elevation="4dp" /> diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml index d1ef5d638e7872e5d8c3390776a72bab3fcacee7..734c877d7829992b80d70d6466e9b7a76d6a89fa 100644 --- a/packages/SystemUI/res/layout/rounded_corners.xml +++ b/packages/SystemUI/res/layout/rounded_corners.xml @@ -22,7 +22,7 @@ android:id="@+id/left" android:layout_width="12dp" android:layout_height="12dp" - android:layout_gravity="left" + android:layout_gravity="left|top" android:tint="#ff000000" android:src="@drawable/rounded" /> diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml index c2b1009c31370780251b5330418161a8359d5d47..a3118b0a5d9137a67d804d5ef4e685631ce381d4 100644 --- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml +++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml @@ -84,7 +84,25 @@ android:layout_height="@dimen/screen_pinning_request_button_height" android:layout_weight="0" android:paddingStart="@dimen/screen_pinning_request_frame_padding" - android:paddingEnd="@dimen/screen_pinning_request_frame_padding" > + android:paddingEnd="@dimen/screen_pinning_request_frame_padding" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent"> + + + + + android:layout_weight="0" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent"> + + + + + android:layout_weight="0" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent" > + + + + + @@ -38,8 +39,8 @@ android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false" - android:paddingTop="12dp" - android:paddingBottom="12dp" + android:paddingTop="10dp" + android:paddingBottom="10dp" android:background="@drawable/rounded_bg_full" android:translationZ="8dp" android:orientation="horizontal" > @@ -59,6 +60,7 @@ android:gravity="center" android:layout_gravity="end" android:translationZ="8dp" + android:clickable="true" android:orientation="vertical" > + android:textAppearance="@style/TextAppearance.Volume.Header" /> @@ -88,7 +90,7 @@ android:ellipsize="end" android:maxLines="1" android:textColor="?android:attr/colorControlNormal" - android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" /> diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml index 1d1f95b4465919b9236315ed7906e370f970b87c..70654a803b44a2a7a9acdc650c85da0eae5de21c 100644 --- a/packages/SystemUI/res/layout/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout/volume_dialog_row.xml @@ -29,15 +29,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" - android:padding="10dp"> + android:padding="5dp"> + android:textAppearance="@style/TextAppearance.Volume.Header" /> + android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" /> @@ -69,19 +73,20 @@ + android:layoutDirection="rtl" + android:layout_height="@dimen/volume_dialog_panel_width"> + android:rotation="90" /> \ No newline at end of file diff --git a/packages/SystemUI/res/values-af/config.xml b/packages/SystemUI/res/values-af/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-af/config.xml +++ b/packages/SystemUI/res/values-af/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 52420299370bf6a3204e66b7c086a7eed80b25c5..9d090ba744c2e722e24dbb23bd6e6347d348068d 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -103,12 +103,9 @@ "maak kamera oop" "Kies nuwe taakuitleg" "Kanselleer" - - - - - - + "Vingerafdrukikoon" + "Programikoon" + "Hulpboodskapgebied" "Versoenbaarheid-zoem se knoppie." "Zoem kleiner na groter skerm." "Bluetooth gekoppel." @@ -311,6 +308,8 @@ "Wi-Fi af" "Wi-Fi is aan" "Geen Wi-Fi-netwerke beskikbaar nie" + + "Saai uit" "Saai tans uit" "Onbenoemde toestel" @@ -327,9 +326,11 @@ "Koppel tans …" "USB-verbinding" "Warmkol" - - - + "Skakel tans aan …" + + %d toestelle + %d toestel + "Kennisgewings" "Flitslig" "Mobiele data" @@ -339,10 +340,8 @@ "%s gebruik" "%s-limiet" "%s waarskuwing" - - - - + "Werkprofiel" + "Kennisgewings en programme is af" "Aandbeligting" "Aan by sonsondergang" "Tot sonsopkoms" @@ -360,8 +359,7 @@ "%s is in veiligmodus gedeaktiveer." "Vee alles uit" "Trek hier om verdeelde skerm te gebruik" - - + "Swiep op om programme te wissel" "Verdeel horisontaal" "Verdeel vertikaal" "Verdeel gepasmaak" @@ -502,11 +500,24 @@ "Skakel nou af" "Vou uit" "Vou in" + "Wissel uitvoertoestel" "Skerm is vasgespeld" "Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Oorsig om dit te ontspeld." + + "Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Oorsig om dit te ontspeld." + + + + + + "Het dit" "Nee, dankie" + + + + "Versteek %1$s?" "Dit sal verskyn die volgende keer wanneer jy dit in instellings aanskakel." "Versteek" @@ -586,8 +597,7 @@ "Met kragkennisgewingkontroles kan jy \'n belangrikheidvlak van 0 tot 5 vir \'n program se kennisgewings stel. \n\n""Vlak 5"" \n- Wys aan die bokant van die kennisgewinglys \n- Laat volskermonderbreking toe \n- Wys altyd opspringkennisgewings \n\n""Vlak 4"" \n- Verhoed volskermonderbreking \n- Wys altyd opspringkennisgewings \n\n""Vlak 3"" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n\n""Vlak 2"" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n\n""Vlak 1"" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n- Versteek van sluitskerm en statusbalk \n- Wys aan die onderkant van die kennisgewinglys \n\n""Vlak 0"" \n- Blokkeer alle kennisgewings van die program af" "Kennisgewings" "Jy sal nie meer hierdie kennisgewings sien nie" - - + "Jy maak hierdie kennisgewings gewoonlik toe. \nMoet ons aanhou om hulle te wys?" "Hou aan om hierdie kennisgewings te wys?" "Stop kennisgewings" "Hou aan wys" diff --git a/packages/SystemUI/res/values-am/config.xml b/packages/SystemUI/res/values-am/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-am/config.xml +++ b/packages/SystemUI/res/values-am/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index f08c71e8c66d407b23536f27f16ac8dc6afd8c02..cf1adf2d9a7d312de9f76911a6b9bb1d86c8f681 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -103,12 +103,9 @@ "ካሜራ ክፈት" "የአዲስ ተግባር አቀማመጥን ይምረጡ" "ይቅር" - - - - - - + "የጣት አሻራ አዶ" + "የመተግበሪያ አዶ" + "የእገዛ መልዕክት አካባቢ" "የተኳኋኝአጉላ አዝራር።" "አነስተኛውን ማያ ወደ ትልቅ አጉላ።" "ብሉቱዝ ተያይዟል።" @@ -311,6 +308,8 @@ "Wi-Fi ጠፍቷል" "Wi-Fi በርቷል" "ምንም የWi-Fi አውታረ መረቦች የሉም" + + "Cast" "በመውሰድ ላይ" "ያልተሰየመ መሳሪያ" @@ -327,9 +326,11 @@ "በማገናኘት ላይ..." "በማገናኘት ላይ" "መገናኛ ነጥብ" - - - + "በማብራት ላይ..." + + %d መሣሪያዎች + %d መሣሪያዎች + "ማሳወቂያዎች" "የባትሪ ብርሃን" "የተንቀሳቃሽ ስልክ ውሂብ" @@ -339,10 +340,8 @@ "%s ጥቅም ላይ ውሏል" "%s ገደብ" "የ%s ማስጠንቀቂያ" - - - - + "የሥራ መገለጫ" + "ማሳወቂያዎች እና መተግበሪያዎች ጠፍተዋል" "የምሽት ብርሃን" "ጸሐይ ስትጠልቅ ይበራል" "ጸሐይ እስክትወጣ ድረስ" @@ -360,8 +359,7 @@ "%s በጥንቃቄ ሁነታ ውስጥ ታግዷል።" "ሁሉንም አጽዳ" "የተከፈለ ማያ ገጽን ለመጠቀም እዚህ ላይ ይጎትቱ" - - + "መተግበሪያዎችን ለመቀየር ወደ ላይ ያንሸራትቱ" "አግድም ክፈል" "ቁልቁል ክፈል" "በብጁ ክፈል" @@ -502,11 +500,24 @@ "አሁን አጥፋ" "አስፋ" "ሰብስብ" + "የውጽዓት መሣሪያን ይቀይሩ" "ማያ ገጽ ተሰክቷል" "ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና አጠቃላይ ዕይታ የሚለውን ይጫኑ እና ይያዙ።" + + "ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል አጠቃላይ ዕይታ ተጭነው ይያዙ።" + + + + + + "ገባኝ" "አይ፣ አመሰግናለሁ" + + + + "%1$s ይደበቅ?" "በቅንብሮች ውስጥ በሚቀጥለው ጊዜ እንዲበራ በሚያደርጉበት ጊዜ ዳግመኛ ብቅ ይላል።" "ደብቅ" @@ -586,8 +597,7 @@ "በኃይል ማሳወቂያ መቆጣጠሪያዎች አማካኝነት የአንድ መተግበሪያ ማሳወቂያዎች የአስፈላጊነት ደረጃ ከ0 እስከ 5 ድረስ ማዘጋጀት ይችላሉ። \n\n""ደረጃ 5"" \n- በማሳወቂያ ዝርዝሩ አናት ላይ አሳይ \n- የሙሉ ማያ ገጽ ማቋረጥን ፍቀድ \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n""ደረጃ 4"" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n""ደረጃ 3"" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- በፍጹም አጮልቀው አይምልከቱ \n\n""ደረጃ 2"" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ እና ንዝረትን በፍጹም አይኑር \n\n""ደረጃ 1"" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ ወይም ንዝረትን በፍጹም አያደርጉ \n- ከመቆለፊያ ገጽ እና የሁኔታ አሞሌ ይደብቁ \n- በማሳወቂያ ዝርዝር ግርጌ ላይ አሳይ \n\n""ደረጃ 0"" \n- ሁሉንም የመተግበሪያው ማሳወቂያዎች ያግዱ" "ማሳወቂያዎች" "እነዚህን ማሳወቂያዎችን ከእንግዲህ አይመለከቷቸውም" - - + "አብዛኛውን ጊዜ እነዚህን ማሳወቂያዎች ያሰናብቷቸዋል። \nመታየታቸው ይቀጥል??" "እነዚህን ማሳወቂያዎች ማሳየት ይቀጥሉ?" "ማሳወቂያዎችን አስቁም" "ማሳየትን ቀጥል" diff --git a/packages/SystemUI/res/values-ar/config.xml b/packages/SystemUI/res/values-ar/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ar/config.xml +++ b/packages/SystemUI/res/values-ar/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-az/config.xml b/packages/SystemUI/res/values-az/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-az/config.xml +++ b/packages/SystemUI/res/values-az/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 17d7718b934154404f578d76c16b8fcff0cefba8..e00a2dd8d515b568099c54648502afc0c5282d2f 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -103,12 +103,9 @@ "kemaranı açın" "Yeni tapşırıq sxemi seçin" "Ləğv et" - - - - - - + "Barmaq izi ikonası" + "Tətbiq ikonası" + "Yardım mesajı bölməsi" "Uyğunluq zoom düyməsi." "Daha böyük ekranda uzaqlaşdır." "Bluetooth qoşulub." @@ -311,6 +308,8 @@ "Wi-Fi sönülüdür" "Wi-Fi Aktiv" "Heç bir Wi-Fi şəbəkəsi əlçatan deyil" + + "Yayım" "Yayım" "Adsız cihaz" @@ -327,9 +326,11 @@ "Qoşulur..." "Birləşmə" "Hotspot" - - - + "Aktiv edilir..." + + %d cihaz + %d cihaz + "Bildirişlər" "İşartı" "Mobil data" @@ -499,11 +500,24 @@ "İndi deaktiv edin" "Genişləndirin" "Yığcamlaşdırın" + "Çıxış cihazına keçin" "Ekrana sancaq taxıldı" "Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın." + + "Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri düyməsinə basıb saxlayın." + + + + + + "Anladım!" "Yox, çox sağ olun" + + + + "%1$s gizlədilsin?" "Ayarlarda onu aktivləşdirəcəyiniz vaxta qədər o, yenidən görünəcək." "Gizlədin" @@ -583,8 +597,7 @@ "Enerji bildiriş nəzarəti ilə, tətbiq bildirişləri üçün əhəmiyyət səviyyəsini 0-dan 5-ə kimi ayarlaya bilərsiniz. \n\n""Səviyyə 5"" \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n- Tam ekran kəsintisinə icazə verin \n- Hər zaman izləyin \n\n""Səviyyə 4"" \n- Tam ekran kəsintisinin qarşısını alın \n- Hər zaman izləyin \n\n""Level 3"" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n\n""Level 2"" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n\n""Səviyyə 1"" \n- Prevent full screen interruption \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n- Ekran kilidi və ya status panelindən gizlədin \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n\n""Səviyyə 0"" \n- Bütün bildirişləri tətbiqdən blok edin" "Bildirişlər" "Artıq bu bildirişləri görməyəcəkəsiniz" - - + "Adətən bu bildirişləri rədd edirsiniz. \nBildirişlər göstərilsin?" "Bu bildirişlər göstərilməyə davam edilsin?" "Bildirişləri dayandırın" "Göstərməyə davam edin" diff --git a/packages/SystemUI/res/values-b+sr+Latn/config.xml b/packages/SystemUI/res/values-b+sr+Latn/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/config.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-be/config.xml b/packages/SystemUI/res/values-be/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-be/config.xml +++ b/packages/SystemUI/res/values-be/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-bg/config.xml b/packages/SystemUI/res/values-bg/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-bg/config.xml +++ b/packages/SystemUI/res/values-bg/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-bn/config.xml b/packages/SystemUI/res/values-bn/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-bn/config.xml +++ b/packages/SystemUI/res/values-bn/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 4cbb5edbb5fecbbce2c0a215516241d6159f41a3..eb08f5094db987e50a8cf99a682dcd2d0c1e11ed 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -103,12 +103,9 @@ "ক্যামেরা খুলুন" "নতুন কার্য লেআউট বেছে নিন" "বাতিল করুন" - - - - - - + "আঙ্গুলের ছাপের আইকন" + "অ্যাপ্লিকেশনের আইকন" + "সহায়তার মেসেজ দেখানোর জায়গা" "সামঞ্জস্যের জুম বোতাম৷" "ছোট থেকে বৃহৎ স্ক্রীণে জুম করুন৷" "ব্লুটুথ সংযুক্ত হয়েছে৷" @@ -311,6 +308,8 @@ "ওয়াই-ফাই বন্ধ" "ওয়াই-ফাই চালু আছে" "কোনো ওয়াই-ফাই নেটওয়ার্ক উপলব্ধ নেই" + + "কাস্ট করুন" "কাস্ট করা হচ্ছে" "নামবিহীন ডিভাইস" @@ -327,9 +326,11 @@ "সংযুক্ত হচ্ছে..." "টেদারিং" "হটস্পট" - - - + "চালু করা হচ্ছে…" + + %dটি ডিভাইস + %dটি ডিভাইস + "বিজ্ঞপ্তিগুলি" "ফ্ল্যাশলাইট" "মোবাইল ডেটা" @@ -339,10 +340,8 @@ "%s ব্যবহৃত হয়েছে" "সীমা %s" "%s সতর্কতা" - - - - + "কাজের প্রোফাইল" + "বিজ্ঞপ্তি ও অ্যাপ বন্ধ আছে" "নাইট লাইট" "সূর্যাস্তে চালু হবে" "সূর্যোদয় পর্যন্ত" @@ -360,8 +359,7 @@ "নিরাপদ মোডে %s অক্ষম করা হয়েছে৷" "সবকিছু সাফ করুন" "বিভক্ত স্ক্রীন ব্যবহার করতে এখানে টেনে আনুন" - - + "অন্য অ্যাপে যেতে উপরের দিকে সোয়াইপ করুন" "অনুভূমিক স্প্লিট" "উল্লম্ব স্প্লিট" "কাস্টম স্প্লিট করুন" @@ -502,11 +500,25 @@ "এখনই বন্ধ করুন" "বড় করুন" "সঙ্কুচিত করুন" + + "স্ক্রিন পিন করা হয়েছে" "এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ফিরুন এবং ওভারভিউ স্পর্শ করে ধরে থাকুন।" + + "এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ওভারভিউ স্পর্শ করে ধরে থাকুন৷" + + + + + + "বুঝেছি" "না থাক" + + + + "%1$s লুকাবেন?" "আপনি পরের বার সেটিংস-এ এটি চালু করলে এটি উপস্থিত হবে" "লুকান" @@ -586,8 +598,7 @@ "পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি ব্যহবার করে, আপনি কোনও অ্যাপ্লিকেশনের বিজ্ঞপ্তির জন্য ০ থেকে ৫ পর্যন্ত একটি গুরুত্বের লেভেলকে সেট করতে পারবেন৷ \n\n""লেভেল ৫"" \n- বিজ্ঞপ্তি তালিকার শীর্ষে দেখায় \n- পূর্ণ স্ক্রিনের বাধাকে অনুমতি দেয় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n""লেভেল ৪"" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n""লেভেল ৩"" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n\n""লেভেল ২"" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n\n""লেভেল ১"" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n- লক স্ক্রিন এবং স্ট্যাটাস বার থেকে লুকায় \n- বিজ্ঞপ্তি তালিকার নীচের দিকে দেখায় \n\n""লেভেল ০"" \n- অ্যাপ্লিকেশন থেকে সমস্ত বিজ্ঞপ্তিকে অবরূদ্ধ করে" "বিজ্ঞপ্তি" "এই বিজ্ঞপ্তিগুলি আপনাকে আর দেখানো হবে না" - - + "এই বিজ্ঞপ্তিগুলিকে আপনি সাধারণত বাতিল করেন। \nসেগুলি দেখতে চান?" "এই বিজ্ঞপ্তিগুলি পরেও দেখে যেতে চান?" "বিজ্ঞপ্তি বন্ধ করুন" "দেখতে থাকুন" diff --git a/packages/SystemUI/res/values-bs/config.xml b/packages/SystemUI/res/values-bs/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-bs/config.xml +++ b/packages/SystemUI/res/values-bs/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 7f8d001cc2a86931306d90824aca4103aa8c5b7e..676ecd0fe3a43380f019209f93d110753d6b0205 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -104,12 +104,9 @@ "otvori kameru" "Odaberite novi raspored zadataka" "Otkaži" - - - - - - + "Ikona za otisak prsta" + "Ikona aplikacije" + "Prostor za poruku za pomoć" "Dugme za uvećavanje u slučaju nekompatibilnosti." "Uvećani prikaz manjeg ekrana na većem ekranu." "Bluetooth je povezan." @@ -210,13 +207,13 @@ "Uključen način rada u avionu." "Način rada u avionu je isključen." "Način rada u avionu je uključen." - "Opcija Ne ometaj je uključena, čut će se samo prioritetna obavještenja." - "Opcija Ne ometaj je uključena, potpuna tišina." - "Opcija Ne ometaj je uključena, čut će se samo alarmi." + "Način rada Ne ometaj je uključen, čut će se samo prioritetna obavještenja." + "Način rada Ne ometaj je uključen, potpuna tišina." + "Način rada Ne ometaj je uključen, čut će se samo alarmi." "Ne ometaj." - "Opcija Ne ometaj je isključena." - "Opcija Ne ometaj je isključena." - "Opcija Ne ometaj je uključena." + "Način rada Ne ometaj je isključen." + "Način rada Ne ometaj je isključen." + "Način rada Ne ometaj je uključen." "Bluetooth." "Bluetooth isključen." "Bluetooth uključen." @@ -313,6 +310,8 @@ "Wi-Fi isključen" "Wi-Fi uključen" "Nema dostupnih Wi-Fi mreža" + + "Emitiranje" "Prebacivanje" "Neimenovani uređaj" @@ -329,9 +328,12 @@ "Povezivanje..." "Dijeljenje veze" "Pristupna tačka" - - - + "Uključivanje…" + + %d uređaj + %d uređaja + %d uređaja + "Obavještenja" "Svjetiljka" "Prijenos podataka na mobilnoj mreži" @@ -341,10 +343,8 @@ "Iskorišteno %s" "Ograničenje %s" "Upozorenje %s" - - - - + "Radni profil" + "Isključena su obavještenja i aplikacije" "Noćno svjetlo" "Uključuje se u suton" "Do svitanja" @@ -362,8 +362,7 @@ "%s je onemogućena u sigurnom načinu rada." "Obriši sve" "Povucite ovdje za korištenje podijeljenog ekrana" - - + "Prevucite prema gore za promjenu aplikacije" "Podjela po horizontali" "Podjela po vertikali" "Prilagođena podjela" @@ -504,11 +503,25 @@ "Isključi sada" "Proširi" "Skupi" + + "Ekran je prikačen" "Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad." + + "Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Pregled." + + + + + + "Razumijem" "Ne, hvala" + + + + "Želite li sakriti %1$s?" "Pojavit će se sljedeći put kada opciju uključite u postavkama." "Sakrij" @@ -590,8 +603,7 @@ "Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n""Nivo 5"" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n""Nvio 4"" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n""Nivo 3"" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n""Nivo 2"" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n""Nivo 1"" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n""Nivo 0"" \n- Blokiraj sva obavještenja iz aplikacije" "Obavještenja" "Nećete više vidjeti ova obavještenja" - - + "Obično odbacujete ova obavještenja. \nNastaviti ih prikazivati?" "Nastaviti prikazivanje ovih obavještenja?" "Zaustavi obavještenja" "Nastavi prikazivanje" @@ -668,7 +680,7 @@ "Prikazati sa kontrolama jačine zvuka" "Ne ometaj" "Prečica za dugmad za Jačinu zvuka" - "Deaktiviraj režim Ne ometaj kada se zvuk pojača" + "Deaktiviraj način rada Ne ometaj kada se zvuk pojača" "Baterija" "Sat" "Slušalice s mikrofonom" @@ -802,10 +814,10 @@ "Prijenos podataka na mobilnoj mreži" "Wi-Fi veza je isključena" "Bluetooth je isključen" - "Opcija Ne ometaj je isključena" + "Način rada Ne ometaj je isključen" "Opciju Ne ometaju uključilo je automatsko pravilo (%s)." - "Opciju Ne ometaj uključila je aplikacija %s." - "Opciju Ne ometaj uključilo je automatsko pravilo ili aplikacija." + "Način rada Ne ometaj uključila je aplikacija %s." + "Način rada Ne ometaj uključilo je automatsko pravilo ili aplikacija." "Do %s" "Zadrži" "Zamijeni" diff --git a/packages/SystemUI/res/values-ca/config.xml b/packages/SystemUI/res/values-ca/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ca/config.xml +++ b/packages/SystemUI/res/values-ca/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 8d61a9a248802d8a5855adb40e0c17ae1b0de895..4eff30d6527ec5643283e599bb488c40ff84145b 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -33,13 +33,13 @@ "Continu" "Notificacions" "Queda poca bateria" - "Queda poca bateria. Activa el mode Estalvi de bateria." + "Queda poca bateria. Activa el mode d\'estalvi de bateria." "Queda un %s." "Queda un %s; temps restant aproximat segons l\'ús que en fas: %s" "Queda un %s; temps restant aproximat: %s" "Queda un %s. La funció Estalvi de bateria està activada." - "Pujada d\'USB no admesa.\nUtilitza només el carregador proporcionat." - "La pujada per USB no és compatible." + "Càrrega per USB no admesa.\nUtilitza només el carregador proporcionat." + "La càrrega per USB no és compatible." "Fes servir només el carregador proporcionat amb el dispositiu." "Configuració" "Vols activar la funció Estalvi de bateria?" @@ -103,12 +103,9 @@ "obre la càmera" "Selecciona el disseny de la tasca nova" "Cancel·la" - - - - - - + "Icona d\'empremta digital" + "Icona d\'aplicació" + "Àrea de missatge d\'ajuda" "Botó de zoom de compatibilitat." "Amplia menys com més gran sigui la pantalla." "Bluetooth connectat." @@ -311,6 +308,8 @@ "Wi-Fi desconnectada" "La Wi-Fi està activada" "No hi ha cap xarxa Wi-Fi disponible" + + "Emet" "En emissió" "Dispositiu sense nom" @@ -327,9 +326,11 @@ "S\'està connectant..." "Compartició de xarxa" "Punt d\'accés Wi-Fi" - - - + "S\'està activant..." + + %d dispositius + %d dispositiu + "Notificacions" "Llanterna" "Dades mòbils" @@ -339,10 +340,8 @@ "Utilitzats: %s" "Límit: %s" "Advertiment: %s" - - - - + "Perfil professional" + "Les notificacions i les aplicacions estan desactivades" "Llum nocturna" "A la posta de sol" "Fins a l\'alba" @@ -360,8 +359,7 @@ "En mode segur, l\'aplicació %s està desactivada." "Esborra-ho tot" "Arrossega-ho aquí per utilitzar la pantalla dividida" - - + "Llisca cap amunt per canviar d\'aplicació" "Divisió horitzontal" "Divisió vertical" "Divisió personalitzada" @@ -370,7 +368,7 @@ "Divideix la pantalla cap a la dreta" "Carregada" "S\'està carregant" - "%s per completar la pujada" + "%s per completar la càrrega" "No s\'està carregant" "És possible que la xarxa\nestigui controlada" "Cerca" @@ -397,9 +395,9 @@ "Silenci\ntotal" "Només\ninterr. prior." "Només\nalarmes" - "Carregant (%s per completar la pujada)" - "Pujada ràpida (%s per completar-se)" - "Pujada lenta (%s per completar-se)" + "Carregant (%s per completar la càrrega)" + "Càrrega ràpida (%s per completar-se)" + "Càrrega lenta (%s per completar-se)" "Canvia d\'usuari" "Canvia d\'usuari. Usuari actual: %s" "Usuari actual: %s" @@ -502,11 +500,25 @@ "Desactiva ara" "Amplia" "Replega" + + "La pantalla està fixada" "Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premudes els botons Enrere i Aplicacions recents." + + "Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premut el botó Aplicacions recents." + + + + + + "D\'acord" "No, gràcies" + + + + "Vols amagar %1$s?" "Tornarà a mostrar-se la propera vegada que l\'activis a la configuració." "Amaga" @@ -586,8 +598,7 @@ "Amb els controls de notificació millorats, pots establir un nivell d\'importància d\'entre 0 i 5 per a les notificacions d\'una aplicació. \n\n""Nivell 5"" \n- Mostra les notificacions a la part superior de la llista \n- Permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n""Nivell 4"" \n- No permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n""Nivell 3"" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n\n""Nivell 2"" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- Les notificacions no poden emetre sons ni vibracions \n\n""Nivell 1"" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- No activa mai el so ni la vibració \n- Amaga les notificacions de la pantalla de bloqueig i de la barra d\'estat \n- Mostra les notificacions a la part inferior de la llista \n\n""Nivell 0"" \n- Bloqueja totes les notificacions de l\'aplicació" "Notificacions" "Ja no veuràs aquestes notificacions" - - + "Normalment ignores aquestes notificacions. \nVols que es continuïn mostrant?" "Vols continuar rebent aquestes notificacions?" "Deixa d\'enviar notificacions" "Continua rebent" @@ -614,7 +625,7 @@ %d minut "Consum de la bateria" - "La funció Estalvi de bateria no està disponible durant la pujada" + "La funció Estalvi de bateria no està disponible durant la càrrega" "Estalvi de bateria" "Redueix el rendiment i les dades en segon pla" "Botó %1$s" diff --git a/packages/SystemUI/res/values-cs/config.xml b/packages/SystemUI/res/values-cs/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-cs/config.xml +++ b/packages/SystemUI/res/values-cs/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 3c3e1d42c7bde2cf32f1ca7f6b1e3d4bfbbaa18d..faa1f1f5e0830a0bac6ad97fb49be1bb43c3e87b 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -105,12 +105,9 @@ "spustit fotoaparát" "Vybrat nové rozvržení úkolů" "Zrušit" - - - - - - + "Ikona otisku prstu" + "Ikona aplikace" + "Oblast pro zprávu nápovědy" "Tlačítko úpravy velikosti z důvodu kompatibility" "Zvětšit menší obrázek na větší obrazovku." "Rozhraní Bluetooth je připojeno." @@ -317,6 +314,8 @@ "Wi-Fi vypnuta" "Wi-Fi je zapnutá" "Žádné sítě Wi-Fi nejsou k dispozici" + + "Odeslat" "Odesílání" "Nepojmenované zařízení" @@ -333,9 +332,13 @@ "Připojování..." "Sdílené připojení" "Hotspot" - - - + "Zapínání..." + + %d zařízení + %d zařízení + %d zařízení + %d zařízení + "Oznámení" "Svítilna" "Mobilní data" @@ -345,10 +348,8 @@ "Využito: %s" "Limit: %s" "Upozornění při %s" - - - - + "Pracovní profil" + "Oznámení a aplikace jsou vypnuty" "Noční režim" "Zapnout při soumraku" "Do svítání" @@ -366,8 +367,7 @@ "Aplikace %s je v nouzovém režimu zakázána." "Vymazat vše" "Rozdělenou obrazovku můžete použít přetažením zde" - - + "Přejetím nahoru přepnete aplikace" "Vodorovné rozdělení" "Vertikální rozdělení" "Vlastní rozdělení" @@ -508,11 +508,24 @@ "Vypnout" "Rozbalit" "Sbalit" + "Přepnout zařízení pro výstup" "Obrazovka je připnuta" "Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítek Zpět a Přehled." + + "Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítka Přehled." + + + + + + "Rozumím" "Ne, děkuji" + + + + "Skrýt %1$s?" "Tato položka se znovu zobrazí, až ji v nastavení znovu zapnete." "Skrýt" @@ -592,8 +605,7 @@ "Rozšířené ovládací prvky oznámení umožňují nastavit úroveň důležitosti oznámení aplikace od 0 do 5. \n\n""Úroveň 5"" \n– Zobrazit na začátku seznamu oznámení \n– Povolit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n""Úroveň 4"" \n– Zabránit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n""Úroveň 3"" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n\n""Úroveň 2"" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat žádný zvukový signál ani nevibrovat \n\n""Úroveň 1"" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat zvukový signál ani nevibrovat \n– Skrýt z obrazovky uzamčení a stavového řádku \n– Zobrazovat na konci seznamu oznámení \n\n"";Úroveň 0"" \n– Blokovat všechna oznámení z aplikace" "Oznámení" "Tato oznámení již nebudete dostávat" - - + "Tato oznámení obvykle odmítáte. \nChcete je nadále zobrazovat?" "Mají se tato oznámení nadále zobrazovat?" "Přestat zobrazovat oznámení" "Nadále zobrazovat" diff --git a/packages/SystemUI/res/values-da/config.xml b/packages/SystemUI/res/values-da/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-da/config.xml +++ b/packages/SystemUI/res/values-da/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-de/config.xml b/packages/SystemUI/res/values-de/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-de/config.xml +++ b/packages/SystemUI/res/values-de/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-el/config.xml b/packages/SystemUI/res/values-el/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-el/config.xml +++ b/packages/SystemUI/res/values-el/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-en-rAU/config.xml b/packages/SystemUI/res/values-en-rAU/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-en-rAU/config.xml +++ b/packages/SystemUI/res/values-en-rAU/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 3f6d5e5fffd9ee6afc4fde6bc71ab6e33c93f950..3e9e3a2349e3d78602c5befb032f9dbe9db0e595 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -103,12 +103,9 @@ "open camera" "Select new task layout" "Cancel" - - - - - - + "Fingerprint icon" + "Application icon" + "Help message area" "Compatibility zoom button." "Zoom smaller to larger screen." "Bluetooth connected." @@ -311,6 +308,8 @@ "Wi-Fi Off" "Wi-Fi On" "No Wi-Fi networks available" + + "Cast" "Casting" "Unnamed device" @@ -327,9 +326,11 @@ "Connecting..." "Tethering" "Hotspot" - - - + "Turning on..." + + %d devices + %d device + "Notifications" "Torch" "Mobile data" @@ -499,11 +500,24 @@ "Turn off now" "Expand" "Collapse" + "Switch output device" "Screen is pinned" "This keeps it in view until you unpin. Touch & hold Back and Overview to unpin." + + "This keeps it in view until you unpin. Touch & hold Overview to unpin." + + + + + + "Got it" "No, thanks" + + + + "Hide %1$s?" "It will reappear the next time you turn it on in settings." "Hide" @@ -583,8 +597,7 @@ "With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n""Level 5"" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n""Level 4"" \n- Prevent full screen interruption \n- Always peek \n\n""Level 3"" \n- Prevent full screen interruption \n- Never peek \n\n""Level 2"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n""Level 1"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n""Level 0"" \n- Block all notifications from the app" "Notifications" "You won\'t see these notifications anymore" - - + "You usually dismiss these notifications. \nKeep showing them?" "Keep showing these notifications?" "Stop notifications" "Keep showing" diff --git a/packages/SystemUI/res/values-en-rCA/config.xml b/packages/SystemUI/res/values-en-rCA/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-en-rCA/config.xml +++ b/packages/SystemUI/res/values-en-rCA/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index d49c25abafdcff4453f6ad167e43c63495e8fca4..e5f4ecedc67900837e6e121f212ae943e7c46f5a 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -103,12 +103,9 @@ "open camera" "Select new task layout" "Cancel" - - - - - - + "Fingerprint icon" + "Application icon" + "Help message area" "Compatibility zoom button." "Zoom smaller to larger screen." "Bluetooth connected." @@ -311,6 +308,8 @@ "Wi-Fi Off" "Wi-Fi On" "No Wi-Fi networks available" + + "Cast" "Casting" "Unnamed device" @@ -327,9 +326,11 @@ "Connecting..." "Tethering" "Hotspot" - - - + "Turning on..." + + %d devices + %d device + "Notifications" "Flashlight" "Mobile data" @@ -499,11 +500,24 @@ "Turn off now" "Expand" "Collapse" + "Switch output device" "Screen is pinned" "This keeps it in view until you unpin. Touch & hold Back and Overview to unpin." + + "This keeps it in view until you unpin. Touch & hold Overview to unpin." + + + + + + "Got it" "No, thanks" + + + + "Hide %1$s?" "It will reappear the next time you turn it on in settings." "Hide" @@ -583,8 +597,7 @@ "With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n""Level 5"" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n""Level 4"" \n- Prevent full screen interruption \n- Always peek \n\n""Level 3"" \n- Prevent full screen interruption \n- Never peek \n\n""Level 2"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n""Level 1"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n""Level 0"" \n- Block all notifications from the app" "Notifications" "You won\'t see these notifications anymore" - - + "You usually dismiss these notifications. \nKeep showing them?" "Keep showing these notifications?" "Stop notifications" "Keep showing" diff --git a/packages/SystemUI/res/values-en-rGB/config.xml b/packages/SystemUI/res/values-en-rGB/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-en-rGB/config.xml +++ b/packages/SystemUI/res/values-en-rGB/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 3f6d5e5fffd9ee6afc4fde6bc71ab6e33c93f950..3e9e3a2349e3d78602c5befb032f9dbe9db0e595 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -103,12 +103,9 @@ "open camera" "Select new task layout" "Cancel" - - - - - - + "Fingerprint icon" + "Application icon" + "Help message area" "Compatibility zoom button." "Zoom smaller to larger screen." "Bluetooth connected." @@ -311,6 +308,8 @@ "Wi-Fi Off" "Wi-Fi On" "No Wi-Fi networks available" + + "Cast" "Casting" "Unnamed device" @@ -327,9 +326,11 @@ "Connecting..." "Tethering" "Hotspot" - - - + "Turning on..." + + %d devices + %d device + "Notifications" "Torch" "Mobile data" @@ -499,11 +500,24 @@ "Turn off now" "Expand" "Collapse" + "Switch output device" "Screen is pinned" "This keeps it in view until you unpin. Touch & hold Back and Overview to unpin." + + "This keeps it in view until you unpin. Touch & hold Overview to unpin." + + + + + + "Got it" "No, thanks" + + + + "Hide %1$s?" "It will reappear the next time you turn it on in settings." "Hide" @@ -583,8 +597,7 @@ "With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n""Level 5"" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n""Level 4"" \n- Prevent full screen interruption \n- Always peek \n\n""Level 3"" \n- Prevent full screen interruption \n- Never peek \n\n""Level 2"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n""Level 1"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n""Level 0"" \n- Block all notifications from the app" "Notifications" "You won\'t see these notifications anymore" - - + "You usually dismiss these notifications. \nKeep showing them?" "Keep showing these notifications?" "Stop notifications" "Keep showing" diff --git a/packages/SystemUI/res/values-en-rIN/config.xml b/packages/SystemUI/res/values-en-rIN/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-en-rIN/config.xml +++ b/packages/SystemUI/res/values-en-rIN/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 3f6d5e5fffd9ee6afc4fde6bc71ab6e33c93f950..3e9e3a2349e3d78602c5befb032f9dbe9db0e595 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -103,12 +103,9 @@ "open camera" "Select new task layout" "Cancel" - - - - - - + "Fingerprint icon" + "Application icon" + "Help message area" "Compatibility zoom button." "Zoom smaller to larger screen." "Bluetooth connected." @@ -311,6 +308,8 @@ "Wi-Fi Off" "Wi-Fi On" "No Wi-Fi networks available" + + "Cast" "Casting" "Unnamed device" @@ -327,9 +326,11 @@ "Connecting..." "Tethering" "Hotspot" - - - + "Turning on..." + + %d devices + %d device + "Notifications" "Torch" "Mobile data" @@ -499,11 +500,24 @@ "Turn off now" "Expand" "Collapse" + "Switch output device" "Screen is pinned" "This keeps it in view until you unpin. Touch & hold Back and Overview to unpin." + + "This keeps it in view until you unpin. Touch & hold Overview to unpin." + + + + + + "Got it" "No, thanks" + + + + "Hide %1$s?" "It will reappear the next time you turn it on in settings." "Hide" @@ -583,8 +597,7 @@ "With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n""Level 5"" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n""Level 4"" \n- Prevent full screen interruption \n- Always peek \n\n""Level 3"" \n- Prevent full screen interruption \n- Never peek \n\n""Level 2"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n""Level 1"" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n""Level 0"" \n- Block all notifications from the app" "Notifications" "You won\'t see these notifications anymore" - - + "You usually dismiss these notifications. \nKeep showing them?" "Keep showing these notifications?" "Stop notifications" "Keep showing" diff --git a/packages/SystemUI/res/values-en-rXC/config.xml b/packages/SystemUI/res/values-en-rXC/config.xml index f015d9b378d43f5bc5971f58d57c747588879689..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-en-rXC/config.xml +++ b/packages/SystemUI/res/values-en-rXC/config.xml @@ -22,6 +22,5 @@ - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎com.android.launcher3/com.android.quickstep.TouchInteractionService‎‏‎‎‏‎" diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 0571c1ff9b0dcc484de1cddd23bcae6d8cad466e..35cef208cb3096ca106e37fd298e8bffbafe7ef3 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -103,12 +103,9 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‎open camera‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎Select new task layout‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎Cancel‎‏‎‎‏‎" - - - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎Fingerprint icon‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎Application icon‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎Help message area‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎Compatibility zoom button.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎Zoom smaller to larger screen.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎Bluetooth connected.‎‏‎‎‏‎" @@ -311,6 +308,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎Wi-Fi Off‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎Wi-Fi On‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎No Wi-Fi networks available‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎Cast‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎Casting‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎Unnamed device‎‏‎‎‏‎" @@ -327,9 +326,11 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎Connecting...‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‎Tethering‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎Hotspot‎‏‎‎‏‎" - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎Turning on...‎‏‎‎‏‎" + + ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‎%d devices‎‏‎‎‏‎ + ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‎%d device‎‏‎‎‏‎ + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎Notifications‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‎Flashlight‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎Mobile data‎‏‎‎‏‎" @@ -499,11 +500,24 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎Turn off now‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‏‎Expand‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎Collapse‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‎‎Switch output device‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‏‎Screen is pinned‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‎This keeps it in view until you unpin. Touch & hold Back and Overview to unpin.‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎This keeps it in view until you unpin. Touch & hold Overview to unpin.‎‏‎‎‏‎" + + + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎Got it‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‎No thanks‎‏‎‎‏‎" + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎Hide ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎?‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎It will reappear the next time you turn it on in settings.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎Hide‎‏‎‎‏‎" @@ -583,8 +597,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎Level 5‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Show at the top of the notification list ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Allow full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Always peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎Level 4‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Always peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎Level 3‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎Level 2‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never make sound and vibration ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎Level 1‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never make sound or vibrate ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Hide from lock screen and status bar ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Show at the bottom of the notification list ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎Level 0‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Block all notifications from the app‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎Notifications‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎You won\'t see these notifications anymore‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‎You usually dismiss these notifications. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Keep showing them?‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‎Keep showing these notifications?‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎Stop notifications‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎Keep showing‎‏‎‎‏‎" diff --git a/packages/SystemUI/res/values-es-rUS/config.xml b/packages/SystemUI/res/values-es-rUS/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-es-rUS/config.xml +++ b/packages/SystemUI/res/values-es-rUS/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-es/config.xml b/packages/SystemUI/res/values-es/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-es/config.xml +++ b/packages/SystemUI/res/values-es/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 5cc6ab6a0b2c065988e1f29506a2914543b9bfc7..2a409a51574e25be6ee34243e946b81b8948824b 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -88,7 +88,7 @@ "Inicio" "Menú" "Accesibilidad" - "Girar la pantalla" + "Girar pantalla" "Aplicaciones recientes" "Buscar" "Cámara" @@ -103,12 +103,9 @@ "abrir cámara" "Seleccionar diseño de tarea nueva" "Cancelar" - - - - - - + "Icono de huella digital" + "Icono de aplicación" + "Área de mensaje de ayuda" "Botón de zoom de compatibilidad" "Zoom de pantalla más pequeña a más grande" "Bluetooth conectado" @@ -313,6 +310,8 @@ "Wi-Fi desactivado" "Wi-Fi activada" "No hay ninguna red Wi-Fi disponible" + + "Enviar" "Enviando" "Dispositivo sin nombre" @@ -329,9 +328,11 @@ "Conectando..." "Compartir conexión" "Zona Wi-Fi" - - - + "Activando..." + + %d dispositivos + %d dispositivo + "Notificaciones" "Linterna" "Datos móviles" @@ -341,10 +342,8 @@ "%s usado" "Límite de %s" "Advertencia de %s" - - - - + "Perfil de trabajo" + "Las notificaciones y las aplicaciones están desactivadas" "Luz nocturna" "Al atardecer" "Hasta el amanecer" @@ -362,8 +361,7 @@ "La aplicación %s se ha inhabilitado en modo seguro." "Borrar todo" "Arrastra hasta aquí para utilizar la pantalla dividida" - - + "Desliza el dedo hacia arriba para cambiar de aplicación" "División horizontal" "División vertical" "División personalizada" @@ -504,11 +502,24 @@ "Desactivar" "Mostrar" "Ocultar" + "Cambiar dispositivo de salida" "Pantalla fijada" "La pantalla se mantiene visible hasta que dejas de fijarla. Para ello, mantén pulsados los botones Atrás y Aplicaciones recientes." + + "La pantalla se mantiene visible hasta que dejas de fijarla. Para ello, mantén pulsado el botón Aplicaciones recientes." + + + + + + "Entendido" "No, gracias" + + + + "¿Ocultar %1$s?" "Volverá a aparecer la próxima vez que actives esta opción en Ajustes." "Ocultar" @@ -588,8 +599,7 @@ "Los controles de energía de las notificaciones permiten establecer un nivel de importancia de 0 a 5 para las notificaciones de las aplicaciones. \n\n""Nivel 5"" \n- Mostrar en la parte superior de la lista de notificaciones \n- Permitir interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n""Nivel 4"" \n- Evitar interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n""Nivel 3"" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n\n""Nivel 2"" \n- Evitar interrumpir en el modo de pantalla completa\n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n\n""Nivel 1"" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n- Ocultar de la pantalla de bloqueo y de la barra de estado \n- Mostrar en la parte inferior de la lista de notificaciones \n\n""Nivel 0"" \n- Bloquear todas las notificaciones de la aplicación" "Notificaciones" "No volverás a ver estas notificaciones" - - + "Normalmente ignoras estas notificaciones. \n¿Quieres seguir viéndolas?" "¿Quieres seguir viendo estas notificaciones?" "Detener las notificaciones" "Seguir mostrando" diff --git a/packages/SystemUI/res/values-et/config.xml b/packages/SystemUI/res/values-et/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-et/config.xml +++ b/packages/SystemUI/res/values-et/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-eu/config.xml b/packages/SystemUI/res/values-eu/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-eu/config.xml +++ b/packages/SystemUI/res/values-eu/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-fa/config.xml b/packages/SystemUI/res/values-fa/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-fa/config.xml +++ b/packages/SystemUI/res/values-fa/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-fi/config.xml b/packages/SystemUI/res/values-fi/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-fi/config.xml +++ b/packages/SystemUI/res/values-fi/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 34072db40a24de59cca01c0f433738f1650c1c3d..e7fcb43e0ab25afe1e548fe2976076d9ddbe581c 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -103,12 +103,9 @@ "avaa kamera" "Valitse uusi tehtävien asettelu" "Peruuta" - - - - - - + "Sormenjälkikuvake" + "Sovelluskuvake" + "Ohjeviestialue" "Yhteensopivuuszoomaus-painike." "Zoomaa pienemmältä suuremmalle ruudulle." "Bluetooth yhdistetty." @@ -311,6 +308,8 @@ "Wi-Fi-yhteys pois käytöstä" "Wi-Fi on käytössä" "Ei Wi-Fi-verkkoja käytettävissä" + + "Suoratoisto" "Lähetetään" "Nimetön laite" @@ -327,9 +326,11 @@ "Yhdistetään…" "Jaettu yhteys" "Hotspot" - - - + "Otetaan käyttöön…" + + %d laitetta + %d laite + "Ilmoitukset" "Taskulamppu" "Mobiilidata" @@ -339,10 +340,8 @@ "käytetty %s" "kiintiö %s" "%s – varoitus" - - - - + "Työprofiili" + "Ilmoitukset ja sovellukset on poistettu käytöstä" "Yövalo" "Auringon laskiessa" "Auringonnousuun" @@ -360,8 +359,7 @@ "%s on poistettu käytöstä vikasietotilassa." "Tyhjennä kaikki" "Jaa näyttö vetämällä tähän." - - + "Vaihda sovellusta pyyhkäisemällä ylös" "Vaakasuuntainen jako" "Pystysuuntainen jako" "Muokattu jako" @@ -502,11 +500,24 @@ "Sammuta nyt" "Laajenna." "Tiivistä." + "Vaihda toistolaitetta" "Näyttö on kiinnitetty" "Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Viimeisimmät." + + "Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Viimeisimmät." + + + + + + "Selvä" "Ei kiitos" + + + + "Piilotetaanko %1$s?" "Se tulee takaisin näkyviin, kun seuraavan kerran otat sen käyttöön asetuksissa." "Piilota" @@ -586,8 +597,7 @@ "Ilmoitusten tehohallinnan avulla voit määrittää sovelluksen ilmoituksille tärkeystason väliltä 0–5. \n\n""Taso 5"" \n– Ilmoitukset näytetään ilmoitusluettelon yläosassa \n– Näkyminen koko näytön tilassa sallitaan \n– Ilmoitukset kurkistavat aina näytölle\n\n""Taso 4"" \n– Näkyminen koko näytön tilassa estetään \n– Ilmoitukset kurkistavat aina näytölle \n\n""Taso 3"" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n\n""Taso 2"" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n\n""Taso 1"" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n– Ilmoitukset piilotetaan lukitusnäytöltä ja tilapalkista \n– Ilmoitukset näytetään ilmoitusluettelon alaosassa \n\n""Taso 0"" \n– Kaikki sovelluksen ilmoitukset estetään" "Ilmoitukset" "Et näe näitä ilmoituksia enää" - - + "Hylkäät yleensä nämä ilmoitukset. \nHaluatko, että niitä näytetään myös jatkossa?" "Jatketaanko näiden ilmoitusten näyttämistä?" "Lopeta ilmoitukset" "Jatka näyttämistä" diff --git a/packages/SystemUI/res/values-fr-rCA/config.xml b/packages/SystemUI/res/values-fr-rCA/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-fr-rCA/config.xml +++ b/packages/SystemUI/res/values-fr-rCA/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 16a4eac8af1d8fe4e46766ae90d37d77f2fd63d8..56ca97c2a67f84d2d7670bca824cbeed4abe427b 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -88,6 +88,7 @@ "Domicile" "Menu" "Accessibilité" + "Faire pivoter l\'écran" "Aperçu" "Rechercher" "Appareil photo" @@ -102,6 +103,9 @@ "Ouvrir l\'appareil photo" "Sélectionner un nouveau format de tâche" "Annuler" + "Icône d\'empreinte digitale" + "Icône de l\'application" + "Zone de message d\'aide" "Bouton \"Zoom de compatibilité\"" "Zoom de compatibilité avec la taille de l\'écran" "Bluetooth connecté" @@ -180,7 +184,8 @@ "Sonnerie en mode silencieux" - "Mode Travail" + + "Supprimer %s." "Application \"%s\" ignorée." "Toutes les applications récentes ont été supprimées." @@ -277,6 +282,10 @@ "Bluetooth (%d appareils)" "BLUETOOTH DÉSACTIVÉ" "Aucun des appareils associés n\'est disponible" + "Pile : %s" + "Audio" + "Écouteurs" + "Entrée" "Luminosité" "Rotation automatique" "Rotation automatique de l\'écran" @@ -301,6 +310,8 @@ "Wi-Fi désactivé" "Wi-Fi activé" "Aucun réseau Wi-Fi à proximité" + + "Diffuser" "Diffusion" "Appareil sans nom" @@ -317,6 +328,11 @@ "Connexion en cours…" "Partage de connexion" "Point d\'accès sans fil" + "Activation en cours…" + + %d appareil + %d appareils + "Notifications" "Lampe de poche" "Données cellulaires" @@ -326,8 +342,13 @@ "Quantité de données utilisées :%s" "Limite : %s" "Avertissement : %s" - "Mode Travail" + "Profil professionnel" + "Les notifications et les applications sont désactivées" "Éclairage nocturne" + "Au coucher du soleil" + "Jusqu\'au lev. soleil" + "Actif à %s" + "Jusqu\'à %s" "NFC" "NFC désactivée" "NFC activée" @@ -340,6 +361,7 @@ "%s est désactivée en mode sans échec." "Effacer tout" "Glissez l\'élément ici pour utiliser l\'écran partagé" + "Balayez vers le haut pour changer d\'application" "Séparation horizontale" "Séparation verticale" "Séparation personnalisée" @@ -480,11 +502,24 @@ "Désactiver maintenant" "Développer" "Réduire" + "Changer d\'appareil de sortie" "L\'écran est épinglé" "Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Retour » et « Aperçu »." + + "Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Aperçu »." + + + + + + "OK" "Non, merci" + + + + "Masquer %1$s?" "Cet élément réapparaîtra la prochaine fois que vous l\'activerez dans les paramètres." "Masquer" @@ -564,9 +599,10 @@ "Avec les réglages avancés des notifications, vous pouvez définir un degré d\'importance de 0 à 5 pour les notifications d\'une application. \n\n""Niveau 5"" \n- Afficher dans le haut de la liste des notifications \n- Autoriser les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n""Niveau 4"" \n- Empêcher les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n""Niveau 3"" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n\n""Niveau 2"" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n\n""Niveau 1"" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n- Masquer de l\'écran de verrouillage et de la barre d\'état status bar \n- Afficher dans le bas de la liste des notifications \n\n""Level 0"" \n- Bloquer toutes les notifications de l\'application" "Notifications" "Vous ne verrez plus ces notifications" + "Vous ignorez habituellement ces notifications. \nSouhaitez-vous continuer à les afficher?" "Continuer à afficher ces notifications?" "Arrêter les notifications" - "Continuez à afficher" + "Continuer à afficher" "Continuer à afficher les notifications de cette application?" "Ces notifications ne peuvent pas être désactivées" "Les paramètres des notifications pour %1$s sont ouverts" @@ -658,7 +694,8 @@ "Presse-papiers" "Code de touche" "Sélecteur de clavier" - "Aucun" + "Suggestion de rotation" + "Aucun" "Normale" @@ -782,4 +819,10 @@ "Touchez pour afficher des détails sur l\'utilisation de la pile et des données" "Désactiver les données cellulaires?" "Une application obscurcit une demande d\'autorisation, alors Paramètres ne peut pas vérifier votre réponse." + "Autoriser %1$s à afficher %2$s tranches?" + "- Il peut lire de l\'information de %1$s" + "- Il peut effectuer des actions dans %1$s" + "Autoriser %1$s à afficher des tranches de n\'importe quelle application" + "Autoriser" + "Refuser" diff --git a/packages/SystemUI/res/values-fr/config.xml b/packages/SystemUI/res/values-fr/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-fr/config.xml +++ b/packages/SystemUI/res/values-fr/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-gl/config.xml b/packages/SystemUI/res/values-gl/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-gl/config.xml +++ b/packages/SystemUI/res/values-gl/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-gu/config.xml b/packages/SystemUI/res/values-gu/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-gu/config.xml +++ b/packages/SystemUI/res/values-gu/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 27d3ba86f91af215dc12b91c66af47d75ab54218..7c530cd807235c826e07c66c569aa7b2dd4a9eb0 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -103,12 +103,9 @@ "કૅમેરો ખોલો" "નવું કાર્ય લેઆઉટ પસંદ કરો" "રદ કરો" - - - - - - + "ફિંગરપ્રિન્ટનું આઇકન" + "ઍપ્લિકેશનનું આઇકન" + "સહાય સંદેશનું ક્ષેત્ર" "સુસંગતતા ઝૂમ બટન." "નાનીથી મોટી સ્ક્રીન પર ઝૂમ કરો." "બ્લૂટૂથ કનેક્ટ થયું." @@ -311,6 +308,8 @@ "વાઇ-ફાઇ બંધ" "વાઇ-ફાઇ ચાલુ" "કોઈ વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ નથી" + + "કાસ્ટ કરો" "કાસ્ટ કરી રહ્યાં છે" "અનામાંકિત ઉપકરણ" @@ -327,9 +326,11 @@ "કનેક્ટ કરી રહ્યું છે..." "ટિથરિંગ" "હૉટસ્પૉટ" - - - + "ચાલુ કરી રહ્યાં છીએ…" + + %d ઉપકરણ + %d ઉપકરણો + "નોટિફિકેશનો" "ફ્લેશલાઇટ" "મોબાઇલ ડેટા" @@ -339,10 +340,8 @@ "%s વાપર્યો" "%s મર્યાદા" "%s ચેતવણી" - - - - + "કાર્યાલયની પ્રોફાઇલ" + "નોટિફિકેશન અને ઍપ બંધ છે" "રાત્રિ પ્રકાશ" "સૂર્યાસ્ત વખતે" "સૂર્યોદય સુધી" @@ -360,8 +359,7 @@ "સુરક્ષિત મોડમાં %s અક્ષમ કરેલ છે." "બધું સાફ કરો" "વિભાજિત સ્ક્રીનનો ઉપયોગ કરવા માટે અહીં ખેંચો" - - + "ઍપ સ્વિચ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો" "આડું વિભક્ત કરો" "ઊભું વિભક્ત કરો" "કસ્ટમ વિભક્ત કરો" @@ -502,11 +500,25 @@ "હમણાં બંધ કરો" "વિસ્તૃત કરો" "સંકુચિત કરો" + + "સ્ક્રીન પિન કરેલ છે" "તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. અનપિન કરવા માટે પાછળ અને ઝલકને સ્પર્શ કરી રાખો." + + "તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યક્ષમ રાખે છે. અનપિન કરવા માટે ઝલકને સ્પર્શ કરી રાખો." + + + + + + "સમજાઈ ગયું" "ના, આભાર" + + + + "%1$s ને છુપાવીએ?" "તે સેટિંગ્સમાં તમે તેને ચાલુ કરશો ત્યારે આગલી વખતે ફરીથી દેખાશે." "છુપાવો" @@ -586,8 +598,7 @@ "પાવર સૂચના નિયંત્રણો સાથે, તમે ઍપની સૂચનાઓ માટે 0 થી 5 સુધીના મહત્વના સ્તરને સેટ કરી શકો છો. \n\n""સ્તર 5"" \n- સૂચના સૂચિની ટોચ પર બતાવો \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n""સ્તર 4"" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n""સ્તર 3"" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n\n""સ્તર 2"" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n\n""સ્તર 1"" \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n- લૉક સ્ક્રીન અને સ્ટેટસ બારથી છુપાવો \n- સૂચના સૂચિના તળિયા પર બતાવો \n\n""સ્તર 0"" \n- ઍપની તમામ સૂચનાઓને બ્લૉક કરો" "નોટિફિકેશનો" "તમને હવેથી આ નોટિફિકેશન દેખાશે નહીં" - - + "તમે સામાન્ય રીતે આ નોટીફિકેશનને છોડી દો છો. \nતેમને બતાવવાનું ચાલુ રાખીએ?" "આ નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?" "નોટિફિકેશન બંધ કરો" "બતાવવાનું ચાલુ રાખો" diff --git a/packages/SystemUI/res/values-hi/config.xml b/packages/SystemUI/res/values-hi/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-hi/config.xml +++ b/packages/SystemUI/res/values-hi/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index bb2e897ba419b2be3373a1d3f123dd44e527766a..379d1abc4b4913b5d5171d832f38eefb4e489957 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -103,12 +103,9 @@ "कैमरा खोलें" "नया कार्य लेआउट चुनें" "रद्द करें" - - - - - - + "फ़िंगरप्रिंट आइकॉन" + "ऐप्लिकेशन आइकॉन" + "सहायता का मैसेज दिखाने की जगह" "संगतता ज़ूम बटन." "छोटी से बड़ी स्‍क्रीन पर ज़ूम करें." "ब्लूटूथ कनेक्ट किया गया." @@ -311,6 +308,8 @@ "वाई-फ़ाई बंद" "वाई-फ़ाई चालू है" "कोई भी वाई-फ़ाई नेटवर्क उपलब्‍ध नहीं है" + + "कास्ट करें" "कास्टिंग" "अनाम डिवाइस" @@ -327,9 +326,11 @@ "कनेक्ट हो रहा है..." "टेदरिंग" "हॉटस्पॉट" - - - + "चालू किया जा रहा है..." + + %d डिवाइस + %d डिवाइस + "सूचनाएं" "फ़्लैशलाइट" "मोबाइल डेटा" @@ -339,10 +340,8 @@ "%s उपयोग किया गया" "%s सीमा" "%s चेतावनी" - - - - + "कार्य प्रोफ़ाइल" + "सूचनाएं और ऐप्लिकेशन बंद हैं" "नाइट लाइट" "शाम को चालू की जाएगी" "सुबह तक चालू रहेगी" @@ -360,8 +359,7 @@ "%s को सुरक्षित-मोड में बंद किया गया." "Clear all" "स्क्रीन के दो हिस्से में बंट जाने, स्पिल्ट स्क्रीन, का इस्तेमाल करने के लिए यहां खींचें और छोडें" - - + "ऐप्लिकेशन बदलने के लिए ऊपर स्वाइप करें" "क्षैतिज रूप से विभाजित करें" "लम्बवत रूप से विभाजित करें" "अपने मुताबिक बांटें" @@ -502,11 +500,25 @@ "अभी बंद करें" "विस्तार करें" "छोटा करें" + + "स्‍क्रीन पिन कर दी गई है" "इससे वह तब तक दिखता रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'वापस जाएं\' और \'खास जानकारी\' को दबाकर रखें." + + "इससे वह तब तक दिखता रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'खास जानकारी\' को दबाकर रखें." + + + + + + "ठीक है" "नहीं, रहने दें" + + + + "%1$s को छिपाएं?" "जब आप उसे अगली बार सेटिंग में चालू करेंगे तो वह फिर से दिखाई देगी." "छिपाएं" @@ -586,8 +598,7 @@ "पावर सूचना नियंत्रण के ज़रिये, आप किसी ऐप की सूचना को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n""लेवल 5"" \n- सूचना सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"" लेवल 4"" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n""लेवल 3"" \n- पूरे स्क्रीन को ढंकने से रोकें \n-कभी भी न देखें \n\n""लेवल 2"" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n\n""लेवल 1"" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- सूचना सूची के नीचे दिखाएं \n\n""लेवल 0"" \n- ऐप्लिकेशन की सभी सूचनाएं रोक दें" "सूचना" "अब आपको ये सूचनाएं दिखाई नहीं देंगी" - - + "अाप अक्सर इन सूचनाओं को खारिज कर देते हैं. \nआगे भी इन्हें देखना जारी रखना चाहते हैं?" "ये सूचनाएं दिखाना जारी रखें?" "सूचनाएं दिखाना बंद करें" "दिखाना जारी रखें" @@ -807,10 +818,10 @@ "बैटरी और डेटा खर्च की जानकारी के लिए छूएं" "मोबाइल डेटा बंद करना चाहते हैं?" "ऐप की वजह से मंज़ूरी के अनुरोध को समझने में दिक्कत हो रही है, इसलिए सेटिंग से आपके जवाब की पुष्टि नहीं हो पा रही है." - "%1$s को %2$s से हिस्से (स्लाइस) दिखाने की मंज़ूरी दें?" + "%1$s को %2$s के हिस्से (स्लाइस) दिखाने की मंज़ूरी दें?" "- यह %1$s से सूचना पढ़ सकता है" "- यह %1$s में कार्रवाई कर सकता है" - "%1$s को किसी भी ऐप्लिकेशन से हिस्से (स्लाइस) दिखाने की मंज़ूरी दें." + "%1$s को किसी भी ऐप्लिकेशन के हिस्से (स्लाइस) दिखाने की मंज़ूरी दें" "मंज़ूरी दें" "नामंज़ूर करें" diff --git a/packages/SystemUI/res/values-hr/config.xml b/packages/SystemUI/res/values-hr/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-hr/config.xml +++ b/packages/SystemUI/res/values-hr/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-hu/config.xml b/packages/SystemUI/res/values-hu/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-hu/config.xml +++ b/packages/SystemUI/res/values-hu/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-hy/config.xml b/packages/SystemUI/res/values-hy/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-hy/config.xml +++ b/packages/SystemUI/res/values-hy/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-in/config.xml b/packages/SystemUI/res/values-in/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-in/config.xml +++ b/packages/SystemUI/res/values-in/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-is/config.xml b/packages/SystemUI/res/values-is/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-is/config.xml +++ b/packages/SystemUI/res/values-is/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-it/config.xml b/packages/SystemUI/res/values-it/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-it/config.xml +++ b/packages/SystemUI/res/values-it/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 880da638a7a27e2e52e5a2d70e0e403f18e13adc..89e9cc1857610942abdeda74893fa58e62fb9dce 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -103,12 +103,9 @@ "apri fotocamera" "Seleziona un nuovo layout per le attività" "Annulla" - - - - - - + "Icona dell\'impronta digitale" + "Icona dell\'applicazione" + "Area dei messaggi di assistenza" "Pulsante zoom compatibilità." "Zoom inferiore per schermo più grande." "Bluetooth collegato." @@ -313,6 +310,8 @@ "Wi-Fi disattivato" "Wi-Fi attivo" "Nessuna rete Wi-Fi disponibile" + + "Trasmetti" "In trasmissione" "Dispositivo senza nome" @@ -329,9 +328,11 @@ "Connessione..." "Tethering" "Hotspot" - - - + "Attivazione…" + + %d dispositivi + %d dispositivo + "Notifiche" "Torcia" "Dati mobili" @@ -501,11 +502,24 @@ "Disattiva ora" "Espandi" "Comprimi" + "Cambia dispositivo di uscita" "La schermata è fissata" "La schermata rimane visibile finché non viene sganciata. Per sganciarla, tieni premuto Indietro e Panoramica." + + "La schermata rimane visibile finché non viene sganciata. Per sganciarla, tieni premuto Panoramica." + + + + + + "OK" "No, grazie" + + + + "Nascondere %1$s?" "Verranno visualizzate di nuovo quando le riattiverai nelle impostazioni." "Nascondi" @@ -585,8 +599,7 @@ "I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n""Livello 5"" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n""Livello 4"" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n""Livello 3"" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n""Livello 2"" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n""Livello 1"" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n""Livello 0"" \n- Blocca tutte le notifiche dell\'app" "Notifiche" "Non vedrai più queste notifiche" - - + "In genere ignori queste notifiche. \nVuoi continuare a riceverle?" "Continuare a ricevere queste notifiche?" "Interrompi la ricezione di notifiche" "Continua a mostrare" diff --git a/packages/SystemUI/res/values-iw/config.xml b/packages/SystemUI/res/values-iw/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-iw/config.xml +++ b/packages/SystemUI/res/values-iw/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ja/config.xml b/packages/SystemUI/res/values-ja/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ja/config.xml +++ b/packages/SystemUI/res/values-ja/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ka/config.xml b/packages/SystemUI/res/values-ka/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ka/config.xml +++ b/packages/SystemUI/res/values-ka/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-kk/config.xml b/packages/SystemUI/res/values-kk/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-kk/config.xml +++ b/packages/SystemUI/res/values-kk/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-km/config.xml b/packages/SystemUI/res/values-km/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-km/config.xml +++ b/packages/SystemUI/res/values-km/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-kn/config.xml b/packages/SystemUI/res/values-kn/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-kn/config.xml +++ b/packages/SystemUI/res/values-kn/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index a8b30077badd70ba57967bd2737aeee10d67dab6..4b638f57d99c2fe08495e098479005eb2a5d1253 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -103,12 +103,9 @@ "ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ" "ಹೊಸ ಕಾರ್ಯ ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆಮಾಡಿ" "ರದ್ದುಮಾಡಿ" - - - - - - + "ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್" + "ಅಪ್ಲಿಕೇಶನ್‌ ಐಕಾನ್‌" + "ಸಹಾಯ ಸಂದೇಶ ಪ್ರದೇಶ" "ಹೊಂದಾಣಿಕೆಯ ಝೂಮ್ ಬಟನ್." "ಚಿಕ್ಕ ಪರದೆಯಿಂದ ದೊಡ್ಡ ಪರದೆಗೆ ಝೂಮ್ ಮಾಡು." "ಬ್ಲೂಟೂತ್‌‌ ಸಂಪರ್ಕಗೊಂಡಿದೆ." @@ -311,6 +308,8 @@ "ವೈ-ಫೈ ಆಫ್" "ವೈ-ಫೈ ಆನ್ ಆಗಿದೆ" "ಯಾವುದೇ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ" + + "ಬಿತ್ತರಿಸುವಿಕೆ" "ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ" "ಹೆಸರಿಸದಿರುವ ಸಾಧನ" @@ -327,9 +326,11 @@ "ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ..." "ಟೆಥರಿಂಗ್‌" "ಹಾಟ್‌ಸ್ಪಾಟ್" - - - + "ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ..." + + %d ಸಾಧನಗಳು + %d ಸಾಧನಗಳು + "ಅಧಿಸೂಚನೆಗಳು" "ಫ್ಲಾಶ್‌ಲೈಟ್‌" "ಮೊಬೈಲ್ ಡೇಟಾ" @@ -339,10 +340,8 @@ "%s ಬಳಸಲಾಗಿದೆ" "%s ಮಿತಿ" "%s ಎಚ್ಚರಿಕೆ" - - - - + "ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌" + "ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಆಫ್‌ ಆಗಿವೆ" "ನೈಟ್ ಲೈಟ್" "ಸೂರ್ಯಾಸ್ತದಲ್ಲಿ" "ಸೂರ್ಯೋದಯದ ತನಕ" @@ -360,8 +359,7 @@ "%s ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ." "ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ" "ವಿಭಜಿತ ಪರದೆಯನ್ನು ಬಳಸಲು ಇಲ್ಲಿ ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ" - - + "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸ್ವೈಪ್ ಮಾಡಿ" "ಅಡ್ಡಲಾಗಿ ವಿಭಜಿಸಿದ" "ಲಂಬವಾಗಿ ವಿಭಜಿಸಿದ" "ಕಸ್ಟಮ್ ವಿಭಜಿಸಿದ" @@ -502,11 +500,25 @@ "ಈಗ ಆಫ್ ಮಾಡಿ" "ವಿಸ್ತರಿಸು" "ಸಂಕುಚಿಸು" + + "ಪರದೆಯನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ" "ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅವಲೋಕಿಸಿ." + + "ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅವಲೋಕನವನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ." + + + + + + "ತಿಳಿಯಿತು" "ಧನ್ಯವಾದಗಳು" + + + + "%1$s ಮರೆಮಾಡುವುದೇ?" "ನೀವು ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅದನ್ನು ಆನ್ ಮಾಡಿದಾಗ ಅದು ಮರುಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ." "ಮರೆಮಾಡಿ" @@ -586,8 +598,7 @@ "ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಅಧಿಸೂಚನೆಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n""ಹಂತ 5"" \n- ಮೇಲಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n""ಹಂತ 4"" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n""ಹಂತ 3"" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n""ಹಂತ 2"" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n""ಹಂತ 1"" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n""ಹಂತ 0"" \n- ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ" "ಅಧಿಸೂಚನೆಗಳು" "ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇನ್ನು ಮುಂದೆ ನೋಡುವುದಿಲ್ಲ" - - + "ನೀವು ಸಾಮಾನ್ಯವಾಗಿ ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಜಾಗೊಳಿಸಿದ್ದೀರಿ. \nಅವುಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?" "ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?" "ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಲ್ಲಿಸಿ" "ತೋರಿಸುತ್ತಲಿರಿ" diff --git a/packages/SystemUI/res/values-ko/config.xml b/packages/SystemUI/res/values-ko/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ko/config.xml +++ b/packages/SystemUI/res/values-ko/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ky/config.xml b/packages/SystemUI/res/values-ky/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ky/config.xml +++ b/packages/SystemUI/res/values-ky/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-lo/config.xml b/packages/SystemUI/res/values-lo/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-lo/config.xml +++ b/packages/SystemUI/res/values-lo/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 338da6cf31af3eb887c5ae12e2fa2f4f441aa478..1b56074e42687f370c6c102f0b6d1b9b996e2a9d 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -103,12 +103,9 @@ "ເປີດ​ກ້ອງ" "ເລືອກ​ແຜນ​ຜັງ​ໜ້າ​ວຽກ​ໃໝ່" "ຍົກເລີກ" - - - - - - + "ໄອຄອນລາຍນິ້ວມື" + "ໄອຄອນແອັບພລິເຄຊັນ" + "ຊ່ວຍພື້ນທີ່ຂໍ້ຄວາມ" "ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້." "ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່." "ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ." @@ -311,6 +308,8 @@ "Wi​-Fi ປິດ" "Wi-Fi ເປີດ" "ບໍ່​ມີ​ເຄືອ​ຂ່າຍ Wi-Fi ຢູ່" + + "ການສົ່ງສັນຍານ" "​ກຳ​ລັງ​ສົ່ງ​ສັນ​ຍານ" "​ອຸ​ປະ​ກອນບໍ່​ມີ​ຊື່" @@ -327,9 +326,11 @@ "ກຳລັງເຊື່ອມຕໍ່..." "​ການ​ປ່ອນ​ສັນ​ຍານ" "​ຮັອດ​ສະ​ປອດ" - - - + "ກຳລັງເປີດ..." + + %d ອຸປະກອນ + %d ອຸປະກອນ + "ການແຈ້ງເຕືອນ" "​ໄຟ​ສາຍ" "ອິນເຕີເນັດມືຖື" @@ -339,10 +340,8 @@ "ໃຊ້​ໄປ​ແລ້ວ %s" "ຈຳ​ກັດ %s" "ຄຳ​ເຕືອນ %s" - - - - + "ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ" + "ການແຈ້ງເຕືອນ ແລະ ແອັບຖືກປິດໄວ້" "ແສງກາງຄືນ" "ເປີດຕອນຕາເວັນຕົກ" "ຈົນກວ່າຕາເວັນຂຶ້ນ" @@ -360,8 +359,7 @@ "%s ຖືກປິດໃຊ້ໃນໂໝດຄວາມມປອດໄພ." "ລຶບລ້າງທັງໝົດ" "ລາກມາບ່ອນນີ້ເພື່ອໃຊ້ການແບ່ງໜ້າຈໍ" - - + "ປັດຂື້ນເພື່ອສະຫຼັບແອັບ" "ການ​ແຍກ​ລວງ​ຂວາງ" "ການ​ແຍກ​ລວງ​ຕັ້ງ" "ການ​ແຍກ​ກຳ​ນົດ​ເອງ" @@ -502,11 +500,25 @@ "ປິດດຽວນີ້" "ຂະຫຍາຍ" "ຫຍໍ້ລົງ" + + "ປັກ​ໝຸດໜ້າ​ຈໍ​ແລ້ວ" "ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ." + + "ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ." + + + + + + "ເຂົ້າໃຈແລ້ວ" "ບໍ່, ຂອບໃຈ" + + + + "ເຊື່ອງ %1$s ຫຼື​ບໍ່?" "​ມັນ​ຈະ​ສະ​ແດງ​ຄືນ​ໃໝ່​ເມື່ອ​ທ່ານ​ເປີດ​ນຳ​ໃຊ້​ມັນ​ໃນ​ການ​ຕັ້ງ​ຄ່າ​ຄັ້ງ​ຕໍ່​ໄປ." "ເຊື່ອງ" @@ -586,8 +598,7 @@ "ດ້ວຍການຄວບຄຸມການແຈ້ງເຕືອນ, ທ່ານສາມາດຕັ້ງລະດັບຄວາມສຳຄັນຈາກ 0 ຮອດ 5 ໃຫ້ກັບການແຈ້ງເຕືອນແອັບໃດໜຶ່ງໄດ້. \n\n""ລະດັບ 5"" \n- ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ \n- ອະນຸຍາດໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n""ລະດັບ 4"" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n""ລະດັບ 3"" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n\n""ລະດັບ 2"" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n\n""ລະດັບ 1"" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n- ເຊື່ອງຈາກໜ້າຈໍລັອກ ແລະ ແຖບສະຖານະ \n- ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນ \n\n""ລະດັບ 0"" \n- ປິດກັ້ນການແຈ້ງເຕືອນທັງໝົດຈາກແອັບ" "ການແຈ້ງເຕືອນ" "ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນເຫຼົ່ານີ້ອີກຕໍ່ໄປ" - - + "ໂດຍປົກກະຕິທ່ານປິດການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄວ້. \nສືບຕໍ່ສະແດງພວກມັນບໍ?" "ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ຕໍ່ໄປບໍ?" "ຢຸດການແຈ້ງເຕືອນ" "ສະແດງຕໍ່ໄປ" diff --git a/packages/SystemUI/res/values-lt/config.xml b/packages/SystemUI/res/values-lt/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-lt/config.xml +++ b/packages/SystemUI/res/values-lt/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-lv/config.xml b/packages/SystemUI/res/values-lv/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-lv/config.xml +++ b/packages/SystemUI/res/values-lv/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-mk/config.xml b/packages/SystemUI/res/values-mk/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-mk/config.xml +++ b/packages/SystemUI/res/values-mk/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 9808ab6c95e8ab18eb2874e70fb042f27bc7fd0f..07ea7aa041092a474be378a6bf4a1deb746cae1d 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -103,12 +103,9 @@ "отвори камера" "Изберете нов распоред на задача" "Откажи" - - - - - - + "Икона за отпечатоци" + "Икона за апликацијата" + "Поле за пораки за помош" "Копче за компатибилност на зум." "Зумот е помал на поголем екран." "Bluetooth е поврзан." @@ -311,6 +308,8 @@ "Wi-Fi е исклучено" "Вклучено е Wi-Fi" "Нема достапни Wi-Fi мрежи" + + "Емитувај" "Емитување" "Неименуван уред" @@ -327,9 +326,11 @@ "Се поврзува..." "Поврзување" "Точка на пристап" - - - + "Се вклучува…" + + %d уред + %d уреди + "Известувања" "Светилка" "Мобилен интернет" @@ -499,11 +500,24 @@ "Исклучи сега" "Прошири" "Собери" + "Префрлете го излезниот уред" "Екранот е прикачен" "Ќе се гледа сѐ додека не го откачите. Допрете и држете „Назад“ и „Краток преглед“ за откачување." + + "Ќе се гледа сѐ додека не го откачите. Допрете и држете „Краток преглед“ за откачување." + + + + + + "Сфатив" "Не, фала" + + + + "Сокриј %1$s?" "Ќе се појави повторно следниот пат кога ќе го вклучите во поставки." "Сокриј" @@ -583,8 +597,7 @@ "Со контролите за известувањата за напојување, може да поставите ниво на важност од 0 до 5 за известувањата на која било апликација. \n\n""Ниво 5"" \n- Прикажувај на врвот на списокот со известувања \n- Дозволи прекин во цел екран \n- Секогаш користи појавување \n\n""Ниво 4"" \n- Спречи прекин во цел екран \n- Секогаш користи појавување \n\n""Ниво 3"" \n- Спречи прекин во цел екран \n- Без појавување \n\n""Ниво 2"" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n\n""Ниво 1"" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n- Сокриј од заклучен екран и статусна лента \n- Прикажувај на дното на списокот со известувања \n\n""Ниво 0"" \n- Блокирај ги сите известувања од апликацијата" "Известувања" "Веќе нема да ги гледате овие известувања" - - + "Обично ги отфрлате известувањава. \nДа продолжат да се прикажуваат?" "Дали да продолжат да се прикажуваат известувањава?" "Запри ги известувањата" "Продолжи да ги прикажуваш" diff --git a/packages/SystemUI/res/values-ml/config.xml b/packages/SystemUI/res/values-ml/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ml/config.xml +++ b/packages/SystemUI/res/values-ml/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 446f0e4e128bd1f04e5e436d6a8957159901ee37..d4d6297381408fa52c638ebb90c83c5ec1b0dc48 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -103,12 +103,9 @@ "ക്യാമറ തുറക്കുക" "പുതിയ ടാസ്‌ക് ലേഔട്ട് തിരഞ്ഞെടുക്കുക" "റദ്ദാക്കുക" - - - - - - + "വിരലടയാള ഐക്കൺ" + "ആപ്പ് ഐക്കൺ" + "സഹായ സന്ദേശ ഏരിയ" "അനുയോജ്യതാ സൂം ബട്ടൺ." "ചെറുതിൽ നിന്ന് വലിയ സ്‌ക്രീനിലേക്ക് സൂം ചെയ്യുക." "ബ്ലൂടൂത്ത് കണക്‌റ്റുചെയ്തു." @@ -311,6 +308,8 @@ "വൈഫൈ ഓഫുചെയ്യുക" "വൈഫൈ ഓണാണ്" "വൈഫൈ നെറ്റ്‌വർക്കുകളൊന്നും ലഭ്യമല്ല" + + "കാസ്‌റ്റുചെയ്യുക" "കാസ്റ്റുചെയ്യുന്നു" "പേരിടാത്ത ഉപകരണം" @@ -327,9 +326,11 @@ "കണക്റ്റുചെയ്യുന്നു..." "ടെതറിംഗ്" "ഹോട്ട്‌സ്‌പോട്ട്" - - - + "ഓൺ ചെയ്യുന്നു..." + + %d ഉപകരണങ്ങൾ + %d ഉപകരണം + "അറിയിപ്പുകൾ" "ടോർച്ച്" "മൊബൈൽ ഡാറ്റ" @@ -339,10 +340,8 @@ "%s ഉപയോഗിച്ചു" "%s പരിധി" "%s മുന്നറിയിപ്പ്" - - - - + "ഔദ്യോഗിക പ്രൊഫൈൽ" + "അറിയിപ്പുകളും ആപ്പുകളും ഓഫാണ്" "നൈറ്റ് ലൈറ്റ്" "സൂര്യാസ്‌തമയത്തിന്" "സൂര്യോദയം വരെ" @@ -360,8 +359,7 @@ "സുരക്ഷിത മോഡിൽ %s പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു." "എല്ലാം മായ്‌ക്കുക" "സ്പ്ലിറ്റ് സ്ക്രീൻ ഉപയോഗിക്കുന്നതിന് ഇവിടെ വലിച്ചിടുക" - - + "ആപ്പുകൾ മാറാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക" "തിരശ്ചീനമായി വേർതിരിക്കുക" "ലംബമായി വേർതിരിക്കുക" "ഇഷ്‌ടാനുസൃതമായി വേർതിരിക്കുക" @@ -502,11 +500,25 @@ "ഇപ്പോൾ ഓഫ് ചെയ്യുക" "വികസിപ്പിക്കുക" "ചുരുക്കുക" + + "സ്‌ക്രീൻ പിൻ ചെയ്‌തു" "നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ\', \'ചുരുക്കവിവരണം\' എന്നിവ സ്‌പർശിച്ച് പിടിക്കുക." + + "നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'ചുരുക്കവിവരണം\' സ്‌പർശിച്ച് പിടിക്കുക." + + + + + + "മനസ്സിലായി" "വേണ്ട, നന്ദി" + + + + "%1$s എന്നത് മറയ്‌ക്കണോ?" "അടുത്ത തവണ നിങ്ങൾ അത് ക്രമീകരണങ്ങളിൽ ഓണാക്കുമ്പോൾ അത് വീണ്ടും ദൃശ്യമാകും." "മറയ്‌ക്കുക" @@ -586,8 +598,7 @@ "പവർ അറിയിപ്പ് നിയന്ത്രണം ഉപയോഗിച്ച്, ഒരു ആപ്പിനായുള്ള അറിയിപ്പുകൾക്ക് 0 മുതൽ 5 വരെയുള്ള പ്രാധാന്യ ലെവലുകളിലൊന്ന് നിങ്ങൾക്ക് സജ്ജമാക്കാവുന്നതാണ്. \n\n""ലെവൽ 5"" \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ മുകളിൽ കാണിക്കുക \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം അനുവദിക്കുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n""ലെവൽ 4"" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n""ലെവൽ 3"" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും സൃശ്യമാക്കരുത് \n\n""ലെവൽ 2"" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n\n""ലെവൽ 1"" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n- ലോക്ക് സ്ക്രീനിൽ നിന്നും സ്റ്റാറ്റസ് ബാറിൽ നിന്നും മറയ്ക്കുക \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ അടിയിൽ കാണിക്കുക \n\n""ലെവൽ 0"" \n- ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക" "അറിയിപ്പുകൾ" "നിങ്ങൾ ഇനി ഈ അറിയിപ്പുകൾ കാണില്ല" - - + "സാധാരണയായി നിങ്ങൾ ഈ അറിയിപ്പുകൾ നിരാകരിക്കുന്നു. \nഅവ തുടർന്നും കാണിക്കണോ?" "ഈ അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?" "അറിയിപ്പുകൾ നിർത്തുക" "തുടർന്നും കാണിക്കുക" diff --git a/packages/SystemUI/res/values-mn/config.xml b/packages/SystemUI/res/values-mn/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-mn/config.xml +++ b/packages/SystemUI/res/values-mn/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-mr/config.xml b/packages/SystemUI/res/values-mr/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-mr/config.xml +++ b/packages/SystemUI/res/values-mr/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 804e91623b1ed6f0f29c9a9ed0493d6ca41ac2f6..c34811017954e5a3d720ffe7634bf23f27826a5e 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -103,12 +103,9 @@ "कॅमेरा उघडा" "नवीन कार्य लेआउट निवडा" "रद्द करा" - - - - - - + "फिंगरप्रिंट आयकन" + "अॅप्लिकेशन आयकन" + "मदत संदेश क्षेत्र" "सुसंगतता झूम बटण." "लहानपासून मोठ्‍या स्‍क्रीनवर झूम करा." "ब्लूटूथ कनेक्‍ट केले." @@ -311,6 +308,8 @@ "वाय-फाय बंद" "वाय-फाय चालू" "वाय-फाय नेटवर्क उपलब्‍ध नाहीत" + + "कास्‍ट करा" "कास्ट करत आहे" "निनावी डिव्हाइस" @@ -327,9 +326,11 @@ "कनेक्ट करत आहे..." "टेदरिंग" "हॉटस्पॉट" - - - + "चालू करत आहे…" + + %d डिव्हाइस + %d डिव्हाइस + "सूचना" "फ्लॅशलाइट" "मोबाइल डेटा" @@ -339,10 +340,8 @@ "%s वापरले" "%s मर्यादा" "%s चेतावणी" - - - - + "कार्य प्रोफाइल" + "सूचना आणि अ‍ॅप्स बंद आहेत" "रात्रीचा प्रकाश" "संध्याकाळी चालू असते" "सूर्योदयापर्यंत" @@ -360,8 +359,7 @@ "%s सुरक्षित-मोडमध्ये अक्षम केला आहे." "सर्व साफ करा" "विभाजित स्क्रीन वापर करण्यासाठी येथे ड्रॅग करा" - - + "अ‍ॅप्स स्विच करण्यासाठी वर स्वाइप करा" "क्षैतिज विभाजित करा" "अनुलंब विभाजित करा" "सानुकूल विभाजित करा" @@ -502,11 +500,25 @@ "आता बंद करा" "विस्तृत करा" "संकुचित करा" + + "स्क्रीन पिन केलेली आहे" "आपण अनपिन करेर्यंत हे यास दृश्यामध्ये ठेवते. अनपिन करण्‍यासाठी परत आणि विहंगावलोकनास स्पर्श करा आणि धरून ठेवा." + + "आपण अनपिन करेर्यंत हे यास दृश्यामध्ये ठेवते. अनपिन करण्‍यासाठी विहंगावलोकनास स्पर्श करा आणि धरून ठेवा." + + + + + + "समजले" "नाही, नको" + + + + "%1$s लपवायचे?" "आपण सेटिंग्जमध्ये ते पुढील वेळी चालू कराल तेव्हा ते पुन्हा दिसेल." "लपवा" @@ -586,8 +598,7 @@ "पॉवर सूचना नियंत्रणांच्या साहाय्याने तुम्ही अॅप सूचनांसाठी 0 ते 5 असे महत्त्व स्तर सेट करू शकता. \n\n""स्तर 5"" \n- सूचना सूचीच्या शीर्षस्थानी दाखवा \n- पूर्ण स्क्रीन व्यत्ययास अनुमती द्या \n- नेहमी डोकावून पहा \n\n""स्तर 4"\n" - पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- नेहमी डोकावून पहा \n\n""स्तर 3"" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n\n""स्तर 2"" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा कंपन करू नका \n\n""स्तर 1"\n"- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा कंपन करू नका \n- लॉक स्क्रीन आणि स्टेटस बार मधून लपवा \n- सूचना सूचीच्या तळाशी दर्शवा \n\n""स्तर 0"" \n- अॅपमधील सर्व सूचना ब्लॉक करा" "सूचना" "आता तुम्हाला या सूचना दिसणार नाहीत" - - + "तुम्ही या सूचना सामान्यतः डिसमिस करता. \nते दाखवत राहायचे?" "या सूचना दाखवणे सुरू ठेवायचे?" "सूचना थांबवा" "दाखवणे सुरू ठेवा" diff --git a/packages/SystemUI/res/values-ms/config.xml b/packages/SystemUI/res/values-ms/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ms/config.xml +++ b/packages/SystemUI/res/values-ms/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-my/config.xml b/packages/SystemUI/res/values-my/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-my/config.xml +++ b/packages/SystemUI/res/values-my/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 972f4ee11ede1e6f36e4b5866db87d50e959f1c5..41f28e2093e1f8b5c630841f45028c02d300c1ea 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -103,12 +103,9 @@ "ကင်မရာ ဖွင့်ရန်" "အလုပ်သစ်စီစဥ်မှုကို ရွေးပါ။" "မလုပ်တော့" - - - - - - + "လက်ဗွေ သင်္ကေတ" + "အပလီကေးရှင်း သင်္ကေတ" + "အကူအညီမက်ဆေ့ဂျ် နေရာ" "အံဝင်ခွင်ကျ ဇူးမ်ခလုတ်" "ဖန်သားပြင်ပေါ်တွင် အသေးမှအကြီးသို့ ဇူးမ်ဆွဲခြင်း" "ဘလူးတုသ်ချိတ်ဆက်ထားမှု" @@ -311,6 +308,8 @@ "ဝိုင်ဖိုင်ပိတ်ရန်" "Wi-Fi ကိုဖွင့်ပါ" "Wi-Fi ကွန်ရက် မရှိပါ" + + "Cast" "ကာစ်တင်" "အမည်မတပ် ကိရိယာ" @@ -327,9 +326,11 @@ "ဆက်သွယ်နေ..." "တွဲချီပေးခြင်း" "ဟော့စပေါ့" - - - + "ဖွင့်နေသည်..." + + စက် %d ခု + စက် %d ခု + "အကြောင်းကြားချက်များ" "ဖလက်ရှ်မီး" "မိုဘိုင်းဒေတာ" @@ -499,11 +500,24 @@ "ပိတ်ရန်" "တိုးချဲ့ရန်" "ခေါက်သိမ်းရန်..." + "အထွက် စက်ပစ္စည်းကို ပြောင်းပါ" "မျက်နှာပြင် ပင်ထိုးပြီးပါပြီ" "သင်ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် Back နှင့် Overview ကို ထိ၍ဖိထားပါ။" + + "သင်ပင်မဖြုတ်မချင်း ၎င်းကိုပြသထားပါမည်။ ပင်ဖြုတ်ရန် Overview ကိုထိပြီး ဖိထားပါ။" + + + + + + "ရပါပြီ" "မလိုတော့ပါ" + + + + "%1$s ဝှက်မည်လား?" "နောက်တစ်ကြိမ်သင် ချိန်ညှိချက်များဖွင့်လျှင် ၎င်းပေါ်လာပါမည်။" "ဖျောက်ထားမည်" @@ -583,8 +597,7 @@ "ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများကိုအသုံးပြုပြီး အက်ပ်တစ်ခု၏ အကြောင်းကြားချက် အရေးပါမှု ၀ မှ ၅ အထိသတ်မှတ်ပေးနိုင်သည်။ \n\n""အဆင့် ၅"" \n- အကြောင်းကြားချက်စာရင်း၏ ထိပ်ဆုံးတွင် ပြသည် \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်းကို ခွင့်ပြုသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n""အဆင့် ၄"" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n""အဆင့် ၃"" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n\n""အဆင့် ၂"" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n\n""အဆင့် ၁"" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n- လော့ခ်ချထားသည့် မျက်နှာပြင်နှင့် အခြေအနေဘားတန်းတို့တွင် မပြပါ \n- အကြောင်းကြားချက်စာရင်း အောက်ဆုံးတွင်ပြသည် \n\n""အဆင့် ၀"" \n- အက်ပ်မှ အကြောင်းကြားချက်များ အားလုံးကို ပိတ်ဆို့သည်" "အကြောင်းကြားချက်များ" "ဤအကြောင်းကြားချက်များကို မြင်ရတော့မည် မဟုတ်ပါ" - - + "သင်သည် အများအားဖြင့် ဤအကြောင်းကြားချက်များကို ပယ်လေ့ရှိပါသည်။ \n၎င်းတို့ကို ဆက်လက်ပြသလိုပါသလား။" "ဤအကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။" "အကြောင်းကြားချက်များကို ရပ်ရန်" "ဆက်ပြရန်" diff --git a/packages/SystemUI/res/values-nb/config.xml b/packages/SystemUI/res/values-nb/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-nb/config.xml +++ b/packages/SystemUI/res/values-nb/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index d4d61607733cd5aab30c77c286659121ffa07d8e..5bd4f2ee321d347ebe7265bc82b75c9a43f2c676 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -103,12 +103,9 @@ "åpne kamera" "Velg en ny utforming for oppgaver" "Avbryt" - - - - - - + "Ikon for fingeravtrykk" + "Appikon" + "Område for hjelpemelding" "Zoomknapp for kompatibilitet." "Zoom fra mindre til større skjerm." "Bluetooth er tilkoblet." @@ -311,6 +308,8 @@ "Wi-Fi er av" "Wi-Fi er på" "Ingen tilgjengelige Wi-Fi-nettverk" + + "Cast" "Casting" "Enhet uten navn" @@ -327,9 +326,11 @@ "Kobler til …" "Internettdeling" "Wi-Fi-sone" - - - + "Slår på …" + + %d enheter + %d enhet + "Varsler" "Lommelykt" "Mobildata" @@ -339,10 +340,8 @@ "%s brukt" "Grense på %s" "Advarsel for %s" - - - - + "Jobbprofil" + "Varsler og apper er slått av" "Nattlys" "På ved solnedgang" "Til soloppgang" @@ -360,8 +359,7 @@ "%s er slått av i sikker modus." "Tøm alt" "Dra hit for å bruke delt skjerm" - - + "Sveip opp for å bytte apper" "Del horisontalt" "Del vertikalt" "Del tilpasset" @@ -502,11 +500,25 @@ "Slå av nå" "Utvid" "Skjul" + + "Skjermen er låst" "På denne måten blir skjermen synlig frem til du løsner den. Trykk og hold inne Tilbake og Oversikt for å løsne den." + + "På denne måten blir skjermen synlig frem til du løsner den. Trykk og hold inne Oversikt for å løsne den." + + + + + + "Skjønner" "Nei takk" + + + + "Vil du skjule %1$s?" "Den vises igjen neste gang du slår den på i innstillingene." "Skjul" @@ -586,8 +598,7 @@ "Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n""Nivå 5"" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n""Nivå 4"" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n""Nivå 3"" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n""Nivå 2"" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n""Nivå 1"" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n""Nivå 0"" \n– Blokkér alle varsler fra appen" "Varsler" "Du ser ikke disse varslene lenger" - - + "Du avviser vanligvis disse varslene. \nVil du fortsette å vise dem?" "Vil du fortsette å vise disse varslene?" "Stopp varsler" "Fortsett å vise" diff --git a/packages/SystemUI/res/values-ne/config.xml b/packages/SystemUI/res/values-ne/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ne/config.xml +++ b/packages/SystemUI/res/values-ne/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index e3efe1bf70f707eb0c53cc72b0fdf5d875f5ecd9..ca81f44f7cacf4f9dd1107351c1a2a183ca10e5d 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -41,7 +41,7 @@ "USB चार्ज गर्न समर्थित छैन।\n आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।" "USB चार्ज समर्थित छैन।" "आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।" - "सेटिङ्हरू" + "सेटिङहरू" "ब्याट्री सेभर सक्रिय गर्ने हो?" "खोल्नुहोस्" "ब्याट्री सेभर सक्रिय गर्नुहोस्" @@ -103,12 +103,9 @@ "क्यामेरा खोल्नुहोस्" "नयाँ कार्य लेआउट चयन गर्नुहोस्" "रद्द गर्नुहोस्" - - - - - - + "फिंगरप्रिन्ट जनाउने आइकन" + "अनुप्रयोग जनाउने आइकन" + "मद्दतसम्बन्धी सन्देशको क्षेत्र" "मिलाउने जुम बटन।" "स्क्रिनलाई सानोबाट ठूलो पार्नुहोस्।" "ब्लुटुथ जडान भयो।" @@ -264,8 +261,8 @@ भित्र थप %s सूचनाहरू छन्। भित्र थप %s सूचना छ। - "अधिसूचना सेटिङ्हरू" - "%s सेटिङ्हरू" + "अधिसूचना सेटिङहरू" + "%s सेटिङहरू" "स्क्रिन स्वतः घुम्ने छ।" "स्क्रिनलाई ल्यान्डस्केप अवस्थामा बन्द गरिएको छ।" "स्क्रिन पोर्टेट अभिमूखमा लक गरिएको छ।" @@ -311,6 +308,8 @@ "Wi-Fi बन्द" "Wi-Fi सक्रिय छ" "Wi-Fi नेटवर्क अनुपलब्ध" + + "Cast" "प्रसारण गर्दै" "बेनाम उपकरण" @@ -327,9 +326,11 @@ "जडान हुँदै..." "टेदर गर्दै" "हटस्पट" - - - + "सक्रिय गर्दै…" + + %d यन्त्रहरू + %d यन्त्र + "अधिसूचनाहरू" "फ्ल्यासलाइट" "मोबाइल डेटा" @@ -339,10 +340,8 @@ "%s प्रयोग गरियो" "%s सीमा" "%s चेतावनी दिँदै" - - - - + "कार्य प्रोफाइल" + "सूचना तथा अनुप्रयोगहरू निष्क्रिय छन्‌" "रात्रिको प्रकाश" "सूर्यास्तमा सक्रिय" "सूर्योदयसम्म" @@ -360,8 +359,7 @@ "%s लाई सुरक्षित-मोडमा असक्षम गरिएको छ।" "सबै हटाउनुहोस्" "विभाजित स्क्रिनको प्रयोग गर्नका लागि यहाँ तान्नुहोस्" - - + "अनुप्रयोगहरू बदल्न माथितिर स्वाइप गर्नुहोस्" "तेर्सो रूपमा विभाजन गर्नुहोस्" "ठाडो रूपमा विभाजन गर्नुहोस्" "आफू अनुकूल विभाजन गर्नुहोस्" @@ -376,11 +374,11 @@ "खोज्नुहोस्" "%sको लागि माथि धिसार्नुहोस्" "स्लाइड %sको लागि बायाँ।" - "तपाईंलाई अलार्म, रिमाइन्डर, कार्यक्रम र तपाईंले निर्दिष्ट गर्नुभएका कलरहरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै संगीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।" - "तपाईंलाई अलार्महरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै संगीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।" + "तपाईंलाई अलार्म, रिमाइन्डर, कार्यक्रम र तपाईंले निर्दिष्ट गर्नुभएका कलरहरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।" + "तपाईंलाई अलार्महरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।" "आफू अनुकूल बनाउनुहोस्" - "यसले अलार्म, संगीत, भिडियो, र खेलहरू लगायत सबैका ध्वनि र कम्पनहरूमाथि रोक लगाउँछ। तपाईं अझै पनि फोन कलहरू गर्न सक्नुहुनेछ।" - "यसले अलार्म, संगीत, भिडियोहरू र खेलहरूसहित सबै ध्वनिहरू र कम्पनहरूलाई रोक्छ।" + "यसले अलार्म, सङ्गीत, भिडियो, र खेलहरू लगायत सबैका ध्वनि र कम्पनहरूमाथि रोक लगाउँछ। तपाईं अझै पनि फोन कलहरू गर्न सक्नुहुनेछ।" + "यसले अलार्म, सङ्गीत, भिडियोहरू र खेलहरूसहित सबै ध्वनिहरू र कम्पनहरूलाई रोक्छ।" "+%d" "तल कम जरुरी सूचनाहरू" "खोल्न पुनः ट्याप गर्नुहोस्" @@ -502,11 +500,25 @@ "अहिले नै निष्क्रिय पार्नुहोस्" "विस्तार गर्नुहोस्" "संक्षिप्त पार्नुहोस्" + + "पर्दा राखेका छ" "तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र परिदृश्य बटनलाई छोइराख्नुहोस्।" + + "तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न परिदृश्य बटनलाई छोइराख्नुहोस्।" + + + + + + "बुझेँ" "धन्यवाद पर्दैन" + + + + "लुकाउनुहुन्छ %1$s?" "यो तपाईं सेटिङ् मा यो बारी अर्को समय देखापर्नेछ।" "लुकाउनुहोस्" @@ -586,8 +598,7 @@ "सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n""स्तर ५"" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n""स्तर ४"" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n""स्तर ३"" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n""स्तर २"" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n""स्तर १"" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n""स्तर ०"" \n- अनुप्रयोगका सबै सूचनाहरूलाई रोक्ने" "सूचनाहरू" "तपाईं अब उप्रान्त यी सूचनाहरू देख्नु हुने छैन" - - + "तपाईं सामान्यतया यी सूचनाहरूलाई खारेज गर्ने गर्नुहुन्छ। \nतिनलाई देखाइरहने हो?" "यी सूचनाहरू देखाउने क्रम जारी राख्ने हो?" "सूचनाहरू देखाउन छाड्नुहोस्" "देखाउने क्रम जारी राख्नुहोस्" @@ -656,7 +667,7 @@ "सम्पर्कहरू" "इमेल" "SMS" - "संगीत" + "सङ्गीत" "YouTube" "पात्रो" "भोल्युम नियन्त्रणसहित देखाउनुहोस्" diff --git a/packages/SystemUI/res/values-nl/config.xml b/packages/SystemUI/res/values-nl/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-nl/config.xml +++ b/packages/SystemUI/res/values-nl/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-pa/config.xml b/packages/SystemUI/res/values-pa/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-pa/config.xml +++ b/packages/SystemUI/res/values-pa/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 4e391065e73ab86e994a2cf22912d7b6b754ee13..9308fee0d546c44e7531afbe5696e465738c9c22 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -103,12 +103,9 @@ "ਕੈਮਰਾ ਖੋਲ੍ਹੋ" "ਨਵਾਂ ਕੰਮ ਲੇਆਉਟ ਚੁਣੋ" "ਰੱਦ ਕਰੋ" - - - - - - + "ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਪ੍ਰਤੀਕ" + "ਐਪਲੀਕੇਸ਼ਨ ਦਾ ਪ੍ਰਤੀਕ" + "ਮਦਦ ਸੁਨੇਹਾ ਖੇਤਰ" "ਅਨੁਰੂਪਤਾ ਜ਼ੂਮ ਬਟਨ।" "ਵੱਡੀ ਸਕ੍ਰੀਨ ਤੇ ਛੋਟਾ ਜ਼ੂਮ ਕਰੋ।" "Bluetooth ਕਨੈਕਟ ਕੀਤੀ।" @@ -311,6 +308,8 @@ "ਵਾਈ-ਫਾਈ ਬੰਦ" "ਵਾਈ-ਫਾਈ ਚਾਲੂ" "ਕੋਈ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ" + + "ਕਾਸਟ" "ਕਾਸਟਿੰਗ" "ਬਿਨਾਂ ਨਾਮ ਦਾ ਡੀਵਾਈਸ" @@ -327,9 +326,11 @@ "ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..." "ਟੈਦਰਿੰਗ" "ਹੌਟਸਪੌਟ" - - - + "ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." + + %d ਡੀਵਾਈਸ + %d ਡੀਵਾਈਸਾਂ + "ਸੂਚਨਾਵਾਂ" "ਫਲੈਸ਼ਲਾਈਟ" "ਮੋਬਾਈਲ ਡਾਟਾ" @@ -339,10 +340,8 @@ "%s ਵਰਤਿਆ" "%s ਸੀਮਾ" "%s ਚਿਤਾਵਨੀ" - - - - + "ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ" + "ਸੂਚਨਾਵਾਂ ਅਤੇ ਐਪਾਂ ਬੰਦ ਹਨ" "ਰਾਤਰੀ ਲਾਈਟ" "ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ" "ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ" @@ -360,8 +359,7 @@ "%s ਨੂੰ ਸੁਰੱਖਿਅਤ-ਮੋਡ ਵਿੱਚ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ।" "ਸਭ ਕਲੀਅਰ ਕਰੋ" "ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇੱਥੇ ਘਸੀਟੋ" - - + "ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ" "ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ" "ਵਰਟੀਕਲ ਸਪਲਿਟ" "ਵਿਉਂਂਤੀ ਸਪਲਿਟ" @@ -502,11 +500,25 @@ "ਹੁਣੇ ਬੰਦ ਕਰੋ" "ਵਿਸਤਾਰ ਕਰੋ" "ਨਸ਼ਟ ਕਰੋ" + + "ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ" "ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + + "ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + + + + + + "ਸਮਝ ਲਿਆ" "ਨਹੀਂ ਧੰਨਵਾਦ" + + + + "ਕੀ %1$s ਨੂੰ ਲੁਕਾਉਣਾ ਹੈ?" "ਇਹ ਅਗਲੀ ਵਾਰ ਮੁੜ ਪ੍ਰਗਟ ਹੋਵੇਗਾ ਜਦੋਂ ਤੁਸੀਂ ਇਸਨੂੰ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕਰਦੇ ਹੋ।" "ਲੁਕਾਓ" @@ -586,8 +598,7 @@ "ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n""ਪੱਧਰ 5"" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n""ਪੱਧਰ 4"" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n""ਪੱਧਰ 3"" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n\n""ਪੱਧਰ 2"" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n""ਪੱਧਰ 1"" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲਾਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਦਿਖਾਓ \n\n""ਪੱਧਰ 0"" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ" "ਸੂਚਨਾਵਾਂ" "ਤੁਹਾਨੂੰ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਦਿਖਾਈ ਨਹੀਂ ਦੇਣਗੀਆਂ" - - + "ਤੁਸੀਂ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਆਮ ਤੌਰ \'ਤੇ ਖਾਰਜ ਕਰਦੇ ਹੋ। \nਕੀ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?" "ਕੀ ਇਨ੍ਹਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?" "ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ" "ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖੋ" diff --git a/packages/SystemUI/res/values-pl/config.xml b/packages/SystemUI/res/values-pl/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-pl/config.xml +++ b/packages/SystemUI/res/values-pl/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-pt-rBR/config.xml b/packages/SystemUI/res/values-pt-rBR/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-pt-rBR/config.xml +++ b/packages/SystemUI/res/values-pt-rBR/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 3472d1d2f5069b2fc540c8b9e51b1a8763727aa0..982b8b7df37b829c835c2bd8205b0b0fa7ad3d20 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -103,12 +103,9 @@ "abrir câmera" "Selecionar novo layout da tarefa" "Cancelar" - - - - - - + "Ícone de impressão digital" + "Ícone do app" + "Área da mensagem de ajuda" "Botão de zoom da compatibilidade." "Aumentar a tela com zoom." "Bluetooth conectado." @@ -313,6 +310,8 @@ "Wi-Fi desligado" "Wi-Fi ativado" "Nenhuma rede Wi-Fi disponível" + + "Transmitir" "Transmitindo" "Dispositivo sem nome" @@ -329,9 +328,11 @@ "Conectando..." "Tethering" "Ponto de acesso" - - - + "Ativando…" + + %d dispositivo + %d dispositivos + "Notificações" "Lanterna" "Dados móveis" @@ -501,11 +502,24 @@ "Desativar agora" "Expandir" "Recolher" + "Alterar dispositivo de saída" "A tela está fixada" "Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar." + + "Ela é mantida à vista até que seja liberada. Toque em Visão geral e mantenha essa opção pressionada para liberar." + + + + + + "Entendi" "Não, obrigado" + + + + "Esconder %1$s?" "Ela reaparecerá na próxima vez que você ativá-la nas configurações." "Ocultar" @@ -585,8 +599,7 @@ "Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n""Nível 5"" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n""Nível 4"" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n""Nível 3"" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n""Nível 2"" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n""Nível 1"" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n""Nível 0"" \n- Bloquear todas as notificações do app" "Notificações" "Você deixará de ver essas notificações" - - + "Geralmente você dispensa essas notificações. \nQuer que elas continuem a ser exibidas?" "Continuar mostrando essas notificações?" "Bloquear notificações" "Continuar mostrando" diff --git a/packages/SystemUI/res/values-pt-rPT/config.xml b/packages/SystemUI/res/values-pt-rPT/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-pt-rPT/config.xml +++ b/packages/SystemUI/res/values-pt-rPT/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index a631fcc2f95686d3083c86b3e4370f6206872515..2bc1c03edd443f418af1084ca31c3e3deef953d2 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -103,12 +103,9 @@ "abrir câmara" "Selecionar novo esquema de tarefa" "Cancelar" - - - - - - + "Ícone de impressão digital" + "Ícone de aplicação" + "Área da mensagem de ajuda" "Botão zoom de compatibilidade." "Zoom menor para ecrã maior." "Bluetooth ligado." @@ -311,6 +308,8 @@ "Wi-Fi Desligado" "Wi-Fi ligado" "Não estão disponíveis redes Wi-Fi" + + "Transmitir" "Transmissão" "Dispositivo sem nome" @@ -327,9 +326,11 @@ "A ligar..." "Associação" "Zona Wi-Fi" - - - + "A ativar…" + + %d dispositivos + %d dispositivo + "Notificações" "Lanterna" "Dados móveis" @@ -339,10 +340,8 @@ "%s utilizado(s)" "Limite de %s" "Aviso de %s" - - - - + "Perfil de trabalho" + "As notificações e as aplicações estão desativadas" "Luz noturna" "Ativ. ao pôr-do-sol" "Até ao nascer do sol" @@ -360,8 +359,7 @@ "O %s está desativado no modo de segurança." "Limpar tudo" "Arraste aqui para utilizar o ecrã dividido" - - + "Deslizar rapidamente para cima para mudar de aplicação" "Divisão horizontal" "Divisão vertical" "Divisão personalizada" @@ -502,11 +500,24 @@ "Desativar agora" "Expandir" "Reduzir" + "Mudar de dispositivo de saída" "O ecrã está fixado" "Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Vista geral para soltar." + + "Esta opção mantém o item visível até o soltar. Toque sem soltar em Vista geral para soltar." + + + + + + "Compreendi" "Não, obrigado" + + + + "Pretende ocultar %1$s?" "Reaparecerá da próxima vez que a funcionalidade for ativada nas definições." "Ocultar" @@ -586,8 +597,7 @@ "Com os controlos de notificações do consumo de energia, pode definir um nível de importância de 0 a 5 para as notificações de aplicações. \n\n""Nível 5"" \n- Mostrar no início da lista de notificações \n- Permitir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre \n\n""Nível 4"" \n- Impedir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre\n\n""Nível 3"" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n\n""Nível 2"" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n\n""Nível 1"" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n- Ocultar do ecrã de bloqueio e da barra de estado \n- Mostrar no fim da lista de notificações \n\n""Nível 0"" \n- Bloquear todas as notificações da aplicação" "Notificações" "Nunca mais verá estas notificações." - - + "Normalmente, ignora estas notificações. \nPretende continuar a mostrá-las?" "Pretende continuar a ver estas notificações?" "Parar notificações" "Continuar a mostrar" diff --git a/packages/SystemUI/res/values-pt/config.xml b/packages/SystemUI/res/values-pt/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-pt/config.xml +++ b/packages/SystemUI/res/values-pt/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 3472d1d2f5069b2fc540c8b9e51b1a8763727aa0..982b8b7df37b829c835c2bd8205b0b0fa7ad3d20 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -103,12 +103,9 @@ "abrir câmera" "Selecionar novo layout da tarefa" "Cancelar" - - - - - - + "Ícone de impressão digital" + "Ícone do app" + "Área da mensagem de ajuda" "Botão de zoom da compatibilidade." "Aumentar a tela com zoom." "Bluetooth conectado." @@ -313,6 +310,8 @@ "Wi-Fi desligado" "Wi-Fi ativado" "Nenhuma rede Wi-Fi disponível" + + "Transmitir" "Transmitindo" "Dispositivo sem nome" @@ -329,9 +328,11 @@ "Conectando..." "Tethering" "Ponto de acesso" - - - + "Ativando…" + + %d dispositivo + %d dispositivos + "Notificações" "Lanterna" "Dados móveis" @@ -501,11 +502,24 @@ "Desativar agora" "Expandir" "Recolher" + "Alterar dispositivo de saída" "A tela está fixada" "Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar." + + "Ela é mantida à vista até que seja liberada. Toque em Visão geral e mantenha essa opção pressionada para liberar." + + + + + + "Entendi" "Não, obrigado" + + + + "Esconder %1$s?" "Ela reaparecerá na próxima vez que você ativá-la nas configurações." "Ocultar" @@ -585,8 +599,7 @@ "Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n""Nível 5"" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n""Nível 4"" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n""Nível 3"" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n""Nível 2"" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n""Nível 1"" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n""Nível 0"" \n- Bloquear todas as notificações do app" "Notificações" "Você deixará de ver essas notificações" - - + "Geralmente você dispensa essas notificações. \nQuer que elas continuem a ser exibidas?" "Continuar mostrando essas notificações?" "Bloquear notificações" "Continuar mostrando" diff --git a/packages/SystemUI/res/values-ro/config.xml b/packages/SystemUI/res/values-ro/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ro/config.xml +++ b/packages/SystemUI/res/values-ro/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 58b6b753a57248d5e28be8e1cd6f7a1b2ab579d9..d7652821560eda110e38be7c78fcecae7ae95e7a 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -104,12 +104,9 @@ "deschideți camera foto" "Selectați noul aspect pentru activitate" "Anulați" - - - - - - + "Pictograma amprentă" + "Pictograma aplicației" + "Zona mesajelor de ajutor" "Buton zoom pentru compatibilitate." "Faceți zoom de la o imagine mai mică la una mai mare." "Conectat prin Bluetooth." @@ -315,6 +312,8 @@ "Wi-Fi deconectat" "Wi-Fi activat" "Nicio rețea Wi-Fi disponibilă" + + "Proiectați" "Se proiectează" "Dispozitiv nedenumit" @@ -331,9 +330,12 @@ "Se conectează..." "Tethering" "Hotspot" - - - + "Se activează..." + + %d dispozitive + %d de dispozitive + %d dispozitiv + "Notificări" "Lanternă" "Date mobile" @@ -503,11 +505,24 @@ "Dezactivați acum" "Extindeți" "Restrângeți" + "Comutați dispozitivul de ieșire" "Ecranul este fixat" "Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunile Înapoi și Recente pentru a anula fixarea." + + "Astfel rămâne afișat până anulați fixarea. Atingeți lung opțiunea Recente pentru a anula fixarea." + + + + + + "Am înțeles" "Nu, mulțumesc" + + + + "Ascundeți %1$s?" "Va reapărea la următoarea activare în setări." "Ascundeți" @@ -587,8 +602,7 @@ "Folosind comenzile de gestionare a notificărilor, puteți să setați un nivel de importanță de la 0 la 5 pentru notificările unei aplicații. \n\n""Nivelul 5"" \n– Se afișează la începutul listei de notificări \n– Se permite întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n""Nivelul 4"" \n– Se împiedică întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n""Nivelul 3"" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n\n""Nivelul 2"" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n\n""Nivelul 1"" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n– Se ascunde în ecranul de blocare și în bara de stare \n– Se afișează la finalul listei de notificări \n\n""Nivelul 0"" \n– Se blochează toate notificările din aplicație" "Notificări" "Nu veți mai vedea aceste notificări" - - + "De regulă respingeți aceste notificări. \nDoriți să fie afișate în continuare?" "Doriți să continuați afișarea acestor notificări?" "Opriți notificările" "Continuați afișarea" diff --git a/packages/SystemUI/res/values-ru/config.xml b/packages/SystemUI/res/values-ru/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ru/config.xml +++ b/packages/SystemUI/res/values-ru/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 3bda5eb5297b44e92a4f99896d44f92a580f637d..9cd90827a39c43b4fde88e437069d79ce377500e 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -105,12 +105,9 @@ "Открыть камеру." "Выберите другой макет" "Отмена" - - - - - - + "Значок отпечатка пальца" + "Значок приложения" + "Справочное сообщение" "Кнопка масштабирования (режим совместимости)" "Уменьшение изображения для увеличения свободного места на экране." "Bluetooth-соединение установлено." @@ -317,6 +314,8 @@ "Wi-Fi выкл." "Wi-Fi включен" "Не удалось найти доступные сети Wi-Fi" + + "Трансляция" "Передача изображения" "Безымянное устройство" @@ -333,9 +332,13 @@ "Соединение..." "Режим модема" "Точка доступа" - - - + "Подождите…" + + %d устройство + %d устройства + %d устройств + %d устройства + "Уведомления" "Фонарик" "Мобильный Интернет" @@ -345,10 +348,8 @@ "Использовано: %s" "Ограничение: %s" "Предупреждение: %s" - - - - + "Рабочий профиль" + "Уведомления и приложения отключены" "Ночной режим" "Включить на закате" "До рассвета" @@ -366,8 +367,7 @@ "Приложение \"%s\" отключено в безопасном режиме." "Очистить все" "Перетащите сюда, чтобы разделить экран" - - + "Чтобы переключиться между приложениями, проведите по экрану вверх." "Разделить по горизонтали" "Разделить по вертикали" "Разделить по-другому" @@ -508,11 +508,24 @@ "Отключить" "Развернуть" "Свернуть" + "Сменить устройство аудиовыхода" "Блокировка в приложении включена" "Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Обзор\"." + + "Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопку \"Обзор\"." + + + + + + "ОК" "Нет, спасибо" + + + + "Скрыть параметр \"%1$s\"?" "Этот параметр появится в следующий раз, когда вы включите его." "Скрыть" @@ -592,8 +605,7 @@ "С помощью этой функции вы можете устанавливать уровень важности уведомлений от 0 до 5 для каждого приложения.\n\n""Уровень 5"\n"‒ Помещать уведомления в начало списка.\n‒ Показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 4\n"\n"‒ Не показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 3\n"\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\nУровень 2\n"\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\nУровень 1\n"\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\n‒ Не показывать на экране блокировки и в строке состояния.\n‒ Помещать уведомления в конец списка.\nУровень 0\n"\n"‒ Блокировать все уведомления приложения." "Уведомления" "Вы больше не будете получать эти уведомления." - - + "Обычно вы скрываете эти уведомления.\nПоказывать их?" "Показывать эти уведомления?" "Отключить уведомления" "Показывать" diff --git a/packages/SystemUI/res/values-si/config.xml b/packages/SystemUI/res/values-si/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-si/config.xml +++ b/packages/SystemUI/res/values-si/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 8c9208b68549d26fd85ce914032932a2672f5803..b041d48d1cc469981c6b3055a6d504a6f267039f 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -103,12 +103,9 @@ "කැමරාව විවෘත කරන්න" "නව කාර්යය සැකැස්ම තෝරන්න" "අවලංගු කරන්න" - - - - - - + "ඇඟිලි සලකුණු නිරූපකය" + "යෙදුම් නිරූපකය" + "උදවු පණිවිඩ ප්‍රදේශය" "ගැළපෙන විශාලන බොත්තම." "විශාල තිරය වෙත කුඩාව විශාලනය කරන්න." "බ්ලූටූත් සම්බන්ධිතයි." @@ -311,6 +308,8 @@ "Wi-Fi අක්‍රියයි" "Wi-Fi ක්‍රියාත්මකයි" "Wi-Fi ජාල ලබා ගත නොහැකිය" + + "Cast" "කාස්ට් කිරීම" "නම් නොකළ උපාංගය" @@ -327,9 +326,11 @@ "සම්බන්ධ වෙමින්..." "ටෙදරින්" "හොට්ස්පොට්" - - - + "ක්‍රියාත්මක කරමින්…" + + උපාංග %d + උපාංග %d + "දැනුම්දීම්" "සැණෙළි ආලෝකය" "ජංගම දත්ත" @@ -499,11 +500,24 @@ "දැන් ක්‍රියාවිරහිත කරන්න" "දිග හරින්න" "හකුළන්න" + "ප්‍රතිදාන උපාංගය මාරු කරන්න" "තීරය අමුණන ලදි" "මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර ආපසු අල්ලාගෙන සිටින්න." + + "මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර අල්ලාගෙන සිටින්න." + + + + + + "හරි, තේරුණා" "එපා ස්තූතියි" + + + + "%1$s සඟවන්නද?" "ඊළඟ අවස්ථාවේ සැකසීම් තුළ ඔබ එය සක්‍රිය කළ විට එය නැවත දිසිවේ." "සඟවන්න" @@ -583,8 +597,7 @@ "බල දැනුම්දීම් පාලන සමගින්, ඔබට යෙදුමක දැනුම්දීම් සඳහා වැදගත්කම 0 සිට 5 දක්වා සැකසිය හැකිය. \n\n""5 මට්ටම"" \n- දැනුම්දීම් ලැයිස්තුවේ ඉහළින්ම පෙන්වන්න \n- පූර්ණ තිර බාධාවට ඉඩ දෙන්න \n- සැම විට එබී බලන්න \n\n""4 මට්ටම"" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- සැම විට එබී බලන්න \n\n""3 මට්ටම"" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n\n""2 මට්ටම"" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n\n""1 මට්ටම"" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n- අගුලු තිරය සහ තත්ත්ව තීරුව වෙතින් සඟවන්න \n- දැනුම්දීම් ලැයිස්තුවේ පහළින්ම පෙන්වන්න \n\n""0 මට්ටම"" \n- යෙදුම වෙතින් වන සියලු දැනුම් දීම් සඟවන්න." "දැනුම් දීම්" "ඔබට තවදුරටත් මෙම දැනුම්දීම් නොදකිනු ඇත" - - + "ඔබ සාමාන්‍යයෙන් මෙවැනි දැනුම්දීම් ඉවත දමයි. \nඒවා දිගටම පෙන්වන්නද?" "මෙම දැනුම්දීම් පෙන්වමින් තබන්නද?" "දැනුම්දීම් නවත්වන්න" "පෙන්වමින් තබන්න" diff --git a/packages/SystemUI/res/values-sk/config.xml b/packages/SystemUI/res/values-sk/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-sk/config.xml +++ b/packages/SystemUI/res/values-sk/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-sl/config.xml b/packages/SystemUI/res/values-sl/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-sl/config.xml +++ b/packages/SystemUI/res/values-sl/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-sq/config.xml b/packages/SystemUI/res/values-sq/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-sq/config.xml +++ b/packages/SystemUI/res/values-sq/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-sr/config.xml b/packages/SystemUI/res/values-sr/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-sr/config.xml +++ b/packages/SystemUI/res/values-sr/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-sv/config.xml b/packages/SystemUI/res/values-sv/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-sv/config.xml +++ b/packages/SystemUI/res/values-sv/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-sw/config.xml b/packages/SystemUI/res/values-sw/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-sw/config.xml +++ b/packages/SystemUI/res/values-sw/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 3880540bb9d314bffb941661845442c002e9cbca..a74f8a4c4e191637447d695d20ff4b7b2bfb3719 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -103,12 +103,9 @@ "fungua kamera" "Chagua muundo mpya wa kazi" "Ghairi" - - - - - - + "Aikoni ya alama ya kidole" + "Aikoni ya programu" + "Sehemu ya ujumbe wa usaidizi" "Kichupo cha kukuza kwa utangamanifu" "Kuza kidogo kwa skrini kubwa." "Bluetooth imeunganishwa." @@ -311,6 +308,8 @@ "Wi-Fi Imezimwa" "Imewasha Wi-Fi" "Hakuna mitandao ya Wi-Fi inayopatikana" + + "Tuma" "Inatuma" "Kifaa hakina jina" @@ -327,9 +326,11 @@ "Inaunganisha..." "Kusambaza mtandao" "Mtandao-hewa" - - - + "Inawasha..." + + Vifaa %d + Kifaa %d + "Arifa" "Tochi" "Data ya mtandao wa simu" @@ -339,10 +340,8 @@ "%s imetumika" "kikomo %s" "Onyo %s" - - - - + "Wasifu wa kazini" + "Umezima kipengele cha arifa na programu" "Mwanga wa Usiku" "Itawashwa machweo" "Hadi macheo" @@ -360,8 +359,7 @@ "%s imezimwa katika hali salama." "Futa zote" "Buruta hapa ili utumie skrini iliyogawanywa" - - + "Telezesha kidole juu ili ubadilishe programu" "Gawanya Mlalo" "Gawanya Wima" "Maalum Iliyogawanywa" @@ -502,11 +500,24 @@ "Izime sasa" "Panua" "Kunja" + "Badilisha kifaa cha kutoa sauti" "Skrini imebandikwa" "Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kipengele cha Nyuma na Muhtasari ili ubandue." + + "Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kipengele cha Muhtasari ili ubandue." + + + + + + "Nimeelewa" "Hapana, asante" + + + + "Ungependa kuficha %1$s?" "Itaonekana tena wakati mwingine utakapoiwasha katika mipangilio." "Ficha" @@ -586,8 +597,7 @@ "Ukiwa na udhibiti wa arifa, unaweza kuweka kiwango cha umuhimu wa arifa za programu kuanzia 0 hadi 5. \n\n""Kiwango cha 5"" \n- Onyesha katika sehemu ya juu ya orodha ya arifa \n- Ruhusu ukatizaji wa skrini nzima \n- Ruhusu arifa za kuchungulia kila wakati\n\n""Kiwango cha 4"" \n- Zuia ukatizaji wa skrini nzima\n- Ruhusu arifa za kuchungulia kila wakati \n\n""Kiwango cha 3"" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia\n\n""Kiwango cha 2"" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti au mtetemo \n\n""Kiwango cha 1"" \n- Zuia ukatizaji wa skrini nzima \n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti na mtetemo \n- Usionyeshe skrini iliyofungwa na sehemu ya arifa \n- Onyesha katika sehemu ya chini ya orodha ya arifa \n\n""Kiwango cha 0"" \n- Zuia arifa zote kutoka programu" "Arifa" "Hutaona tena arifa hizi" - - + "Wewe huondoa arifa hizi. \nUngependa kuzionyesha?" "Ungependa kuendelea kuonyesha arifa hizi?" "Acha kuonyesha arifa" "Endelea kuonyesha" diff --git a/packages/SystemUI/res/values-ta/config.xml b/packages/SystemUI/res/values-ta/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ta/config.xml +++ b/packages/SystemUI/res/values-ta/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 774b2f24197ba439c7be3e706cd54047cd7823fa..c8ff5a175c953f23bcabe1946da9ad134f169242 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -103,12 +103,9 @@ "கேமராவைத் திற" "புதிய பணி தளவமைப்பைத் தேர்ந்தெடுக்கவும்" "ரத்துசெய்" - - - - - - + "கைரேகை ஐகான்" + "பயன்பாட்டு ஐகான்" + "உதவிச் செய்திக்கான பகுதி" "பொருந்துமாறு அளவை மாற்றும் பொத்தான்." "சிறியதிலிருந்து பெரிய திரைக்கு அளவை மாற்றும்." "புளூடூத் இணைக்கப்பட்டது." @@ -311,6 +308,8 @@ "வைஃபையை முடக்கு" "வைஃபை இயக்கத்தில்" "வைஃபை நெட்வொர்க்குகள் இல்லை" + + "Cast" "அனுப்புகிறது" "பெயரிடப்படாத சாதனம்" @@ -327,9 +326,11 @@ "இணைக்கிறது..." "டெதெரிங்" "ஹாட்ஸ்பாட்" - - - + "ஆன் செய்கிறது..." + + %d சாதனங்கள் + %d சாதனம் + "அறிவிப்புகள்" "டார்ச் லைட்" "மொபைல் டேட்டா" @@ -339,10 +340,8 @@ "பயன்படுத்தியது - %s" "%s வரம்பு" "%s எச்சரிக்கை" - - - - + "பணிச் சுயவிவரம்" + "அறிவிப்புகள் & ஆப்ஸ் ஆஃப் செய்யப்பட்டுள்ளன" "இரவு ஒளி" "மாலையில் ஆன் செய்" "சூரிய உதயம் வரை" @@ -360,8 +359,7 @@ "பாதுகாப்புப் பயன்முறையில் %s முடக்கப்பட்டது." "அனைத்தையும் அழி" "திரைப் பிரிப்பைப் பயன்படுத்த, இங்கே இழுக்கவும்" - - + "ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, மேல்நோக்கி ஸ்வைப் செய்க" "கிடைமட்டமாகப் பிரி" "செங்குத்தாகப் பிரி" "தனிவிருப்பத்தில் பிரி" @@ -502,11 +500,25 @@ "இப்போதே முடக்கு" "விரிவாக்கு" "சுருக்கு" + + "திரை பொருத்தப்பட்டது" "பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, முந்தையது மற்றும் மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்." + + "பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்." + + + + + + "புரிந்தது" "வேண்டாம்" + + + + "%1$sஐ மறைக்கவா?" "அடுத்த முறை அமைப்புகளில் மீண்டும் இயக்கும்போது, இது மீண்டும் தோன்றும்." "மறை" @@ -586,8 +598,7 @@ "ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள் மூலம், பயன்பாட்டின் அறிவிப்புகளுக்கு முக்கியத்துவ நிலையை (0-5) அமைக்கலாம். \n\n""நிலை 5"" \n- அறிவிப்புப் பட்டியலின் மேலே காட்டும் \n- முழுத் திரைக் குறுக்கீட்டை அனுமதிக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n""நிலை 4"" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n""நிலை 3"" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n\n""நிலை 2"" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது, அதிர்வுறாது \n\n""நிலை 1"" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது அல்லது அதிர்வுறாது \n- பூட்டுத்திரை மற்றும் நிலைப்பட்டியிலிருந்து மறைக்கும் \n- அறிவிப்புகள் பட்டியலின் கீழே காட்டும் \n\n""நிலை 0"" \n- பயன்பாட்டின் எல்லா அறிவிப்புகளையும் தடுக்கும்" "அறிவிப்புகள்" "இந்த அறிவிப்புகளை இனி பார்க்கமாட்டீர்கள்" - - + "வழக்கமாக, இந்த அறிவிப்புகளை நிராகரிக்கிறீர்கள். \nதொடர்ந்து இவற்றைக் காட்டலாமா?" "இந்த அறிவிப்புகளைத் தொடர்ந்து காட்டவா?" "அறிவிப்புகளை நிறுத்து" "அறிவிப்புகளைத் தொடர்ந்து காட்டு" diff --git a/packages/SystemUI/res/values-te/config.xml b/packages/SystemUI/res/values-te/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-te/config.xml +++ b/packages/SystemUI/res/values-te/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index e143b906f7f83cdba74ebb43878792e51bcbc98c..292fddd0a90a2d7be37a82bbc38bd4322a979492 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -103,12 +103,9 @@ "కెమెరాను తెరువు" "కొత్త విధి లేఅవుట్‌ను ఎంచుకోండి" "రద్దు చేయి" - - - - - - + "వేలిముద్ర చిహ్నం" + "అప్లికేషన్ చిహ్నం" + "సహాయ సందేశ ప్రాంతం" "అనుకూలత జూమ్ బటన్." "చిన్న స్క్రీన్ నుండి పెద్దదానికి జూమ్ చేయండి." "బ్లూటూత్ కనెక్ట్ చేయబడింది." @@ -311,6 +308,8 @@ "Wi-Fi ఆఫ్‌లో ఉంది" "Wi-Fi ఆన్‌లో ఉంది" "Wi-Fi నెట్‌వర్క్‌లు ఏవీ అందుబాటులో లేవు" + + "ప్రసారం చేయండి" "ప్రసారం చేస్తోంది" "పేరులేని పరికరం" @@ -327,9 +326,11 @@ "కనెక్ట్ అవుతోంది..." "టీథరింగ్" "హాట్‌స్పాట్" - - - + "ఆన్ చేస్తోంది…" + + %d పరికరాలు + %d పరికరం + "నోటిఫికేషన్‌లు" "ఫ్లాష్‌లైట్" "మొబైల్ డేటా" @@ -339,10 +340,8 @@ "%s వినియోగించబడింది" "%s పరిమితి" "%s హెచ్చరిక" - - - - + "కార్యాలయ ప్రొఫైల్" + "నోటిఫికేషన్‌లు & యాప్‌లు ఆఫ్ చేయి" "రాత్రి కాంతి" "సూర్యాస్తమయానికి" "సూర్యోదయం వరకు" @@ -360,8 +359,7 @@ "%s సురక్షిత-మోడ్‌లో నిలిపివేయబడింది." "అన్నీ తీసివేయి" "విభజన స్క్రీన్‌ను ఉపయోగించడానికి ఇక్కడ లాగండి" - - + "యాప్‌లను మార్చడం కోసం ఎగువకు స్వైప్ చేయండి" "సమతలంగా విభజించు" "లంబంగా విభజించు" "అనుకూలంగా విభజించు" @@ -502,11 +500,25 @@ "ఇప్పుడు ఆఫ్ చేయండి" "విస్తరింపజేయండి" "కుదించండి" + + "స్క్రీన్ పిన్ చేయబడింది" "దీని వలన మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి వెనుకకు మరియు స్థూలదృష్టి తాకి & అలాగే పట్టుకోండి." + + "దీని వలన మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి స్థూలదృష్టిని తాకి & అలాగే పట్టుకోండి." + + + + + + "అర్థమైంది" "వద్దు, ధన్యవాదాలు" + + + + "%1$sని దాచాలా?" "మీరు సెట్టింగ్‌ల్లో దీన్ని ఆన్ చేసిన తదుపరిసారి ఇది కనిపిస్తుంది." "దాచు" @@ -586,8 +598,7 @@ "పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు యాప్ నోటిఫికేషన్‌ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n""స్థాయి 5"" \n- నోటిఫికేషన్ జాబితా పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n""స్థాయి 4"\n"- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n""స్థాయి 3"" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n""స్థాయి 2"" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n""స్థాయి 1"" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ జాబితా దిగువ భాగంలో చూపబడతాయి \n\n""స్థాయి 0"" \n- యాప్ నుండి అన్ని నోటిఫికేషన్‌లు బ్లాక్ చేయబడతాయి" "నోటిఫికేషన్‌లు" "ఇకపై మీకు ఈ నోటిఫికేషన్‌లు కనిపించవు" - - + "మీరు సాధారణంగా ఈ నోటిఫికేషన్‌లను విస్మరిస్తారు. \nవాటి ప్రదర్శనను కొనసాగించాలా?" "ఈ నోటిఫికేషన్‌లను చూపిస్తూ ఉండాలా?" "నోటిఫికేషన్‌లను ఆపివేయి" "చూపిస్తూనే ఉండు" diff --git a/packages/SystemUI/res/values-th/config.xml b/packages/SystemUI/res/values-th/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-th/config.xml +++ b/packages/SystemUI/res/values-th/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-tl/config.xml b/packages/SystemUI/res/values-tl/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-tl/config.xml +++ b/packages/SystemUI/res/values-tl/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-tr/config.xml b/packages/SystemUI/res/values-tr/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-tr/config.xml +++ b/packages/SystemUI/res/values-tr/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 8a289be4251e726325cccde3c6553e1579b1d533..9adc14150c7f94f69451e7e8fced2d5e8dd116b5 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -103,12 +103,9 @@ "kamerayı aç" "Yeni görev düzenini seçin" "İptal" - - - - - - + "Parmak izi simgesi" + "Uygulama simgesi" + "Yardım mesajı alanı" "Uyumluluk zum düğmesi." "Daha büyük ekrana daha küçük yakınlaştır." "Bluetooth bağlandı." @@ -311,6 +308,8 @@ "Kablosuz Kapalı" "Kablosuz Bağlantı Açık" "Kullanılabilir kablosuz ağ yok" + + "Yayınla" "Yayınlanıyor" "Adsız cihaz" @@ -327,9 +326,11 @@ "Bağlanılıyor..." "Tethering" "Hotspot" - - - + "Açılıyor..." + + %d cihaz + %d cihaz + "Bildirimler" "Fener" "Mobil veri" @@ -339,10 +340,8 @@ "%s kullanıldı" "Sınır: %s" "%s uyarısı" - - - - + "İş profili" + "Bildirimler ve uygulamalar kapalı" "Gece Işığı" "Gün batımı açılacak" "Gün doğumuna kadar" @@ -360,8 +359,7 @@ "%s, güvenli modda devre dışıdır." "Tümünü temizle" "Ekranı bölünmüş olarak kullanmak için burayı sürükleyin" - - + "Uygulamalar arasında geçiş yapmak için yukarı kaydırın" "Yatay Ayırma" "Dikey Ayırma" "Özel Ayırma" @@ -502,11 +500,25 @@ "Şimdi kapat" "Genişlet" "Daralt" + + "Ekran sabitlendi" "Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Genel Bakış\'a dokunup basılı tutun." + + "Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Genel bakış\'a dokunup basılı tutun." + + + + + + "Anladım" "Hayır, teşekkürler" + + + + "%1$s gizlensin mi?" "Ayarlardan etkinleştirdiğiniz bir sonraki sefer tekrar görünür." "Gizle" @@ -586,8 +598,7 @@ "Güç bildirim kontrolleriyle, bir uygulamanın bildirimleri için 0 ile 5 arasında bir önem düzeyi ayarlayabilirsiniz. \n\n""5. Düzey"" \n- Bildirim listesinin en üstünde gösterilsin \n- Tam ekran kesintisine izin verilsin \n- Ekranda her zaman kısaca belirsin \n\n""4. Düzey"" \n- Tam ekran kesintisi engellensin \n- Ekranda her zaman kısaca belirsin \n\n""3. Düzey"" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n\n""2. Düzey"" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman belirmesin \n- Hiçbir zaman ses çıkarmasın ve titreştirmesin \n\n""1. Düzey"" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n- Hiçbir zaman ses çıkarmasın veya titreştirmesin \n- Kilit ekranından ve durum çubuğundan gizlensin \n- Bildirim listesinin en altında gösterilsin \n\n""0. Düzey"" \n- Uygulamadan gelen tüm bildirimler engellensin" "Bildirimler" "Bu bildirimleri artık görmeyeceksiniz" - - + "Bu bildirimleri genellikle kapatıyorsunuz. \nBildirimler gösterilmeye devam edilsin mi?" "Bu bildirimler gösterilmeye devam edilsin mi?" "Bildirimleri durdur" "Göstermeye devam et" diff --git a/packages/SystemUI/res/values-uk/config.xml b/packages/SystemUI/res/values-uk/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-uk/config.xml +++ b/packages/SystemUI/res/values-uk/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index f2961437380f61393db8e442878b17853a621623..38347531fa0508019d2d9aebdb8e49f5cabb78dd 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -105,12 +105,9 @@ "відкрити камеру" "Виберіть новий макет завдання" "Скасувати" - - - - - - + "Значок відбитка пальця" + "Значок додатка" + "Область довідкового повідомлення" "Кнопка масштабування сумісності." "Збільшення екрана." "Bluetooth під’єднано." @@ -317,6 +314,8 @@ "Wi-Fi вимкнено" "Wi-Fi увімкнено" "Немає доступних мереж Wi-Fi" + + "Трансляція" "Трансляція" "Пристрій без назви" @@ -333,9 +332,13 @@ "З’єднання…" "Режим модема" "Точка доступу" - - - + "Увімкнення…" + + %d пристрій + %d пристрої + %d пристроїв + %d пристрою + "Сповіщення" "Ліхтарик" "Мобільне передавання даних" @@ -345,10 +348,8 @@ "Використовується: %s" "Обмеження: %s" "Застереження: %s" - - - - + "Робочий профіль" + "Сповіщення й додатки вимкнено" "Нічний режим" "Вмикається ввечері" "До сходу сонця" @@ -366,8 +367,7 @@ "Додаток %s вимкнено в безпечному режимі." "Очистити все" "Перетягніть сюди, щоб увімкнути режим розділеного екрана" - - + "Проводьте пальцем угору, щоб переходити між додатками" "Розділити горизонтально" "Розділити вертикально" "Розділити (власний варіант)" @@ -508,11 +508,24 @@ "Вимкнути" "Розгорнути" "Згорнути" + "Увімкніть пристрій виведення" "Екран закріплено" "Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопки \"Назад\" та \"Огляд\"." + + "Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопку \"Огляд\"." + + + + + + "Зрозуміло" "Ні, дякую" + + + + "Сховати %1$s?" "З’явиться знову, коли ви ввімкнете його в налаштуваннях." "Сховати" @@ -592,8 +605,7 @@ "За допомогою елементів керування сповіщеннями ви можете налаштувати пріоритет сповіщень додатка – від 0 до 5 рівня. \n\n""Рівень 5"\n"- Показувати сповіщення вгорі списку \n- Виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n""Рівень 4"\n"- Не виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n""Рівень 3"\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n\n""Рівень 2"\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n\n""Рівень 1"\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n- Не показувати на заблокованому екрані та в рядку стану \n- Показувати сповіщення внизу списку \n\n""Рівень 0"\n"- Блокувати всі сповіщення з додатка" "Сповіщення" "Ви більше не бачитимете цих сповіщень" - - + "Ви зазвичай закриваєте ці сповіщення. \nПоказувати їх?" "Чи показувати ці сповіщення надалі?" "Не показувати сповіщення" "Показувати надалі" diff --git a/packages/SystemUI/res/values-ur/config.xml b/packages/SystemUI/res/values-ur/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-ur/config.xml +++ b/packages/SystemUI/res/values-ur/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 8099ef48c4c4bf1233973627f96af758be090dc6..9ebdfeb0c0b5d02bbe74bc74198ed32101995066 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -103,12 +103,9 @@ "کیمرا کھولیں" "نئے کام کا لے آؤٹ منتخب کریں" "منسوخ کریں" - - - - - - + "فنگر پرنٹ آئیکن" + "ایپلیکیشن کا آئیکن" + "امدادی پیغام کا علاقہ" "مطابقت پذیری زوم بٹن۔" "چھوٹی سے بڑی اسکرین پر زوم کریں۔" "بلوٹوتھ مربوط ہے۔" @@ -311,6 +308,8 @@ "‏Wi-Fi آف ہے" "‏Wi-Fi آن ہے" "‏کوئی WI-FI نیٹ ورک دستیاب نہیں" + + "کاسٹ کریں" "کاسٹنگ" "بغیر نام والا آلہ" @@ -327,9 +326,11 @@ "مربوط ہو رہا ہے…" "ٹیدرنگ" "ہاٹ اسپاٹ" - - - + "آن ہو رہا ہے…" + + ‏%d آلات + ‏%d آلہ + "اطلاعات" "فلیش لائٹ" "موبائل ڈیٹا" @@ -339,10 +340,8 @@ "%s استعمال کردہ" "%s حد" "%s وارننگ" - - - - + "دفتری پروفائل" + "اطلاعات اور ایپس آف ہیں" "نائٹ لائٹ" "غروب آفتاب کے وقت آن ہوگی" "طلوع آفتاب تک" @@ -360,8 +359,7 @@ "محفوظ موڈ میں %s غیر فعال ہوتی ہے۔" "سبھی کو صاف کریں" "اسپلٹ اسکرین استعمال کرنے کیلئے یہاں گھسیٹیں" - - + "ایپس سوئچ کرنے کیلئے اوپر سوائپ کریں" "بلحاظ افقی الگ کریں" "بلحاظ عمودی الگ کریں" "بلحاظ حسب ضرورت الگ کریں" @@ -502,11 +500,25 @@ "ابھی بند کریں" "پھیلائیں" "سکیڑیں" + + "اسکرین پن کردہ ہے" "یہ اسے اس وقت تک نظر میں رکھتا ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے پیچھے اور مجموعی جائزہ بٹنز کو ٹچ کریں اور دبائے رکھیں۔" + + "یہ اسے اس وقت تک نظر میں رکھتا ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے مجموعی جائزہ بٹن کو ٹچ کریں اور دبائے رکھیں۔" + + + + + + "سمجھ آ گئی" "نہیں شکریہ" + + + + "%1$s کو چھپائیں؟" "اگلی بار جب آپ اسے ترتیبات میں آن کریں گے تو یہ ظاہر ہوگی۔" "چھپائیں" @@ -586,8 +598,7 @@ "پاور اطلاع کنٹرولز کے ساتھ آپ کسی ایپ کی اطلاعات کیلئے 0 سے 5 تک اہمیت کی سطح سیٹ کر سکتے ہیں۔ \n\n""سطح 5"\n"- اطلاعات کی فہرست کے اوپر دکھائیں \n- پوری اسکرین کی مداخلت کی اجازت دیں \n- ہمیشہ جھانکنا\n\n""سطح 4"\n"- پوری اسکرین کی مداخلت کو روکیں \n- ہمیشہ جھانکنا\n\n""سطح 3"\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n\n""سطح 2"\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n- کبھی آواز اور ارتعاش پیدا نہ کرنا \n\n"" سطح 1"\n"- پوری اسکرین کی مداخلت کو روکنا \n- کبھی نہ جھانکنا \n- کبھی بھی آواز یا ارتعاش پیدا نہ کرنا\n- مقفل اسکرین اور اسٹیٹس بار سے چھپانا \n - اطلاع کی فہرست کی نیچے دکھانا \n\n""سطح 0"\n"- ایپ سے تمام اطلاعات مسدود کریں" "اطلاعات" "آپ کو یہ اطلاعات مزید دکھائی نہیں دیں گی" - - + "آپ عام طور پر ان اطلاعات کو مسترد کرتے ہیں۔ \nان کو دکھاتے رہیں؟" "یہ اطلاعات دکھانا جاری رکھیں؟" "اطلاعات روک دیں" "دکھانا جاری رکھیں" diff --git a/packages/SystemUI/res/values-uz/config.xml b/packages/SystemUI/res/values-uz/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-uz/config.xml +++ b/packages/SystemUI/res/values-uz/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 612859ba7e3a95440d22e185002bf752aec404c0..37d81182c5bd7b887bde257c85db9729d67149e1 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -103,12 +103,9 @@ "kamerani ochish" "Yangi vazifa tartibini tanlash" "Bekor qilish" - - - - - - + "Barmoq izi belgisi" + "Ilova ikonkasi" + "Yordam xabari" "Kattalashtirish tugmasi mosligi." "Kattaroq ekran uchun kichikroqni kattalashtirish." "Bluetooth ulandi." @@ -288,7 +285,7 @@ "Batareya quvvati: %s" "Audio" "Garnitura" - "Matn kiritish" + "Kirish" "Yorqinlik" "Avtomatik burilish" "Ekranning avtomatik burilishi" @@ -313,6 +310,8 @@ "Wi-Fi o‘chiq" "Wi-Fi yoqilgan" "Hech qanday Wi-Fi tarmog‘i mavjud emas" + + "Translatsiya" "Translatsiya qilinmoqda" "Nomsiz qurilma" @@ -329,9 +328,11 @@ "Ulanmoqda…" "Modem rejimi" "Hotspot" - - - + "Yoqilmoqda…" + + %d ta qurilma + %d ta qurilma + "Bildirishnomalar" "Fonar" "Mobil internet" @@ -341,10 +342,8 @@ "%s ishlatilgan" "Cheklov: %s" "Ogohlantirish: %s" - - - - + "Ishchi profil" + "Bildirishnomalar va ilovalar o‘chiq" "Tungi rejim" "Kunbotarda yoqish" "Quyosh chiqqunicha" @@ -362,8 +361,7 @@ "Xavfsiz rejimda %s ilovasi o‘chirib qo‘yildi." "Hammasini tozalash" "Ekranni bo‘lish xususiyatidan foydalanish uchun bu yerga torting" - - + "Ilovalarni almashtirish uchun ekranni tepaga suring" "Gorizontal yo‘nalishda bo‘lish" "Vertikal yo‘nalishda bo‘lish" "Boshqa usulda bo‘lish" @@ -504,11 +502,25 @@ "O‘chiring" "Yoyish" "Yig‘ish" + + "Ekran qadaldi" "Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Orqaga” va “Umumiy ma’lumot” tugmalarini bosib turing." + + "Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Umumiy ma’lumot” tugmasini bosib turing." + + + + + + "OK" "Yo‘q, kerakmas" + + + + "%1$s berkitilsinmi?" "Keyingi safar sozlamalardan yoqilgan paydo bo‘ladi." "Berkitish" @@ -588,8 +600,7 @@ "Bildirishnomalar uchun kengaytirilgan boshqaruv yordamida ilova bildirishnomalarining muhimlik darajasini (0-5) sozlash mumkin. \n\n""5-daraja"" \n- Bildirishnomani ro‘yxatning boshida ko‘rsatish \n- To‘liq ekranli bildirishnomalarni ko‘rsatish \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n""4-daraja"" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n""3-daraja"" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n\n""2-daraja"" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n\n""1-daraja"" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n- Ekran qulfi va holat qatorida ko‘rsatmaslik \n- Bildirishnomani ro‘yxatning oxirida ko‘rsatish \n\n""0-daraja"" \n- Ilovadan keladigan barcha bildirishnomalarni bloklash" "Bildirishnomalar" "Bu bildirishnomalar endi chiqmaydi" - - + "Odatda bunday bildirishnomalarni yopasiz. \nUlar ochiq tursinmi?" "Mazkur bildirishnomalar chiqaversinmi?" "Chiqmasin" "Ha" diff --git a/packages/SystemUI/res/values-vi/config.xml b/packages/SystemUI/res/values-vi/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-vi/config.xml +++ b/packages/SystemUI/res/values-vi/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-zh-rCN/config.xml b/packages/SystemUI/res/values-zh-rCN/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-zh-rCN/config.xml +++ b/packages/SystemUI/res/values-zh-rCN/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 1fa61c56f8f59365163a6b68540811983f6af5a9..5b2674837343430bfa15e60eeaa6a2f052eb7535 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -159,7 +159,7 @@ "LTE" "LTE+" "CDMA" - "漫游中" + "数据漫游" "EDGE" "WLAN" "无 SIM 卡。" diff --git a/packages/SystemUI/res/values-zh-rHK/config.xml b/packages/SystemUI/res/values-zh-rHK/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-zh-rHK/config.xml +++ b/packages/SystemUI/res/values-zh-rHK/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-zh-rTW/config.xml b/packages/SystemUI/res/values-zh-rTW/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-zh-rTW/config.xml +++ b/packages/SystemUI/res/values-zh-rTW/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 3fb64c957f5839e27f225e09dcdbb788e01d110b..79b0e111b3b98a7dd83e16dcc2286149bc2d1a68 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -103,12 +103,9 @@ "開啟攝影機" "選取新工作版面配置" "取消" - - - - - - + "指紋圖示" + "應用程式圖示" + "說明訊息區域" "相容性縮放按鈕。" "將較小螢幕的畫面放大在較大螢幕上顯示。" "藍牙連線已建立。" @@ -159,7 +156,7 @@ "LTE" "LTE+" "CDMA" - "漫遊中" + "數據漫遊" "Edge" "Wi-Fi" "沒有 SIM 卡。" @@ -311,6 +308,8 @@ "Wi-Fi 已關閉" "已開啟 Wi-Fi" "沒有 Wi-Fi 網路" + + "投放" "投放" "未命名的裝置" @@ -327,9 +326,11 @@ "連線中..." "網路共用" "無線基地台" - - - + "開啟中..." + + %d 個裝置 + %d 個裝置 + "通知" "手電筒" "行動數據" @@ -339,10 +340,8 @@ "已使用 %s" "上限為 %s" "%s 警告" - - - - + "Work 設定檔" + "已關閉通知和應用程式" "夜燈" "於日落時開啟" "於日出時關閉" @@ -360,8 +359,7 @@ "「%s」在安全模式中為停用狀態。" "全部清除" "拖曳到這裡即可使用分割畫面" - - + "向上滑動即可切換應用程式" "水平分割" "垂直分割" "自訂分割" @@ -502,11 +500,25 @@ "立即停用" "展開" "收合" + + "螢幕已固定" "這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住 [返回] 按鈕和 [總覽] 按鈕即可取消固定。" + + "這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住 [總覽] 按鈕即可取消固定。" + + + + + + "知道了" "不用了,謝謝" + + + + "隱藏%1$s?" "只要在設定頁面中重新啟用,就能再次看到快捷設定選項。" "隱藏" @@ -586,8 +598,7 @@ "只要使用電源通知控制項,你就能為應用程式通知設定從 0 到 5 的重要性等級。\n\n""等級 5"" \n- 顯示在通知清單頂端 \n- 允許全螢幕通知 \n- 一律允許短暫顯示通知 \n\n""等級 4"" \n- 禁止全螢幕通知 \n- 一律允許短暫顯示通知 \n\n""等級 3"" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n\n""等級 2"" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n\n""等級 1"" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n- 在鎖定畫面和狀態列中隱藏 \n- 顯示在通知清單底端 \n\n""等級 0"" \n- 封鎖應用程式的所有通知" "通知" "你不會再看到這些通知" - - + "你通常會關閉這些通知。\n要繼續顯示通知嗎?" "要繼續顯示這些通知嗎?" "停止顯示通知" "繼續顯示" diff --git a/packages/SystemUI/res/values-zu/config.xml b/packages/SystemUI/res/values-zu/config.xml index 477f2198e4a634aef3a15ec16a830ed1c912db9a..5309563e39861aca1ac767b7fee53064fa155041 100644 --- a/packages/SystemUI/res/values-zu/config.xml +++ b/packages/SystemUI/res/values-zu/config.xml @@ -22,6 +22,5 @@ - "com.android.launcher3/com.android.quickstep.TouchInteractionService" diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index a99b8cce46404de8f09d1474a7355e611aa660fd..d291a198f84317f725e9f761b235abde256fe102 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -103,12 +103,9 @@ "vula ikhamera" "Khetha isakhiwo somsebenzi omusha" "Khansela" - - - - - - + "Isithonjana sezigxivizo zeminwe" + "Isithonjana sohlelo lokusebenza" + "Indawo yosizo lomlayezo" "Inkinobho evumelekile yokusondeza" "Sondeza kancane esikrinini esikhudlwana" "Bluetooth ixhunyiwe" @@ -311,6 +308,8 @@ "I-Wi-Fi icimile" "I-Wi-Fi ivuliwe" "Awekho amanethiwekhi we-Wi-Fi atholakalayo" + + "Abalingisi" "Ukusakaza" "Idivayisi engenalo igama" @@ -327,9 +326,11 @@ "Iyaxhuma..." "Ukusebenzisa njengemodemu" "I-Hotspot" - - - + "Iyavula..." + + %d amadivayisi + %d amadivayisi + "Izaziso" "I-Flashlight" "Idatha yeselula" @@ -339,10 +340,8 @@ "%s isetshenzisiwe" "%s umkhawulo" "%s isexwayiso" - - - - + "Iphrofayela yomsebenzi" + "Izaziso nezinhlelo zokusebenza kuvaliwe" "Ukukhanya kwasebusuku" "Kuvulwe ekushoneni kwelanga" "Kuze kube sekuphumeni kwelanga" @@ -360,8 +359,7 @@ "I-%s ikhutshaziwe kumodi yokuphepha." "Sula konke" "Hudulela lapha ukuze usebenzise ukuhlukanisa kwesikrini" - - + "Swayiphela phezulu ukuze ushintshe izinhlelo zokusebenza" "Hlukanisa okuvundlile" "Hlukanisa okumile" "Hlukanisa kwezifiso" @@ -502,11 +500,24 @@ "Vala manje" "Nweba" "Goqa" + "Shintsha idivayisi yokukhipha" "Isikrini siphiniwe" "Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe okuthi Emuva Nokubuka konke ukuze ususe ukuphina." + + "Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe Ukubuka konke ukuze ususe ukuphina." + + + + + + "Ngiyitholile" "Cha ngiyabonga" + + + + "Fihla i-%1$s?" "Izovela ngesikhathi esilandelayo uma uvule lesi silungiselelo." "Fihla" @@ -586,8 +597,7 @@ "Ngezilawuli zesaziso zamandla, ungasetha ileveli ebalulekile kusuka ku-0 kuya ku-5 kusuka kuzaziso zohlelo lokusebenza. \n\n""Ileveli 5"" \n- Ibonisa phezulu kuhlu lwesaziso \n- Vumela ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n""Ileveli 4"" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n""Ileveli 3"" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n\n""Ileveli 2"" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo nokudlidliza \n\n""Ileveli 1"" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo noma ukudlidliza \n- Fihla kusuka kusikrini sokukhiya nebha yesimo \n- Bonisa phansi kohlu lwesaziso \n\n""Ileveli 0"" \n- Vimbela zonke izaziso kusuka kuhlelo lokusebenza" "Izaziso" "Ngeke usabona lezi zaziso" - - + "Uvamise ukucashisa lezi zaziso. \nQhubeka ulokhu uzibonisa?" "Qhubeka nokubonisa lezi zaziso?" "Misa izaziso" "Qhubeka nokubonisa" diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml new file mode 100755 index 0000000000000000000000000000000000000000..22c67235f2535cf265a1edf026b984ae2a3fb8c7 --- /dev/null +++ b/packages/SystemUI/res/values/arrays.xml @@ -0,0 +1,1127 @@ + + + + + + + + array/telephony_data_type_sim1 + array/telephony_data_type_sim1 + array/telephony_data_type_sim1 + + + + + 0 + + drawable/stat_sys_data_fully_connected_g + + drawable/stat_sys_data_fully_connected_e + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_1x + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_1x + + drawable/stat_sys_data_fully_connected_h + + drawable/stat_sys_data_fully_connected_h + + drawable/stat_sys_data_fully_connected_h + + 0 + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_g + + drawable/stat_sys_data_fully_connected_3g + + 0 + + + + + + + + + + + + + drawable/stat_sys_data_fully_connected_3g + + drawable/stat_sys_data_fully_connected_4g + + drawable/stat_sys_data_fully_connected_4g_plus + + + + + + 0 + + string/accessibility_data_connection_gprs + + string/accessibility_data_connection_edge + + string/accessibility_data_connection_3g + + string/accessibility_data_connection_cdma + + string/accessibility_data_connection_3g + + string/accessibility_data_connection_3g + + string/accessibility_data_connection_cdma + + string/accessibility_data_connection_3.5g + + string/accessibility_data_connection_3.5g + + string/accessibility_data_connection_3.5g + + 0 + + string/accessibility_data_connection_3g + + string/accessibility_data_connection_lte + + string/accessibility_data_connection_3g + + string/accessibility_data_connection_3.5g + + string/accessibility_data_connection_gprs + + string/accessibility_data_connection_3g + + 0 + + + + + string/accessibility_data_connection_3g + + string/accessibility_data_connection_4g + + + + + + array/data_activity_sim1 + array/data_activity_sim1 + array/data_activity_sim1 + + + + array/telephony_data_activity_unknown_sim1 + array/telephony_data_activity_g_sim1 + array/telephony_data_activity_e_sim1 + array/telephony_data_activity_2g_sim1 + array/telephony_data_activity_3g_sim1 + array/telephony_data_activity_4g_sim1 + array/telephony_data_activity_h_sim1 + array/telephony_data_activity_hp_sim1 + array/telephony_data_activity_1x_sim1 + array/telephony_data_activity_lte_sim1 + array/telephony_data_activity_4g_plus_sim1 + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + 0 + drawable/stat_sys_signal_in_auto_mirrored + drawable/stat_sys_signal_out_auto_mirrored + drawable/stat_sys_signal_inout_auto_mirrored + 0 + + + + + + + + + + + + + array/telephony_siganl_strength_sim1 + array/telephony_siganl_strength_sim1 + array/telephony_siganl_strength_sim1 + + + + + array/telephony_siganl_strength_roaming_sim1 + array/telephony_siganl_strength_roaming_sim1 + array/telephony_siganl_strength_roaming_sim1 + + + + array/telephony_signal_strength_g_sim1 + array/telephony_signal_strength_e_sim1 + array/telephony_signal_strength_3g_sim1 + array/telephony_signal_strength_4g_sim1 + array/telephony_signal_strength_h_sim1 + array/telephony_signal_strength_hp_sim1 + array/telephony_signal_strength_1x_sim1 + array/telephony_signal_strength_cdma_sim1 + array/telephony_signal_strength_umts_sim1 + + + + + + + + + + array/telephony_signal_strength_g_roaming_sim1 + array/telephony_signal_strength_e_roaming_sim1 + array/telephony_signal_strength_3g_roaming_sim1 + array/telephony_signal_strength_4g_roaming_sim1 + array/telephony_signal_strength_h_roaming_sim1 + array/telephony_signal_strength_hp_roaming_sim1 + array/telephony_signal_strength_1x_roaming_sim1 + array/telephony_signal_strength_cdma_roaming_sim1 + array/telephony_signal_strength_umts_roaming_sim1 + + + + + + + + + + array/signal_strength_g_normal_sim1 + array/signal_strength_g_fully_sim1 + + + + array/signal_strength_g_normal_roaming_sim1 + array/signal_strength_g_fully_roaming_sim1 + + + + array/signal_strength_e_normal_sim1 + array/signal_strength_e_fully_sim1 + + + + array/signal_strength_e_normal_roaming_sim1 + array/signal_strength_e_fully_roaming_sim1 + + + + array/signal_strength_3g_normal_sim1 + array/signal_strength_3g_fully_sim1 + + + + array/signal_strength_3g_normal_roaming_sim1 + array/signal_strength_3g_fully_roaming_sim1 + + + + array/signal_strength_4g_normal_sim1 + array/signal_strength_4g_fully_sim1 + + + + array/signal_strength_4g_normal_roaming_sim1 + array/signal_strength_4g_fully_roaming_sim1 + + + + array/signal_strength_h_normal_sim1 + array/signal_strength_h_fully_sim1 + + + + array/signal_strength_h_normal_roaming_sim1 + array/signal_strength_h_fully_roaming_sim1 + + + + array/signal_strength_hp_normal_sim1 + array/signal_strength_hp_fully_sim1 + + + + array/signal_strength_hp_normal_roaming_sim1 + array/signal_strength_hp_fully_roaming_sim1 + + + + array/signal_strength_1x_normal_sim1 + array/signal_strength_1x_fully_sim1 + + + + array/signal_strength_1x_normal_roaming_sim1 + array/signal_strength_1x_fully_roaming_sim1 + + + + array/signal_strength_cdma_normal_sim1 + array/signal_strength_cdma_fully_sim1 + + + + array/signal_strength_cdma_normal_roaming_sim1 + array/signal_strength_cdma_fully_roaming_sim1 + + + + array/signal_strength_umts_normal_sim1 + array/signal_strength_umts_fully_sim1 + + + + array/signal_strength_umts_normal_roaming_sim1 + array/signal_strength_umts_fully_roaming_sim1 + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + drawable/stat_sys_signal_0_fully + drawable/stat_sys_signal_1_fully + drawable/stat_sys_signal_2_fully + drawable/stat_sys_signal_3_fully + drawable/stat_sys_signal_4_fully + + + + + string/accessibility_no_phone + string/accessibility_phone_one_bar + string/accessibility_phone_two_bars + string/accessibility_phone_three_bars + string/accessibility_phone_signal_full + + + + + + drawable/stat_sys_signal_null + drawable/stat_sys_signal_null + drawable/stat_sys_signal_null + + + + + + drawable/stat_sys_no_sims + drawable/stat_sys_no_sims + drawable/stat_sys_no_sims + + + + + array/signal_strength_g_normal_sim2 + array/signal_strength_g_fully_sim2 + + + array/signal_strength_g_normal_roaming_sim2 + array/signal_strength_g_fully_roaming_sim2 + + + array/signal_strength_e_normal_sim2 + array/signal_strength_e_fully_sim2 + + + array/signal_strength_e_normal_roaming_sim2 + array/signal_strength_e_fully_roaming_sim2 + + + array/signal_strength_3g_normal_sim2 + array/signal_strength_3g_fully_sim2 + + + array/signal_strength_3g_normal_roaming_sim2 + array/signal_strength_3g_fully_roaming_sim2 + + + array/signal_strength_4g_normal_sim2 + array/signal_strength_4g_fully_sim2 + + + array/signal_strength_4g_normal_roaming_sim2 + array/signal_strength_4g_fully_roaming_sim2 + + + array/signal_strength_h_normal_sim2 + array/signal_strength_h_fully_sim2 + + + array/signal_strength_h_normal_roaming_sim2 + array/signal_strength_h_fully_roaming_sim2 + + + array/signal_strength_hp_normal_sim2 + array/signal_strength_hp_fully_sim2 + + + array/signal_strength_hp_normal_roaming_sim2 + array/signal_strength_hp_fully_roaming_sim2 + + + array/signal_strength_1x_normal_sim2 + array/signal_strength_1x_fully_sim2 + + + array/signal_strength_1x_normal_roaming_sim2 + array/signal_strength_1x_fully_roaming_sim2 + + + array/signal_strength_cdma_normal_sim2 + array/signal_strength_cdma_fully_sim2 + + + array/signal_strength_cdma_normal_roaming_sim2 + array/signal_strength_cdma_fully_roaming_sim2 + + + array/signal_strength_umts_normal_sim2 + array/signal_strength_umts_fully_sim2 + + + array/signal_strength_umts_normal_roaming_sim2 + array/signal_strength_umts_fully_roaming_sim2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + array/signal_strength_g_normal_sim3 + array/signal_strength_g_fully_sim3 + + + array/signal_strength_g_normal_roaming_sim3 + array/signal_strength_g_fully_roaming_sim3 + + + array/signal_strength_e_normal_sim3 + array/signal_strength_e_fully_sim3 + + + array/signal_strength_e_normal_roaming_sim3 + array/signal_strength_e_fully_roaming_sim3 + + + array/signal_strength_3g_normal_sim3 + array/signal_strength_3g_fully_sim3 + + + array/signal_strength_3g_normal_roaming_sim3 + array/signal_strength_3g_fully_roaming_sim3 + + + array/signal_strength_4g_normal_sim3 + array/signal_strength_4g_fully_sim3 + + + array/signal_strength_4g_normal_roaming_sim3 + array/signal_strength_4g_fully_roaming_sim3 + + + array/signal_strength_h_normal_sim3 + array/signal_strength_h_fully_sim3 + + + array/signal_strength_h_normal_roaming_sim3 + array/signal_strength_h_fully_roaming_sim3 + + + array/signal_strength_hp_normal_sim3 + array/signal_strength_hp_fully_sim3 + + + array/signal_strength_hp_normal_roaming_sim3 + array/signal_strength_hp_fully_roaming_sim3 + + + array/signal_strength_1x_normal_sim3 + array/signal_strength_1x_fully_sim3 + + + array/signal_strength_1x_normal_roaming_sim3 + array/signal_strength_1x_fully_roaming_sim3 + + + array/signal_strength_cdma_normal_sim3 + array/signal_strength_cdma_fully_sim3 + + + array/signal_strength_cdma_normal_roaming_sim3 + array/signal_strength_cdma_fully_roaming_sim3 + + + array/signal_strength_umts_normal_sim3 + array/signal_strength_umts_fully_sim3 + + + array/signal_strength_umts_normal_roaming_sim3 + array/signal_strength_umts_fully_roaming_sim3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @drawable/stat_sys_signal_0_3g + @drawable/stat_sys_signal_0_4g + @drawable/stat_sys_signal_1_3g + @drawable/stat_sys_signal_1_4g + @drawable/stat_sys_signal_2_3g + @drawable/stat_sys_signal_2_4g + @drawable/stat_sys_signal_3_3g + @drawable/stat_sys_signal_3_4g + @drawable/stat_sys_signal_4_3g + @drawable/stat_sys_signal_4_4g + @drawable/stat_sys_signal_0_3g_fully + @drawable/stat_sys_signal_0_4g_fully + @drawable/stat_sys_signal_1_3g_fully + @drawable/stat_sys_signal_1_4g_fully + @drawable/stat_sys_signal_2_3g_fully + @drawable/stat_sys_signal_2_4g_fully + @drawable/stat_sys_signal_3_3g_fully + @drawable/stat_sys_signal_3_4g_fully + @drawable/stat_sys_signal_4_3g_fully + @drawable/stat_sys_signal_4_4g_fully + + + + @drawable/stat_sys_signal_0_3g_default + @drawable/stat_sys_signal_0_4g_default + @drawable/stat_sys_signal_1_3g_default + @drawable/stat_sys_signal_1_4g_default + @drawable/stat_sys_signal_2_3g_default + @drawable/stat_sys_signal_2_4g_default + @drawable/stat_sys_signal_3_3g_default + @drawable/stat_sys_signal_3_4g_default + @drawable/stat_sys_signal_4_3g_default + @drawable/stat_sys_signal_4_4g_default + @drawable/stat_sys_signal_0_3g_default_fully + @drawable/stat_sys_signal_0_4g_default_fully + @drawable/stat_sys_signal_1_3g_default_fully + @drawable/stat_sys_signal_1_4g_default_fully + @drawable/stat_sys_signal_2_3g_default_fully + @drawable/stat_sys_signal_2_4g_default_fully + @drawable/stat_sys_signal_3_3g_default_fully + @drawable/stat_sys_signal_3_4g_default_fully + @drawable/stat_sys_signal_4_3g_default_fully + @drawable/stat_sys_signal_4_4g_default_fully + + diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 11870a10b797af22f3e5e477f5cc7cbeb2d004b3..6b6171f09ab5b2db4a2f1f516c9fefffb3f7bb67 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -46,7 +46,7 @@ com.android.systemui.statusbar.phone.StatusBar - com.android.launcher3/com.android.quickstep.TouchInteractionService + com.android.launcher3/com.android.quickstep.TouchInteractionService false @@ -124,7 +124,7 @@ - wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night + wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night,alarm @@ -145,6 +145,29 @@ true + + true + + + false + + + 0 + + + false + false @@ -348,8 +371,7 @@ com.android.systemui.util.leak.GarbageMonitor$Service com.android.systemui.LatencyTester com.android.systemui.globalactions.GlobalActionsComponent - com.android.systemui.RoundedCorners - com.android.systemui.EmulatedDisplayCutout + com.android.systemui.ScreenDecorations com.android.systemui.fingerprint.FingerprintDialogImpl @@ -395,7 +417,7 @@ true - false + true true diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index be1b24e07c7e1b55daf8f7ee197dfbac32710efe..f101cfd9b7f66c5bb8407286201e30a0b2f07cfa 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -262,7 +262,11 @@ @dimen/notification_panel_width - 120dp + + 12dp + + 100dp 320dp @@ -332,6 +336,8 @@ 16dp 24dp 16dp + + 6dp 64dp @@ -902,4 +908,11 @@ 32.0 400 + + + 500 + + 300 + + -30 diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index edda613f2fbc2e7ccf212ad853db42de8d4e2ab3..f9aa8216ec114648dcd4cc64bd01c1bf4dcc574b 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -96,5 +96,7 @@ + + diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 3b5de6aa899e23dddd2575349701db60e269d87c..4ee55a495f9fafb60be1c6d79ab20034631e742f 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -739,6 +739,8 @@ Wi-Fi On No Wi-Fi networks available + + Alarm Cast @@ -1272,16 +1274,30 @@ Collapse + + Switch output device + Screen is pinned This keeps it in view until you unpin. Touch & hold Back and Overview to unpin. + This keeps it in view until you unpin. Touch & hold Back and Home to unpin. This keeps it in view until you unpin. Touch & hold Overview to unpin. + This keeps it in view until you unpin. Touch & hold Home to unpin. + + To unpin this screen, touch & hold Back and Overview + buttons + To unpin this screen, touch & hold Back + and Home buttons Got it No thanks + + Screen pinned + Screen unpinned + Hide %1$s? diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 2497d208059214e30564180b6524c4816076e224..d2ed4d117cd89d0593f57e6c1334e6526ff7786d 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -410,16 +410,11 @@ ?android:attr/textColorSecondary - - + + diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java index 135c93c97af208c4e26cb00fd1d47a67254f0979..901d90eed70a990e39864766964fb4884a63dfeb 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java @@ -17,6 +17,9 @@ package com.android.test.hwui; import android.app.Activity; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; @@ -36,7 +39,9 @@ public class ColoredShadowsActivity extends Activity { private void setShadowColors(ViewGroup row, int rowIndex) { for (int i = 0; i < row.getChildCount(); i++) { View view = row.getChildAt(i); - view.setShadowColor(shadowColorFor(view)); + //view.setBackground(new MyHackyBackground()); + view.setOutlineSpotShadowColor(shadowColorFor(view)); + view.setOutlineAmbientShadowColor(shadowColorFor(view)); view.setElevation(6.0f * (rowIndex + 1)); } } @@ -44,12 +49,27 @@ public class ColoredShadowsActivity extends Activity { private int shadowColorFor(View view) { switch (view.getId()) { case R.id.grey: return 0xFF3C4043; - case R.id.blue: return 0xFF185ABC; - case R.id.red: return 0xFFB31412; - case R.id.yellow: return 0xFFEA8600; - case R.id.green: return 0xFF137333; + case R.id.blue: return Color.BLUE; + case R.id.red: return 0xFFEA4335; + case R.id.yellow: return 0xFFFBBC04; + case R.id.green: return 0xFF34A853; default: return 0xFF000000; } } + private static class MyHackyBackground extends ColorDrawable { + MyHackyBackground() { + super(0); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public int getAlpha() { + return 254; + } + } } diff --git a/tests/UsbTests/Android.mk b/tests/UsbTests/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..a04f32a6d714d195f36b43b202ff4a97b8c6135b --- /dev/null +++ b/tests/UsbTests/Android.mk @@ -0,0 +1,44 @@ +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_STATIC_JAVA_LIBRARIES := \ + frameworks-base-testutils \ + android-support-test \ + mockito-target-inline-minus-junit4 \ + platform-test-annotations \ + services.core \ + services.net \ + services.usb \ + truth-prebuilt \ + +LOCAL_JNI_SHARED_LIBRARIES := \ + libdexmakerjvmtiagent \ + +LOCAL_CERTIFICATE := platform + +LOCAL_PACKAGE_NAME := UsbTests + +LOCAL_COMPATIBILITY_SUITE := device-tests + +include $(BUILD_PACKAGE) diff --git a/tests/UsbTests/AndroidManifest.xml b/tests/UsbTests/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d606951bb5ed08a54735228bf1b92b7a257f3cd --- /dev/null +++ b/tests/UsbTests/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/tests/UsbTests/AndroidTest.xml b/tests/UsbTests/AndroidTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..0b623fbf2015d8ed7fe4daa3da296f01d1724cf8 --- /dev/null +++ b/tests/UsbTests/AndroidTest.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c491b4658999d7391c291615812e7cdda4794178 --- /dev/null +++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.hardware.usb.UsbManager; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.provider.Settings; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.server.FgThread; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * Tests for UsbHandler state changes. + */ +@RunWith(AndroidJUnit4.class) +public class UsbHandlerTest { + private static final String TAG = UsbHandlerTest.class.getSimpleName(); + + @Mock + private UsbDeviceManager mUsbDeviceManager; + @Mock + private UsbDebuggingManager mUsbDebuggingManager; + @Mock + private UsbAlsaManager mUsbAlsaManager; + @Mock + private UsbSettingsManager mUsbSettingsManager; + @Mock + private SharedPreferences mSharedPreferences; + @Mock + private SharedPreferences.Editor mEditor; + + private MockUsbHandler mUsbHandler; + + private static final int MSG_UPDATE_STATE = 0; + private static final int MSG_ENABLE_ADB = 1; + private static final int MSG_SET_CURRENT_FUNCTIONS = 2; + private static final int MSG_SYSTEM_READY = 3; + private static final int MSG_BOOT_COMPLETED = 4; + private static final int MSG_USER_SWITCHED = 5; + private static final int MSG_UPDATE_USER_RESTRICTIONS = 6; + private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12; + private static final int MSG_UPDATE_SCREEN_LOCK = 13; + + private Map mMockProperties; + private Map mMockGlobalSettings; + + private class MockUsbHandler extends UsbDeviceManager.UsbHandler { + boolean mIsUsbTransferAllowed; + Intent mBroadcastedIntent; + + MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager, + UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager, + UsbSettingsManager settingsManager) { + super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager); + mUseUsbNotification = false; + mIsUsbTransferAllowed = true; + mCurrentUsbFunctionsReceived = true; + } + + @Override + protected void setEnabledFunctions(long functions, boolean force) { + mCurrentFunctions = functions; + } + + @Override + protected void setSystemProperty(String property, String value) { + mMockProperties.put(property, value); + } + + @Override + protected void putGlobalSettings(ContentResolver resolver, String setting, int val) { + mMockGlobalSettings.put(setting, val); + } + + @Override + protected String getSystemProperty(String property, String def) { + if (mMockProperties.containsKey(property)) { + return mMockProperties.get(property); + } + return def; + } + + @Override + protected boolean isUsbTransferAllowed() { + return mIsUsbTransferAllowed; + } + + @Override + protected SharedPreferences getPinnedSharedPrefs(Context context) { + return mSharedPreferences; + } + + @Override + protected void sendStickyBroadcast(Intent intent) { + mBroadcastedIntent = intent; + } + } + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + mMockProperties = new HashMap<>(); + mMockGlobalSettings = new HashMap<>(); + when(mSharedPreferences.edit()).thenReturn(mEditor); + + mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(), + InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager, + mUsbAlsaManager, mUsbSettingsManager); + } + + @SmallTest + public void setFunctionsMtp() { + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_MTP)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + } + + @SmallTest + public void setFunctionsPtp() { + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_PTP)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_PTP, 0); + } + + @SmallTest + public void setFunctionsMidi() { + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_MIDI)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MIDI, 0); + } + + @SmallTest + public void setFunctionsRndis() { + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_RNDIS)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_RNDIS, 0); + } + + @SmallTest + public void enableAdb() { + sendBootCompleteMessages(mUsbHandler); + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 1)); + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + assertTrue(mUsbHandler.mAdbEnabled); + assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler + .USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB); + verify(mUsbDebuggingManager).setAdbEnabled(true); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1)); + + assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false)); + assertTrue(mUsbHandler.mBroadcastedIntent + .getBooleanExtra(UsbManager.USB_CONFIGURED, false)); + assertTrue(mUsbHandler.mBroadcastedIntent + .getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false)); + } + + @SmallTest + public void disableAdb() { + mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, + UsbManager.USB_FUNCTION_ADB); + mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(), + InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager, + mUsbAlsaManager, mUsbSettingsManager); + + sendBootCompleteMessages(mUsbHandler); + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 0)); + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + assertFalse(mUsbHandler.mAdbEnabled); + assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler + .USB_PERSISTENT_CONFIG_PROPERTY), ""); + verify(mUsbDebuggingManager).setAdbEnabled(false); + } + + @SmallTest + public void bootCompletedCharging() { + sendBootCompleteMessages(mUsbHandler); + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + } + + @Test + @SmallTest + public void bootCompletedAdbEnabled() { + mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, "adb"); + mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(), + InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager, + mUsbAlsaManager, mUsbSettingsManager); + + sendBootCompleteMessages(mUsbHandler); + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + assertEquals(mMockGlobalSettings.get(Settings.Global.ADB_ENABLED).intValue(), 1); + assertTrue(mUsbHandler.mAdbEnabled); + verify(mUsbDebuggingManager).setAdbEnabled(true); + } + + @SmallTest + public void userSwitchedDisablesMtp() { + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_MTP)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_USER_SWITCHED, + UserHandle.getCallingUserId() + 1)); + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + } + + @SmallTest + public void changedRestrictionsDisablesMtp() { + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_MTP)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + + mUsbHandler.mIsUsbTransferAllowed = false; + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_USER_RESTRICTIONS)); + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + } + + @SmallTest + public void disconnectResetsCharging() { + sendBootCompleteMessages(mUsbHandler); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_MTP)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 0, 0)); + + assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); + } + + @SmallTest + public void configuredSendsBroadcast() { + sendBootCompleteMessages(mUsbHandler); + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_MTP)); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1)); + + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false)); + assertTrue(mUsbHandler.mBroadcastedIntent + .getBooleanExtra(UsbManager.USB_CONFIGURED, false)); + assertTrue(mUsbHandler.mBroadcastedIntent + .getBooleanExtra(UsbManager.USB_FUNCTION_MTP, false)); + } + + @SmallTest + public void setScreenUnlockedFunctions() { + sendBootCompleteMessages(mUsbHandler); + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0)); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, + UsbManager.FUNCTION_MTP)); + assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + verify(mEditor).putString(String.format(Locale.ENGLISH, + UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), + UsbManager.USB_FUNCTION_MTP); + } + + @SmallTest + public void unlockScreen() { + when(mSharedPreferences.getString(String.format(Locale.ENGLISH, + UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), "")) + .thenReturn(UsbManager.USB_FUNCTION_MTP); + sendBootCompleteMessages(mUsbHandler); + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0)); + + assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0); + assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); + } + + private static void sendBootCompleteMessages(Handler handler) { + handler.handleMessage(handler.obtainMessage(MSG_BOOT_COMPLETED)); + handler.handleMessage(handler.obtainMessage(MSG_SYSTEM_READY)); + } +} \ No newline at end of file diff --git a/tests/net/OWNERS b/tests/net/OWNERS index 6f77e04da3c0580c3fff9361596eb734e49b0436..ce50558bf4f6d6840fc672bdb89db8fad314213a 100644 --- a/tests/net/OWNERS +++ b/tests/net/OWNERS @@ -1,7 +1,6 @@ set noparent ek@google.com -hugobenichi@google.com jchalard@google.com lorenzo@google.com satk@google.com diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index 099cfd457160e88365ef4ba2510d3da8df7f7c9e..e692652c7ea42a734243647758e7eccbc1dd9036 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -311,7 +311,7 @@ public class TetheringTest { // Emulate pressing the USB tethering button in Settings UI. mTethering.startTethering(TETHERING_USB, null, false); mLooper.dispatchAll(); - verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false); + verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); // Pretend we receive a USB connected broadcast. Here we also pretend // that the RNDIS function is somehow enabled, so that we see if we diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 069360e3d6f3535a698a842c996776db54046f73..df483b2bdb1b45f79250e2d0752a01523bcd34a8 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -318,7 +318,7 @@ message Primitive { float dimension_value = 4; float fraction_value = 5; int32 int_decimal_value = 6; - uint32 int_hexidecimal_value = 7; + uint32 int_hexadecimal_value = 7; bool boolean_value = 8; uint32 color_argb8_value = 9; uint32 color_rgb8_value = 10; diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 81bc2c88939e97e447269fcc408bc7c6bfee4f77..f1eb95289053e3cdf04f7c6d1c4b781c29691432 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -792,9 +792,9 @@ std::unique_ptr DeserializeItemFromPb(const pb::Item& pb_item, val.dataType = android::Res_value::TYPE_INT_DEC; val.data = static_cast(pb_prim.int_decimal_value()); } break; - case pb::Primitive::kIntHexidecimalValue: { + case pb::Primitive::kIntHexadecimalValue: { val.dataType = android::Res_value::TYPE_INT_HEX; - val.data = pb_prim.int_hexidecimal_value(); + val.data = pb_prim.int_hexadecimal_value(); } break; case pb::Primitive::kBooleanValue: { val.dataType = android::Res_value::TYPE_INT_BOOLEAN; diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index e9622f54f6ae83f1b927fc9156e837890f6ed053..1d00852eab731323739010478dae4eda5bb5fbc9 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -460,7 +460,7 @@ class ValueSerializer : public ConstValueVisitor { pb_prim->set_int_decimal_value(static_cast(val.data)); } break; case android::Res_value::TYPE_INT_HEX: { - pb_prim->set_int_hexidecimal_value(val.data); + pb_prim->set_int_hexadecimal_value(val.data); } break; case android::Res_value::TYPE_INT_BOOLEAN: { pb_prim->set_boolean_value(static_cast(val.data)); diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index dc5ba0cc83b5fd72fa01c8af2a736306af5f10d7..fe63aa1bf79bf62c61306de8fe35eede7396d880 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -7,22 +7,21 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; +import android.content.pm.PackageManager; +import android.net.wifi.rtt.RangingRequest; +import android.net.wifi.rtt.RangingResult; +import android.net.wifi.rtt.RangingResultCallback; +import android.net.wifi.rtt.WifiRttManager; import android.os.Looper; -import android.os.Message; -import android.os.Messenger; import android.os.Parcel; import android.os.Parcelable; -import android.os.RemoteException; import android.util.Log; -import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import java.util.List; + /** @hide */ @SystemApi @SystemService(Context.WIFI_RTT_SERVICE) @@ -175,7 +174,8 @@ public class RttManager { @Deprecated @SuppressLint("Doclava125") public Capabilities getCapabilities() { - return new Capabilities(); + throw new UnsupportedOperationException( + "getCapabilities is not supported in the adaptation layer"); } /** @@ -316,16 +316,7 @@ public class RttManager { @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) public RttCapabilities getRttCapabilities() { - synchronized (mCapabilitiesLock) { - if (mRttCapabilities == null) { - try { - mRttCapabilities = mService.getRttCapabilities(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - return mRttCapabilities; - } + return mRttCapabilities; } /** specifies parameters for RTT request */ @@ -972,69 +963,6 @@ public class RttManager { } } - private boolean rttParamSanity(RttParams params, int index) { - if (mRttCapabilities == null) { - if(getRttCapabilities() == null) { - Log.e(TAG, "Can not get RTT capabilities"); - throw new IllegalStateException("RTT chip is not working"); - } - } - - if (params.deviceType != RTT_PEER_TYPE_AP) { - return false; - } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType != - RTT_TYPE_TWO_SIDED) { - Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType); - return false; - } else if (params.requestType == RTT_TYPE_ONE_SIDED && - !mRttCapabilities.oneSidedRttSupported) { - Log.e(TAG, "Request " + index + ": One side RTT is not supported"); - return false; - } else if (params.requestType == RTT_TYPE_TWO_SIDED && - !mRttCapabilities.twoSided11McRttSupported) { - Log.e(TAG, "Request " + index + ": two side RTT is not supported"); - return false; - } else if(params.bssid == null || params.bssid.isEmpty()) { - Log.e(TAG,"No BSSID in params"); - return false; - } else if ( params.numberBurst != 0 ) { - Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst); - return false; - } else if (params.numSamplesPerBurst <= 0 || params.numSamplesPerBurst > 31) { - Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " + - params.numSamplesPerBurst); - return false; - } else if (params.numRetriesPerMeasurementFrame < 0 || - params.numRetriesPerMeasurementFrame > 3) { - Log.e(TAG, "Request " + index + ": Illegal measurement frame retry number:" + - params.numRetriesPerMeasurementFrame); - return false; - } else if(params.numRetriesPerFTMR < 0 || - params.numRetriesPerFTMR > 3) { - Log.e(TAG, "Request " + index + ": Illegal FTMR frame retry number:" + - params.numRetriesPerFTMR); - return false; - } else if (params.LCIRequest && !mRttCapabilities.lciSupported) { - Log.e(TAG, "Request " + index + ": LCI is not supported"); - return false; - } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) { - Log.e(TAG, "Request " + index + ": LCR is not supported"); - return false; - } else if (params.burstTimeout < 1 || - (params.burstTimeout > 11 && params.burstTimeout != 15)){ - Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout); - return false; - } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) { - Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble); - return false; - } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) { - Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth); - return false; - } - - return true; - } - /** * Request to start an RTT ranging * @@ -1045,24 +973,72 @@ public class RttManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startRanging(RttParams[] params, RttListener listener) { - int index = 0; - for(RttParams rttParam : params) { - if (!rttParamSanity(rttParam, index)) { - throw new IllegalArgumentException("RTT Request Parameter Illegal"); + Log.i(TAG, "Send RTT request to RTT Service"); + + if (!mNewService.isAvailable()) { + listener.onFailure(REASON_NOT_AVAILABLE, ""); + return; + } + + RangingRequest.Builder builder = new RangingRequest.Builder(); + for (RttParams rttParams : params) { + if (rttParams.deviceType != RTT_PEER_TYPE_AP) { + listener.onFailure(REASON_INVALID_REQUEST, "Only AP peers are supported"); + return; + } + + ScanResult reconstructed = new ScanResult(); + reconstructed.BSSID = rttParams.bssid; + if (rttParams.requestType == RTT_TYPE_TWO_SIDED) { + reconstructed.setFlag(ScanResult.FLAG_80211mc_RESPONDER); } - index++; + reconstructed.channelWidth = rttParams.channelWidth; + reconstructed.frequency = rttParams.frequency; + reconstructed.centerFreq0 = rttParams.centerFreq0; + reconstructed.centerFreq1 = rttParams.centerFreq1; + builder.addResponder( + android.net.wifi.rtt.ResponderConfig.fromScanResult(reconstructed)); + } + try { + mNewService.startRanging(builder.build(), new RangingResultCallback() { + @Override + public void onRangingFailure(int code) { + int localCode = REASON_UNSPECIFIED; + if (code == STATUS_CODE_FAIL_RTT_NOT_AVAILABLE) { + localCode = REASON_NOT_AVAILABLE; + } + listener.onFailure(localCode, ""); + } + + @Override + public void onRangingResults(List results) { + RttResult[] legacyResults = new RttResult[results.size()]; + int i = 0; + for (RangingResult result : results) { + legacyResults[i] = new RttResult(); + legacyResults[i].status = result.getStatus(); + legacyResults[i].bssid = result.getMacAddress().toString(); + legacyResults[i].distance = result.getDistanceMm() / 10; + legacyResults[i].distanceStandardDeviation = + result.getDistanceStdDevMm() / 10; + legacyResults[i].rssi = result.getRssi(); + legacyResults[i].ts = result.getRangingTimestampUs(); + } + listener.onSuccess(legacyResults); + } + }, null); + } catch (IllegalArgumentException e) { + Log.e(TAG, "startRanging: invalid arguments - " + e); + listener.onFailure(REASON_INVALID_REQUEST, e.getMessage()); + } catch (SecurityException e) { + Log.e(TAG, "startRanging: security exception - " + e); + listener.onFailure(REASON_PERMISSION_DENIED, e.getMessage()); } - validateChannel(); - ParcelableRttParams parcelableParams = new ParcelableRttParams(params); - Log.i(TAG, "Send RTT request to RTT Service"); - mAsyncChannel.sendMessage(CMD_OP_START_RANGING, - 0, putListener(listener), parcelableParams); } @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void stopRanging(RttListener listener) { - validateChannel(); - mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener)); + Log.e(TAG, "stopRanging: unsupported operation - nop"); } /** @@ -1095,12 +1071,8 @@ public class RttManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void enableResponder(ResponderCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - validateChannel(); - int key = putListenerIfAbsent(callback); - mAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key); + throw new UnsupportedOperationException( + "enableResponder is not supported in the adaptation layer"); } /** @@ -1115,16 +1087,8 @@ public class RttManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void disableResponder(ResponderCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - validateChannel(); - int key = removeListener(callback); - if (key == INVALID_KEY) { - Log.e(TAG, "responder not enabled yet"); - return; - } - mAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key); + throw new UnsupportedOperationException( + "disableResponder is not supported in the adaptation layer"); } /** @@ -1238,17 +1202,9 @@ public class RttManager { /** @hide */ public static final int CMD_OP_REG_BINDER = BASE + 9; - private static final int INVALID_KEY = 0; - private final Context mContext; - private final IRttManager mService; - private final SparseArray mListenerMap = new SparseArray(); - private final Object mListenerMapLock = new Object(); - private final Object mCapabilitiesLock = new Object(); - + private final WifiRttManager mNewService; private RttCapabilities mRttCapabilities; - private int mListenerKey = 1; - private AsyncChannel mAsyncChannel; /** * Create a new WifiScanner instance. @@ -1263,170 +1219,20 @@ public class RttManager { */ public RttManager(Context context, IRttManager service, Looper looper) { mContext = context; - mService = service; - Messenger messenger = null; - int[] key = new int[1]; - try { - Log.d(TAG, "Get the messenger from " + mService); - messenger = mService.getMessenger(new Binder(), key); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - - if (messenger == null) { - throw new IllegalStateException("getMessenger() returned null! This is invalid."); - } - - mAsyncChannel = new AsyncChannel(); - - Handler handler = new ServiceHandler(looper); - mAsyncChannel.connectSync(mContext, handler, messenger); - // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message - // synchronously, which causes RttService to receive the wrong replyTo value. - mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION, - new RttClient(context.getPackageName())); - mAsyncChannel.sendMessage(CMD_OP_REG_BINDER, key[0]); + mNewService = (WifiRttManager) mContext.getSystemService(Context.WIFI_RTT_RANGING_SERVICE); + + boolean rttSupported = mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WIFI_RTT); + + mRttCapabilities = new RttCapabilities(); + mRttCapabilities.oneSidedRttSupported = rttSupported; + mRttCapabilities.twoSided11McRttSupported = rttSupported; + mRttCapabilities.lciSupported = false; + mRttCapabilities.lcrSupported = false; + mRttCapabilities.preambleSupported = PREAMBLE_HT | PREAMBLE_VHT; + mRttCapabilities.bwSupported = RTT_BW_40_SUPPORT | RTT_BW_80_SUPPORT; + mRttCapabilities.responderSupported = false; + mRttCapabilities.secureRttSupported = false; } - - private void validateChannel() { - if (mAsyncChannel == null) throw new IllegalStateException( - "No permission to access and change wifi or a bad initialization"); - } - - private int putListener(Object listener) { - if (listener == null) return INVALID_KEY; - int key; - synchronized (mListenerMapLock) { - do { - key = mListenerKey++; - } while (key == INVALID_KEY); - mListenerMap.put(key, listener); - } - return key; - } - - // Insert a listener if it doesn't exist in mListenerMap. Returns the key of the listener. - private int putListenerIfAbsent(Object listener) { - if (listener == null) return INVALID_KEY; - synchronized (mListenerMapLock) { - int key = getListenerKey(listener); - if (key != INVALID_KEY) { - return key; - } - do { - key = mListenerKey++; - } while (key == INVALID_KEY); - mListenerMap.put(key, listener); - return key; - } - - } - - private Object getListener(int key) { - if (key == INVALID_KEY) return null; - synchronized (mListenerMapLock) { - Object listener = mListenerMap.get(key); - return listener; - } - } - - private int getListenerKey(Object listener) { - if (listener == null) return INVALID_KEY; - synchronized (mListenerMapLock) { - int index = mListenerMap.indexOfValue(listener); - if (index == -1) { - return INVALID_KEY; - } else { - return mListenerMap.keyAt(index); - } - } - } - - private Object removeListener(int key) { - if (key == INVALID_KEY) return null; - synchronized (mListenerMapLock) { - Object listener = mListenerMap.get(key); - mListenerMap.remove(key); - return listener; - } - } - - private int removeListener(Object listener) { - int key = getListenerKey(listener); - if (key == INVALID_KEY) return key; - synchronized (mListenerMapLock) { - mListenerMap.remove(key); - return key; - } - } - - private class ServiceHandler extends Handler { - ServiceHandler(Looper looper) { - super(looper); - } - @Override - public void handleMessage(Message msg) { - Log.i(TAG, "RTT manager get message: " + msg.what); - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: - return; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - Log.e(TAG, "Channel connection lost"); - // This will cause all further async API calls on the WifiManager - // to fail and throw an exception - mAsyncChannel = null; - getLooper().quit(); - return; - } - - Object listener = getListener(msg.arg2); - if (listener == null) { - Log.e(TAG, "invalid listener key = " + msg.arg2 ); - return; - } else { - Log.i(TAG, "listener key = " + msg.arg2); - } - - switch (msg.what) { - /* ActionListeners grouped together */ - case CMD_OP_SUCCEEDED : - reportSuccess(listener, msg); - removeListener(msg.arg2); - break; - case CMD_OP_FAILED : - reportFailure(listener, msg); - removeListener(msg.arg2); - break; - case CMD_OP_ABORTED : - ((RttListener) listener).onAborted(); - removeListener(msg.arg2); - break; - case CMD_OP_ENALBE_RESPONDER_SUCCEEDED: - ResponderConfig config = (ResponderConfig) msg.obj; - ((ResponderCallback) (listener)).onResponderEnabled(config); - break; - case CMD_OP_ENALBE_RESPONDER_FAILED: - ((ResponderCallback) (listener)).onResponderEnableFailure(msg.arg1); - removeListener(msg.arg2); - break; - default: - if (DBG) Log.d(TAG, "Ignoring message " + msg.what); - return; - } - } - - void reportSuccess(Object listener, Message msg) { - RttListener rttListener = (RttListener) listener; - ParcelableRttResults parcelableResults = (ParcelableRttResults) msg.obj; - ((RttListener) listener).onSuccess(parcelableResults.mResults); - } - - void reportFailure(Object listener, Message msg) { - RttListener rttListener = (RttListener) listener; - Bundle bundle = (Bundle) msg.obj; - ((RttListener) listener).onFailure(msg.arg1, bundle.getString(DESCRIPTION_KEY)); - } - } - } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 8d1a00b09d9455dab600c81a01a13d3ed9c4abdc..7da2656761c1ebbef0bc19cb246c294f7523ca19 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -16,6 +16,7 @@ package android.net.wifi; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.pm.PackageManager; import android.net.IpConfiguration; @@ -439,6 +440,7 @@ public class WifiConfiguration implements Parcelable { /** * @hide */ + @NonNull private IpConfiguration mIpConfiguration; /** @@ -2023,6 +2025,7 @@ public class WifiConfiguration implements Parcelable { /** @hide */ public void setIpConfiguration(IpConfiguration ipConfiguration) { + if (ipConfiguration == null) ipConfiguration = new IpConfiguration(); mIpConfiguration = ipConfiguration; } @@ -2306,7 +2309,7 @@ public class WifiConfiguration implements Parcelable { config.allowedGroupCiphers = readBitSet(in); config.enterpriseConfig = in.readParcelable(null); - config.mIpConfiguration = in.readParcelable(null); + config.setIpConfiguration(in.readParcelable(null)); config.dhcpServer = in.readString(); config.defaultGwMacAddress = in.readString(); config.selfAdded = in.readInt() != 0; diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 897b1eaa2a6439ceb14e9987b01be02db5af0983..3396857acbe8324683511992e9b2f547d2919388 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -822,6 +822,25 @@ public class WifiManager { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; + /** + * Broadcast intent action indicating that WifiCountryCode was updated with new + * country code. + * + * @see #EXTRA_COUNTRY_CODE + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String WIFI_COUNTRY_CODE_CHANGED_ACTION = + "android.net.wifi.COUNTRY_CODE_CHANGED"; + + /** + * The lookup key for a string that indicates the 2 char new country code + * + * @hide + */ + public static final String EXTRA_COUNTRY_CODE = "country_code"; + /** * Internally used Wi-Fi lock mode representing the case were no locks are held. * @hide diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java index 9f7362234ad833623792ef3dff353e0d2f1de75c..699f54cf13fb38d66d3d34b1e78989b60ef409e1 100644 --- a/wifi/java/android/net/wifi/aware/DiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java @@ -22,6 +22,8 @@ import android.annotation.SystemApi; import android.net.NetworkSpecifier; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import dalvik.system.CloseGuard; import java.lang.ref.WeakReference; @@ -141,6 +143,34 @@ public class DiscoverySession implements AutoCloseable { } } + /** + * Access the client ID of the Aware session. + * + * Note: internal visibility for testing. + * + * @return The internal client ID. + * + * @hide + */ + @VisibleForTesting + public int getClientId() { + return mClientId; + } + + /** + * Access the discovery session ID of the Aware session. + * + * Note: internal visibility for testing. + * + * @return The internal discovery session ID. + * + * @hide + */ + @VisibleForTesting + public int getSessionId() { + return mSessionId; + } + /** * Sends a message to the specified destination. Aware messages are transmitted in the context * of a discovery session - executed subsequent to a publish/subscribe @@ -246,8 +276,7 @@ public class DiscoverySession implements AutoCloseable { * or * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}. * On a RESPONDER this value is used to gate the acceptance of a connection - * request from only that peer. A RESPONDER may specify a {@code null} - - * indicating that it will accept connection requests from any device. + * request from only that peer. * * @return A {@link NetworkSpecifier} to be used to construct * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to @@ -255,7 +284,7 @@ public class DiscoverySession implements AutoCloseable { * android.net.ConnectivityManager.NetworkCallback)} * [or other varieties of that API]. */ - public NetworkSpecifier createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) { + public NetworkSpecifier createNetworkSpecifierOpen(@NonNull PeerHandle peerHandle) { if (mTerminated) { Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session"); return null; @@ -295,8 +324,7 @@ public class DiscoverySession implements AutoCloseable { * byte[], java.util.List)} or * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request - * from only that peer. A RESPONDER may specify a {@code null} - indicating - * that it will accept connection requests from any device. + * from only that peer. * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from * the passphrase. Use the * {@link #createNetworkSpecifierOpen(PeerHandle)} API to @@ -309,7 +337,7 @@ public class DiscoverySession implements AutoCloseable { * [or other varieties of that API]. */ public NetworkSpecifier createNetworkSpecifierPassphrase( - @Nullable PeerHandle peerHandle, @NonNull String passphrase) { + @NonNull PeerHandle peerHandle, @NonNull String passphrase) { if (!WifiAwareUtils.validatePassphrase(passphrase)) { throw new IllegalArgumentException("Passphrase must meet length requirements"); } @@ -354,8 +382,7 @@ public class DiscoverySession implements AutoCloseable { * byte[], java.util.List)} or * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request - * from only that peer. A RESPONDER may specify a null - indicating that - * it will accept connection requests from any device. + * from only that peer. * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for * encrypting the data-path. Use the * {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a @@ -371,7 +398,7 @@ public class DiscoverySession implements AutoCloseable { * @hide */ @SystemApi - public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle, + public NetworkSpecifier createNetworkSpecifierPmk(@NonNull PeerHandle peerHandle, @NonNull byte[] pmk) { if (!WifiAwareUtils.validatePmk(pmk)) { throw new IllegalArgumentException("PMK must 32 bytes"); diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index 2f0c3163aa0cab944b2bf20f51e245b2ae6dcf95..06a5c2e2710b54fe2d3f38fd2c1b0633894f6e14 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -406,7 +406,7 @@ public class WifiAwareManager { /** @hide */ public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId, - PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) { + @NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) { if (VDBG) { Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId) @@ -420,12 +420,9 @@ public class WifiAwareManager { "createNetworkSpecifier: Invalid 'role' argument when creating a network " + "specifier"); } - if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { - if (peerHandle == null) { - throw new IllegalArgumentException( - "createNetworkSpecifier: Invalid peer handle (value of null) - not " - + "permitted on INITIATOR"); - } + if (peerHandle == null) { + throw new IllegalArgumentException( + "createNetworkSpecifier: Invalid peer handle - cannot be null"); } return new WifiAwareNetworkSpecifier( @@ -443,7 +440,7 @@ public class WifiAwareManager { /** @hide */ public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role, - @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) { + @NonNull byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) { if (VDBG) { Log.v(TAG, "createNetworkSpecifier: role=" + role + ", pmk=" + ((pmk == null) ? "null" : "non-null") @@ -456,11 +453,9 @@ public class WifiAwareManager { "createNetworkSpecifier: Invalid 'role' argument when creating a network " + "specifier"); } - if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { - if (peer == null) { - throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC " - + "address - null not permitted on INITIATOR"); - } + if (peer == null) { + throw new IllegalArgumentException( + "createNetworkSpecifier: Invalid peer MAC - cannot be null"); } if (peer != null && peer.length != 6) { throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address"); diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java index f26b9f5aacfca0088de9351bed7db707a3e3c346..321965330e0b2e53c76067f17277b60ccbf2b960 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java @@ -25,6 +25,8 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import dalvik.system.CloseGuard; import java.lang.ref.WeakReference; @@ -96,6 +98,20 @@ public class WifiAwareSession implements AutoCloseable { } } + /** + * Access the client ID of the Aware session. + * + * Note: internal visibility for testing. + * + * @return The internal client ID. + * + * @hide + */ + @VisibleForTesting + public int getClientId() { + return mClientId; + } + /** * Issue a request to the Aware service to create a new Aware publish discovery session, using * the specified {@code publishConfig} configuration. The results of the publish operation @@ -207,8 +223,7 @@ public class WifiAwareSession implements AutoCloseable { * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER} * @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this * value is used to gate the acceptance of a connection request from only that - * peer. A RESPONDER may specify a {@code null} - indicating that it will accept - * connection requests from any device. + * peer. * * @return A {@link NetworkSpecifier} to be used to construct * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to @@ -217,7 +232,7 @@ public class WifiAwareSession implements AutoCloseable { * [or other varieties of that API]. */ public NetworkSpecifier createNetworkSpecifierOpen( - @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer) { + @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager"); @@ -246,8 +261,7 @@ public class WifiAwareSession implements AutoCloseable { * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER} * @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this * value is used to gate the acceptance of a connection request from only that - * peer. A RESPONDER may specify a {@code null} - indicating that it will accept - * connection requests from any device. + * peer. * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from * the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to * specify an open (unencrypted) link. @@ -259,7 +273,7 @@ public class WifiAwareSession implements AutoCloseable { * [or other varieties of that API]. */ public NetworkSpecifier createNetworkSpecifierPassphrase( - @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, + @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer, @NonNull String passphrase) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { @@ -293,8 +307,7 @@ public class WifiAwareSession implements AutoCloseable { * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER} * @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this * value is used to gate the acceptance of a connection request from only that - * peer. A RESPONDER may specify a null - indicating that it will accept - * connection requests from any device. + * peer. * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for * encrypting the data-path. Use the * {@link #createNetworkSpecifierPassphrase(int, byte[], String)} to specify a @@ -311,7 +324,7 @@ public class WifiAwareSession implements AutoCloseable { */ @SystemApi public NetworkSpecifier createNetworkSpecifierPmk( - @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, @NonNull byte[] pmk) { + @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer, @NonNull byte[] pmk) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager"); diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index b0a048d777301d5b08634bf0e5f35202284a0be7..84e3ed9d2c44e461ad61c2b186997235b87232de 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -1022,7 +1022,7 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierWithClientNullPmk() throws Exception { - executeNetworkSpecifierWithClient(true, null, null); + executeNetworkSpecifierWithClient(new PeerHandle(123412), true, null, null); } /** @@ -1030,7 +1030,7 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierWithClientIncorrectLengthPmk() throws Exception { - executeNetworkSpecifierWithClient(true, "012".getBytes(), null); + executeNetworkSpecifierWithClient(new PeerHandle(123412), true, "012".getBytes(), null); } /** @@ -1038,7 +1038,7 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierWithClientNullPassphrase() throws Exception { - executeNetworkSpecifierWithClient(false, null, null); + executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, null); } /** @@ -1046,7 +1046,7 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierWithClientShortPassphrase() throws Exception { - executeNetworkSpecifierWithClient(false, null, "012"); + executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, "012"); } /** @@ -1054,15 +1054,23 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierWithClientLongPassphrase() throws Exception { - executeNetworkSpecifierWithClient(false, null, + executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, "0123456789012345678901234567890123456789012345678901234567890123456789"); } - private void executeNetworkSpecifierWithClient(boolean doPmk, byte[] pmk, String passphrase) - throws Exception { + /** + * Validate that a null PeerHandle triggers an exception. + */ + @Test(expected = IllegalArgumentException.class) + public void testNetworkSpecifierWithClientNullPeer() throws Exception { + executeNetworkSpecifierWithClient(null, false, null, + "0123456789012345678901234567890123456789012345678901234567890123456789"); + } + + private void executeNetworkSpecifierWithClient(PeerHandle peerHandle, boolean doPmk, byte[] pmk, + String passphrase) throws Exception { final int clientId = 4565; final int sessionId = 123; - final PeerHandle peerHandle = new PeerHandle(123412); final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final PublishConfig publishConfig = new PublishConfig.Builder().build(); @@ -1108,7 +1116,8 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierDirectNullPmk() throws Exception { - executeNetworkSpecifierDirect(true, null, null); + executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), true, + null, null); } /** @@ -1116,7 +1125,8 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierDirectIncorrectLengthPmk() throws Exception { - executeNetworkSpecifierDirect(true, "012".getBytes(), null); + executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), true, + "012".getBytes(), null); } /** @@ -1124,7 +1134,8 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierDirectNullPassphrase() throws Exception { - executeNetworkSpecifierDirect(false, null, null); + executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), + false, null, null); } /** @@ -1132,7 +1143,8 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierDirectShortPassphrase() throws Exception { - executeNetworkSpecifierDirect(false, null, "012"); + executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), + false, null, "012"); } /** @@ -1140,14 +1152,22 @@ public class WifiAwareManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testNetworkSpecifierDirectLongPassphrase() throws Exception { - executeNetworkSpecifierDirect(false, null, + executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), + false, null, "0123456789012345678901234567890123456789012345678901234567890123456789"); } - private void executeNetworkSpecifierDirect(boolean doPmk, byte[] pmk, String passphrase) - throws Exception { + /** + * Validate that a null peer MAC triggers an exception. + */ + @Test(expected = IllegalArgumentException.class) + public void testNetworkSpecifierDirectNullPeer() throws Exception { + executeNetworkSpecifierDirect(null, false, null, null); + } + + private void executeNetworkSpecifierDirect(byte[] someMac, boolean doPmk, byte[] pmk, + String passphrase) throws Exception { final int clientId = 134; - final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java index 1e8382f9b045952535d32ed75eb0137055b588e2..e8e4dc2080c21ec108459a66d08a1b824f0f3529 100644 --- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java +++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java @@ -59,10 +59,10 @@ public class WifiP2pManagerTest { */ @Test public void testChannelFinalize() throws Exception { - WifiP2pManager.Channel channel = new WifiP2pManager.Channel(mContextMock, - mTestLooper.getLooper(), null, null, mDut); - - leakageDetectorRule.assertUnreleasedResourceCount(channel, 1); + try (WifiP2pManager.Channel channel = new WifiP2pManager.Channel(mContextMock, + mTestLooper.getLooper(), null, null, mDut)) { + leakageDetectorRule.assertUnreleasedResourceCount(channel, 1); + } } /**