diff options
277 files changed, 6706 insertions, 4528 deletions
diff --git a/Android.mk b/Android.mk index a1e9ed9abca0..2c85d4d96603 100644 --- a/Android.mk +++ b/Android.mk @@ -388,6 +388,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \ keystore/java/android/security/IKeyChainAliasCallback.aidl \ keystore/java/android/security/IKeyChainService.aidl \ + location/java/android/location/IBatchedLocationCallback.aidl \ location/java/android/location/ICountryDetector.aidl \ location/java/android/location/ICountryListener.aidl \ location/java/android/location/IFusedProvider.aidl \ diff --git a/api/current.txt b/api/current.txt index d5ea0df9865b..5c1bff80b655 100644 --- a/api/current.txt +++ b/api/current.txt @@ -118,6 +118,7 @@ package android { field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; + field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS"; field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM"; @@ -5679,10 +5680,11 @@ package android.app { } public final class RemoteAction implements android.os.Parcelable { - ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener); + ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); method public android.app.RemoteAction clone(); method public int describeContents(); method public void dump(java.lang.String, java.io.PrintWriter); + method public android.app.PendingIntent getActionIntent(); method public java.lang.CharSequence getContentDescription(); method public android.graphics.drawable.Icon getIcon(); method public java.lang.CharSequence getTitle(); @@ -5690,10 +5692,6 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR; } - public static abstract interface RemoteAction.OnActionListener { - method public abstract void onAction(android.app.RemoteAction); - } - public final class RemoteInput implements android.os.Parcelable { method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>); method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle); @@ -6219,6 +6217,7 @@ package android.app.admin { method public java.lang.CharSequence getDeviceOwnerLockScreenInfo(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); + method public java.lang.String[] getLockTaskPackages(android.content.ComponentName); method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); @@ -23955,6 +23954,31 @@ package android.media.tv { field public static final java.lang.String AUTHORITY = "android.media.tv"; } + public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns { + field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; + field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; + field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; + field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; + field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; + field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; + field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; + field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; + field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; + field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; + field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; + field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; + field public static final java.lang.String COLUMN_TITLE = "title"; + field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; + field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; + } + public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns { field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name"; } @@ -24037,7 +24061,7 @@ package android.media.tv { field public static final java.lang.String CONTENT_DIRECTORY = "logo"; } - public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns { + public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns { field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9"; field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1"; field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3"; @@ -24046,53 +24070,31 @@ package android.media.tv { field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION"; field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT"; field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri"; - field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; field public static final java.lang.String COLUMN_AUTHOR = "author"; field public static final java.lang.String COLUMN_AVAILABILITY = "availability"; field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; - field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; - field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; - field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis"; field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; - field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number"; - field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count"; field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id"; field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count"; field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis"; field public static final java.lang.String COLUMN_LIVE = "live"; field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri"; - field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price"; field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio"; - field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri"; field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited"; field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date"; field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating"; field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style"; - field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; - field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number"; - field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; - field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price"; field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio"; - field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - field public static final java.lang.String COLUMN_TITLE = "title"; field public static final java.lang.String COLUMN_TYPE = "type"; - field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; - field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; - field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type"; field public static final java.lang.String COLUMN_WEIGHT = "weight"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; @@ -24148,37 +24150,15 @@ package android.media.tv { field public static final java.lang.String TRAVEL = "TRAVEL"; } - public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns { - field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns { field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; - field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; - field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; - field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; - field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; - field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; field public static final java.lang.String COLUMN_INPUT_ID = "input_id"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; - field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; - field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes"; field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri"; field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis"; field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis"; - field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; - field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; - field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; - field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; - field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - field public static final java.lang.String COLUMN_TITLE = "title"; - field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; - field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; - field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program"; field public static final android.net.Uri CONTENT_URI; @@ -29860,6 +29840,7 @@ package android.os { field public static final int BATTERY_PLUGGED_AC = 1; // 0x1 field public static final int BATTERY_PLUGGED_USB = 2; // 0x2 field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4 + field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6 field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4 field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1 field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3 @@ -44369,6 +44350,7 @@ package android.view { ctor public View(android.content.Context, android.util.AttributeSet, int); ctor public View(android.content.Context, android.util.AttributeSet, int, int); method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>); + method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public void addFocusables(java.util.ArrayList<android.view.View>, int); method public void addFocusables(java.util.ArrayList<android.view.View>, int, int); method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int); @@ -44468,7 +44450,8 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public android.view.autofill.AutoFillType getAutoFillType(); - method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(android.view.autofill.VirtualViewDelegate.Callback); + method public android.view.autofill.AutoFillValue getAutoFillValue(); + method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(); method public android.graphics.drawable.Drawable getBackground(); method public android.content.res.ColorStateList getBackgroundTintList(); method public android.graphics.PorterDuff.Mode getBackgroundTintMode(); @@ -45063,6 +45046,7 @@ package android.view { public static class View.AccessibilityDelegate { ctor public View.AccessibilityDelegate(); + method public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View); method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); @@ -46183,6 +46167,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList(); method public deprecated int getActions(); + method public java.util.List<java.lang.String> getAvailableExtraData(); method public void getBoundsInParent(android.graphics.Rect); method public void getBoundsInScreen(android.graphics.Rect); method public android.view.accessibility.AccessibilityNodeInfo getChild(int); @@ -46239,11 +46224,13 @@ package android.view.accessibility { method public boolean performAction(int, android.os.Bundle); method public void recycle(); method public boolean refresh(); + method public boolean refreshWithExtraData(java.lang.String, android.os.Bundle); method public deprecated void removeAction(int); method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction); method public boolean removeChild(android.view.View); method public boolean removeChild(android.view.View, int); method public void setAccessibilityFocused(boolean); + method public void setAvailableExtraData(java.util.List<java.lang.String>); method public void setBoundsInParent(android.graphics.Rect); method public void setBoundsInScreen(android.graphics.Rect); method public void setCanOpenPopup(boolean); @@ -46326,6 +46313,9 @@ package android.view.accessibility { field public static final int ACTION_SET_SELECTION = 131072; // 0x20000 field public static final int ACTION_SET_TEXT = 2097152; // 0x200000 field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH"; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX"; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2 field public static final int FOCUS_INPUT = 1; // 0x1 field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1 @@ -46407,6 +46397,7 @@ package android.view.accessibility { public abstract class AccessibilityNodeProvider { ctor public AccessibilityNodeProvider(); + method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); @@ -46817,11 +46808,11 @@ package android.view.autofill { } public final class AutoFillManager { - method public void onValueChanged(android.view.View, android.view.autofill.AutoFillValue); - method public void updateAutoFillInput(android.view.View, int); - method public void updateAutoFillInput(android.view.View, int, android.graphics.Rect, int); - field public static final int FLAG_UPDATE_UI_HIDE = 2; // 0x2 - field public static final int FLAG_UPDATE_UI_SHOW = 1; // 0x1 + method public void focusChanged(android.view.View, boolean); + method public void reset(); + method public void valueChanged(android.view.View); + method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean); + method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue); } public final class AutoFillType implements android.os.Parcelable { @@ -46883,13 +46874,6 @@ package android.view.autofill { method public abstract void autoFill(int, android.view.autofill.AutoFillValue); } - public static abstract class VirtualViewDelegate.Callback { - ctor public VirtualViewDelegate.Callback(); - method public void onAutoFillInputUpdated(int, android.graphics.Rect, int); - method public void onNodeRemoved(int...); - method public void onValueChanged(int); - } - } package android.view.inputmethod { @@ -47300,7 +47284,7 @@ package android.view.textclassifier { public final class TextClassificationManager { method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); - method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier(); + method public android.view.textclassifier.TextClassifier getDefaultTextClassifier(); } public final class TextClassificationResult { diff --git a/api/system-current.txt b/api/system-current.txt index 4c3337b05f5e..a29c7f8a71e4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -206,6 +206,7 @@ package android { field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; + field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS"; field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS"; @@ -5875,10 +5876,11 @@ package android.app { } public final class RemoteAction implements android.os.Parcelable { - ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener); + ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); method public android.app.RemoteAction clone(); method public int describeContents(); method public void dump(java.lang.String, java.io.PrintWriter); + method public android.app.PendingIntent getActionIntent(); method public java.lang.CharSequence getContentDescription(); method public android.graphics.drawable.Icon getIcon(); method public java.lang.CharSequence getTitle(); @@ -5886,10 +5888,6 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR; } - public static abstract interface RemoteAction.OnActionListener { - method public abstract void onAction(android.app.RemoteAction); - } - public final class RemoteInput implements android.os.Parcelable { method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>); method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle); @@ -6430,6 +6428,7 @@ package android.app.admin { method public java.lang.CharSequence getDeviceOwnerOrganizationName(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); + method public java.lang.String[] getLockTaskPackages(android.content.ComponentName); method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); @@ -21416,6 +21415,11 @@ package android.location { field public static final android.os.Parcelable.Creator<android.location.Address> CREATOR; } + public abstract class BatchedLocationCallback { + ctor public BatchedLocationCallback(); + method public void onLocationBatch(java.util.List<android.location.Location>); + } + public class Criteria implements android.os.Parcelable { ctor public Criteria(); ctor public Criteria(android.location.Criteria); @@ -21954,14 +21958,17 @@ package android.location { method public void clearTestProviderEnabled(java.lang.String); method public void clearTestProviderLocation(java.lang.String); method public void clearTestProviderStatus(java.lang.String); + method public void flushGnssBatch(); method public java.util.List<java.lang.String> getAllProviders(); method public java.lang.String getBestProvider(android.location.Criteria, boolean); + method public int getGnssBatchSize(); method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus); method public android.location.Location getLastKnownLocation(java.lang.String); method public android.location.LocationProvider getProvider(java.lang.String); method public java.util.List<java.lang.String> getProviders(boolean); method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean); method public boolean isProviderEnabled(java.lang.String); + method public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler); method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback); method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler); method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback); @@ -21992,6 +21999,7 @@ package android.location { method public void setTestProviderEnabled(java.lang.String, boolean); method public void setTestProviderLocation(java.lang.String, android.location.Location); method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long); + method public boolean unregisterGnssBatchedLocationCallback(android.location.BatchedLocationCallback); method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback); method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback); method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback); @@ -25708,6 +25716,31 @@ package android.media.tv { field public static final java.lang.String AUTHORITY = "android.media.tv"; } + public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns { + field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; + field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; + field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; + field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; + field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; + field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; + field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; + field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; + field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; + field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; + field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; + field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; + field public static final java.lang.String COLUMN_TITLE = "title"; + field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; + field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; + } + public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns { field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name"; } @@ -25794,7 +25827,7 @@ package android.media.tv { field public static final java.lang.String CONTENT_DIRECTORY = "logo"; } - public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns { + public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns { field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9"; field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1"; field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3"; @@ -25803,54 +25836,32 @@ package android.media.tv { field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION"; field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT"; field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri"; - field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; field public static final java.lang.String COLUMN_AUTHOR = "author"; field public static final java.lang.String COLUMN_AVAILABILITY = "availability"; field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; - field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; - field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; - field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis"; field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; - field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number"; - field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count"; field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id"; field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count"; field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis"; field public static final java.lang.String COLUMN_LIVE = "live"; field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri"; - field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price"; field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio"; - field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri"; field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited"; field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date"; field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating"; field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style"; - field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; - field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number"; - field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; - field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price"; field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio"; - field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - field public static final java.lang.String COLUMN_TITLE = "title"; field public static final java.lang.String COLUMN_TRANSIENT = "transient"; field public static final java.lang.String COLUMN_TYPE = "type"; - field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; - field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; - field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type"; field public static final java.lang.String COLUMN_WEIGHT = "weight"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; @@ -25906,37 +25917,15 @@ package android.media.tv { field public static final java.lang.String TRAVEL = "TRAVEL"; } - public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns { - field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns { field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; - field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; - field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; - field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; - field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; - field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; field public static final java.lang.String COLUMN_INPUT_ID = "input_id"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; - field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; - field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes"; field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri"; field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis"; field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis"; - field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; - field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; - field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; - field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; - field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - field public static final java.lang.String COLUMN_TITLE = "title"; - field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; - field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; - field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program"; field public static final android.net.Uri CONTENT_URI; @@ -32574,6 +32563,7 @@ package android.os { field public static final int BATTERY_PLUGGED_AC = 1; // 0x1 field public static final int BATTERY_PLUGGED_USB = 2; // 0x2 field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4 + field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6 field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4 field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1 field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3 @@ -47776,6 +47766,7 @@ package android.view { ctor public View(android.content.Context, android.util.AttributeSet, int); ctor public View(android.content.Context, android.util.AttributeSet, int, int); method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>); + method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public void addFocusables(java.util.ArrayList<android.view.View>, int); method public void addFocusables(java.util.ArrayList<android.view.View>, int, int); method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int); @@ -47875,7 +47866,8 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public android.view.autofill.AutoFillType getAutoFillType(); - method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(android.view.autofill.VirtualViewDelegate.Callback); + method public android.view.autofill.AutoFillValue getAutoFillValue(); + method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(); method public android.graphics.drawable.Drawable getBackground(); method public android.content.res.ColorStateList getBackgroundTintList(); method public android.graphics.PorterDuff.Mode getBackgroundTintMode(); @@ -48470,6 +48462,7 @@ package android.view { public static class View.AccessibilityDelegate { ctor public View.AccessibilityDelegate(); + method public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View); method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); @@ -49593,6 +49586,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList(); method public deprecated int getActions(); + method public java.util.List<java.lang.String> getAvailableExtraData(); method public void getBoundsInParent(android.graphics.Rect); method public void getBoundsInScreen(android.graphics.Rect); method public android.view.accessibility.AccessibilityNodeInfo getChild(int); @@ -49649,11 +49643,13 @@ package android.view.accessibility { method public boolean performAction(int, android.os.Bundle); method public void recycle(); method public boolean refresh(); + method public boolean refreshWithExtraData(java.lang.String, android.os.Bundle); method public deprecated void removeAction(int); method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction); method public boolean removeChild(android.view.View); method public boolean removeChild(android.view.View, int); method public void setAccessibilityFocused(boolean); + method public void setAvailableExtraData(java.util.List<java.lang.String>); method public void setBoundsInParent(android.graphics.Rect); method public void setBoundsInScreen(android.graphics.Rect); method public void setCanOpenPopup(boolean); @@ -49736,6 +49732,9 @@ package android.view.accessibility { field public static final int ACTION_SET_SELECTION = 131072; // 0x20000 field public static final int ACTION_SET_TEXT = 2097152; // 0x200000 field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH"; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX"; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2 field public static final int FOCUS_INPUT = 1; // 0x1 field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1 @@ -49817,6 +49816,7 @@ package android.view.accessibility { public abstract class AccessibilityNodeProvider { ctor public AccessibilityNodeProvider(); + method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); @@ -50227,11 +50227,11 @@ package android.view.autofill { } public final class AutoFillManager { - method public void onValueChanged(android.view.View, android.view.autofill.AutoFillValue); - method public void updateAutoFillInput(android.view.View, int); - method public void updateAutoFillInput(android.view.View, int, android.graphics.Rect, int); - field public static final int FLAG_UPDATE_UI_HIDE = 2; // 0x2 - field public static final int FLAG_UPDATE_UI_SHOW = 1; // 0x1 + method public void focusChanged(android.view.View, boolean); + method public void reset(); + method public void valueChanged(android.view.View); + method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean); + method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue); } public final class AutoFillType implements android.os.Parcelable { @@ -50293,13 +50293,6 @@ package android.view.autofill { method public abstract void autoFill(int, android.view.autofill.AutoFillValue); } - public static abstract class VirtualViewDelegate.Callback { - ctor public VirtualViewDelegate.Callback(); - method public void onAutoFillInputUpdated(int, android.graphics.Rect, int); - method public void onNodeRemoved(int...); - method public void onValueChanged(int); - } - } package android.view.inputmethod { @@ -50710,7 +50703,7 @@ package android.view.textclassifier { public final class TextClassificationManager { method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); - method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier(); + method public android.view.textclassifier.TextClassifier getDefaultTextClassifier(); } public final class TextClassificationResult { diff --git a/api/test-current.txt b/api/test-current.txt index d47fe3e79d72..5d6f5d08646d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -118,6 +118,7 @@ package android { field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; + field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS"; field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM"; @@ -5690,10 +5691,11 @@ package android.app { } public final class RemoteAction implements android.os.Parcelable { - ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener); + ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); method public android.app.RemoteAction clone(); method public int describeContents(); method public void dump(java.lang.String, java.io.PrintWriter); + method public android.app.PendingIntent getActionIntent(); method public java.lang.CharSequence getContentDescription(); method public android.graphics.drawable.Icon getIcon(); method public java.lang.CharSequence getTitle(); @@ -5701,10 +5703,6 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR; } - public static abstract interface RemoteAction.OnActionListener { - method public abstract void onAction(android.app.RemoteAction); - } - public final class RemoteInput implements android.os.Parcelable { method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>); method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle); @@ -6240,6 +6238,7 @@ package android.app.admin { method public long getLastBugReportRequestTime(); method public long getLastNetworkLogRetrievalTime(); method public long getLastSecurityLogRetrievalTime(); + method public java.lang.String[] getLockTaskPackages(android.content.ComponentName); method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); @@ -24047,6 +24046,31 @@ package android.media.tv { field public static final java.lang.String AUTHORITY = "android.media.tv"; } + public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns { + field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; + field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; + field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; + field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; + field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; + field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; + field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; + field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; + field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; + field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; + field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; + field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; + field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; + field public static final java.lang.String COLUMN_TITLE = "title"; + field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; + field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; + field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; + } + public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns { field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name"; } @@ -24129,7 +24153,7 @@ package android.media.tv { field public static final java.lang.String CONTENT_DIRECTORY = "logo"; } - public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns { + public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns { field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9"; field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1"; field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3"; @@ -24138,53 +24162,31 @@ package android.media.tv { field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION"; field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT"; field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri"; - field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; field public static final java.lang.String COLUMN_AUTHOR = "author"; field public static final java.lang.String COLUMN_AVAILABILITY = "availability"; field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; - field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; - field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; - field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis"; field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; - field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number"; - field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count"; field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id"; field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count"; field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis"; field public static final java.lang.String COLUMN_LIVE = "live"; field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri"; - field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price"; field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio"; - field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri"; field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited"; field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date"; field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating"; field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style"; - field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; - field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number"; - field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; - field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price"; field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio"; - field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - field public static final java.lang.String COLUMN_TITLE = "title"; field public static final java.lang.String COLUMN_TYPE = "type"; - field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; - field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; - field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type"; field public static final java.lang.String COLUMN_WEIGHT = "weight"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program"; @@ -24240,37 +24242,15 @@ package android.media.tv { field public static final java.lang.String TRAVEL = "TRAVEL"; } - public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns { - field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language"; + public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns { field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre"; - field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre"; - field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id"; - field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating"; field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis"; - field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; - field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title"; field public static final java.lang.String COLUMN_INPUT_ID = "input_id"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; - field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description"; - field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri"; field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes"; field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri"; field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis"; field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis"; - field public static final java.lang.String COLUMN_SEARCHABLE = "searchable"; - field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; - field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title"; - field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description"; field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis"; - field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - field public static final java.lang.String COLUMN_TITLE = "title"; - field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number"; - field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height"; - field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program"; field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program"; field public static final android.net.Uri CONTENT_URI; @@ -29952,6 +29932,7 @@ package android.os { field public static final int BATTERY_PLUGGED_AC = 1; // 0x1 field public static final int BATTERY_PLUGGED_USB = 2; // 0x2 field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4 + field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6 field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4 field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1 field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3 @@ -44675,6 +44656,7 @@ package android.view { ctor public View(android.content.Context, android.util.AttributeSet, int); ctor public View(android.content.Context, android.util.AttributeSet, int, int); method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>); + method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public void addFocusables(java.util.ArrayList<android.view.View>, int); method public void addFocusables(java.util.ArrayList<android.view.View>, int, int); method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int); @@ -44774,7 +44756,8 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public android.view.autofill.AutoFillType getAutoFillType(); - method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(android.view.autofill.VirtualViewDelegate.Callback); + method public android.view.autofill.AutoFillValue getAutoFillValue(); + method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(); method public android.graphics.drawable.Drawable getBackground(); method public android.content.res.ColorStateList getBackgroundTintList(); method public android.graphics.PorterDuff.Mode getBackgroundTintMode(); @@ -45370,6 +45353,7 @@ package android.view { public static class View.AccessibilityDelegate { ctor public View.AccessibilityDelegate(); + method public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View); method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent); @@ -46494,6 +46478,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList(); method public deprecated int getActions(); + method public java.util.List<java.lang.String> getAvailableExtraData(); method public void getBoundsInParent(android.graphics.Rect); method public void getBoundsInScreen(android.graphics.Rect); method public android.view.accessibility.AccessibilityNodeInfo getChild(int); @@ -46550,11 +46535,13 @@ package android.view.accessibility { method public boolean performAction(int, android.os.Bundle); method public void recycle(); method public boolean refresh(); + method public boolean refreshWithExtraData(java.lang.String, android.os.Bundle); method public deprecated void removeAction(int); method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction); method public boolean removeChild(android.view.View); method public boolean removeChild(android.view.View, int); method public void setAccessibilityFocused(boolean); + method public void setAvailableExtraData(java.util.List<java.lang.String>); method public void setBoundsInParent(android.graphics.Rect); method public void setBoundsInScreen(android.graphics.Rect); method public void setCanOpenPopup(boolean); @@ -46638,6 +46625,9 @@ package android.view.accessibility { field public static final int ACTION_SET_SELECTION = 131072; // 0x20000 field public static final int ACTION_SET_TEXT = 2097152; // 0x200000 field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH"; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX"; + field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2 field public static final int FOCUS_INPUT = 1; // 0x1 field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1 @@ -46719,6 +46709,7 @@ package android.view.accessibility { public abstract class AccessibilityNodeProvider { ctor public AccessibilityNodeProvider(); + method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle); method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int); method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int); method public android.view.accessibility.AccessibilityNodeInfo findFocus(int); @@ -47130,11 +47121,11 @@ package android.view.autofill { } public final class AutoFillManager { - method public void onValueChanged(android.view.View, android.view.autofill.AutoFillValue); - method public void updateAutoFillInput(android.view.View, int); - method public void updateAutoFillInput(android.view.View, int, android.graphics.Rect, int); - field public static final int FLAG_UPDATE_UI_HIDE = 2; // 0x2 - field public static final int FLAG_UPDATE_UI_SHOW = 1; // 0x1 + method public void focusChanged(android.view.View, boolean); + method public void reset(); + method public void valueChanged(android.view.View); + method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean); + method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue); } public final class AutoFillType implements android.os.Parcelable { @@ -47196,13 +47187,6 @@ package android.view.autofill { method public abstract void autoFill(int, android.view.autofill.AutoFillValue); } - public static abstract class VirtualViewDelegate.Callback { - ctor public VirtualViewDelegate.Callback(); - method public void onAutoFillInputUpdated(int, android.graphics.Rect, int); - method public void onNodeRemoved(int...); - method public void onValueChanged(int); - } - } package android.view.inputmethod { @@ -47613,7 +47597,7 @@ package android.view.textclassifier { public final class TextClassificationManager { method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); - method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier(); + method public android.view.textclassifier.TextClassifier getDefaultTextClassifier(); } public final class TextClassificationResult { diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 79017378c909..a6d2986e185a 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -352,7 +352,7 @@ bool BootAnimation::threadLoop() bool BootAnimation::android() { - ALOGD("BootAnimationShownTiming: BootAnimation start time: %" PRId64 "ms", elapsedRealtime()); + ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); @@ -878,7 +878,7 @@ bool BootAnimation::playAnimation(const Animation& animation) const int animationX = (mWidth - animation.width) / 2; const int animationY = (mHeight - animation.height) / 2; - ALOGD("BootAnimationShownTiming: BootAnimation start time: %" PRId64 "ms", elapsedRealtime()); + ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime()); for (size_t i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index 5bd372208f6f..7a1931718888 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -37,7 +37,8 @@ interface IAccessibilityServiceConnection { boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, long accessibilityNodeId, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, long threadId); + IAccessibilityInteractionConnectionCallback callback, int flags, long threadId, + in Bundle arguments); boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 6f9530901d82..6a1e74e053e2 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -49,7 +49,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -74,8 +73,6 @@ import android.os.ServiceManager.ServiceNotFoundException; import android.os.StrictMode; import android.os.SystemProperties; import android.os.UserHandle; -import android.service.autofill.AutoFillService; -import android.service.autofill.IAutoFillAppCallback; import android.text.Selection; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -116,7 +113,6 @@ 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.AutoFillSession; import android.widget.AdapterView; @@ -127,7 +123,6 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -1700,16 +1695,21 @@ public class Activity extends ContextThemeWrapper } /** - * Lazily gets the {@link IAutoFillAppCallback} for this activitity. - * - * <p>This callback is used by the {@link AutoFillService} app to auto-fill the activity fields. + * Lazily attachs the activity to the current {@link AutoFillSession} (if any). */ - IAutoFillAppCallback getAutoFillCallback() { + void attachToAutoFillSession() { synchronized (this) { if (mAutoFillSession == null) { - mAutoFillSession = new AutoFillSession(this); + final AutoFillManager afm = getSystemService(AutoFillManager.class); + if (afm != null) { + mAutoFillSession = afm.getSession(); + if (mAutoFillSession != null) { + mAutoFillSession.attachActivity(this); + } else { + Log.w(TAG, "attachToAutoFillSession(): not in a session"); + } + } } - return mAutoFillSession.getCallback(); } } @@ -1798,6 +1798,10 @@ public class Activity extends ContextThemeWrapper getApplication().dispatchActivityStopped(this); mTranslucentCallback = null; mCalled = true; + if (mAutoFillSession != null && isFinishing()) { + mAutoFillSession.finishSession(); + mAutoFillSession = null; + } } /** diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index e848080d3e32..89510d9f2d15 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -154,12 +154,6 @@ public abstract class ActivityManagerInternal { public abstract List<IBinder> getTopVisibleActivities(); /** - * Returns the top, focused activity of the currently visible stack, but only if it belongs to - * the given UID. - */ - public abstract IBinder getTopVisibleActivity(int uid); - - /** * Callback for window manager to let activity manager know that docked stack changes its * minimized state. */ diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d5371f8b7b3c..dffd81fbbcab 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2931,7 +2931,7 @@ public final class ActivityThread { if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutoFill) { structure = new AssistStructure(r.activity, forAutoFill); Intent activityIntent = r.activity.getIntent(); - boolean addAutoFillCallback = false; + boolean attachToSession = false; // TODO(b/33197203): re-evaluate conditions below for auto-fill. In particular, // FLAG_SECURE might be allowed on AUTO_FILL but not on AUTO_FILL_SAVE) boolean notSecure = r.window == null || @@ -2939,7 +2939,7 @@ public final class ActivityThread { & WindowManager.LayoutParams.FLAG_SECURE) == 0; if (activityIntent != null && notSecure) { if (forAutoFill) { - addAutoFillCallback = true; + attachToSession = true; } else { Intent intent = new Intent(activityIntent); intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION @@ -2953,18 +2953,13 @@ public final class ActivityThread { } else { // activityIntent is unlikely to be null, but if it is, we should still // set the auto-fill callback. - addAutoFillCallback = notSecure; + attachToSession = notSecure; } } if (!forAutoFill) { r.activity.onProvideAssistContent(content); - } else if (addAutoFillCallback) { - IAutoFillAppCallback cb = r.activity.getAutoFillCallback(); - if (cb != null) { - data.putBinder(AutoFillService.KEY_CALLBACK, cb.asBinder()); - } else { - Slog.w(TAG, "handleRequestAssistContextExtras(): callback was GCed"); - } + } else if (attachToSession) { + r.activity.attachToAutoFillSession(); } } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 9db2b9237b02..16989c060bc4 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1896,7 +1896,7 @@ class ContextImpl extends Context { pi.getResDir(), pi.getSplitResDirs(), pi.getOverlayDirs(), - pi.getSharedLibraries(), + pi.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfig, compatInfo, @@ -2180,7 +2180,7 @@ class ContextImpl extends Context { packageInfo.getResDir(), splitDirs, packageInfo.getOverlayDirs(), - packageInfo.getSharedLibraries(), + packageInfo.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfiguration, compatInfo, diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 99ae96df01eb..c842f788feda 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -585,7 +585,7 @@ interface IActivityManager { void unregisterTaskStackListener(ITaskStackListener listener); void moveStackToDisplay(int stackId, int displayId); boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras, - int resultCode, in IBinder activityToken); + in IBinder activityToken); void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback); int restartUserInBackground(int userId); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 17f5eddd0af6..7ed96af6fa21 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -311,7 +311,7 @@ public final class LoadedApk { } mResources = ResourcesManager.getInstance().getResources(null, mResDir, - splitPaths, mOverlayDirs, mSharedLibraries, + splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), getClassLoader()); } @@ -923,10 +923,6 @@ public final class LoadedApk { return mOverlayDirs; } - public String[] getSharedLibraries() { - return mSharedLibraries; - } - public String getDataDir() { return mDataDir; } @@ -958,7 +954,7 @@ public final class LoadedApk { } mResources = ResourcesManager.getInstance().getResources(null, mResDir, - splitPaths, mOverlayDirs, mSharedLibraries, + splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), getClassLoader()); } diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java index a37680f7a8f8..5958bc14d474 100644 --- a/core/java/android/app/RemoteAction.java +++ b/core/java/android/app/RemoteAction.java @@ -35,55 +35,30 @@ import java.io.PrintWriter; */ public final class RemoteAction implements Parcelable { - /** - * Interface definition for a callback to be invoked when an action is invoked. - */ - public interface OnActionListener { - /** - * Called when the associated action is invoked. - * - * @param action The action that was invoked. - */ - void onAction(RemoteAction action); - } - private static final String TAG = "RemoteAction"; - private static final int MESSAGE_ACTION_INVOKED = 1; - private final Icon mIcon; private final CharSequence mTitle; private final CharSequence mContentDescription; - private OnActionListener mActionCallback; - private final Messenger mMessenger; + private final PendingIntent mActionIntent; RemoteAction(Parcel in) { mIcon = Icon.CREATOR.createFromParcel(in); mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mMessenger = in.readParcelable(Messenger.class.getClassLoader()); + mActionIntent = PendingIntent.CREATOR.createFromParcel(in); } public RemoteAction(@NonNull Icon icon, @NonNull CharSequence title, - @NonNull CharSequence contentDescription, @NonNull OnActionListener callback) { - if (icon == null || title == null || contentDescription == null || callback == null) { + @NonNull CharSequence contentDescription, @NonNull PendingIntent intent) { + if (icon == null || title == null || contentDescription == null || intent == null) { throw new IllegalArgumentException("Expected icon, title, content description and " + "action callback"); } mIcon = icon; mTitle = title; mContentDescription = contentDescription; - mActionCallback = callback; - mMessenger = new Messenger(new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_ACTION_INVOKED: - mActionCallback.onAction(RemoteAction.this); - break; - } - } - }); + mActionIntent = intent; } /** @@ -108,22 +83,15 @@ public final class RemoteAction implements Parcelable { } /** - * Sends a message that the action was invoked. - * @hide + * Return the action intent. */ - public void sendActionInvoked() { - Message m = Message.obtain(); - m.what = MESSAGE_ACTION_INVOKED; - try { - mMessenger.send(m); - } catch (RemoteException e) { - Log.e(TAG, "Could not send action-invoked", e); - } + public @NonNull PendingIntent getActionIntent() { + return mActionIntent; } @Override public RemoteAction clone() { - return new RemoteAction(mIcon, mTitle, mContentDescription, mActionCallback); + return new RemoteAction(mIcon, mTitle, mContentDescription, mActionIntent); } @Override @@ -136,7 +104,7 @@ public final class RemoteAction implements Parcelable { mIcon.writeToParcel(out, 0); TextUtils.writeToParcel(mTitle, out, flags); TextUtils.writeToParcel(mContentDescription, out, flags); - out.writeParcelable(mMessenger, flags); + mActionIntent.writeToParcel(out, flags); } public void dump(String prefix, PrintWriter pw) { @@ -144,6 +112,7 @@ public final class RemoteAction implements Parcelable { pw.print("title=" + mTitle); pw.print(" contentDescription=" + mContentDescription); pw.print(" icon=" + mIcon); + pw.print(" action=" + mActionIntent.getIntent()); pw.println(); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 08832d1baa8b..f1ccabe57e32 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -377,7 +377,7 @@ public class DevicePolicyManager { * @hide */ public static final String ACTION_BUGREPORT_SHARING_ACCEPTED = - "com.android.server.action.BUGREPORT_SHARING_ACCEPTED"; + "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED"; /** * Action: Bugreport sharing with device owner has been declined by the user. @@ -385,7 +385,7 @@ public class DevicePolicyManager { * @hide */ public static final String ACTION_BUGREPORT_SHARING_DECLINED = - "com.android.server.action.BUGREPORT_SHARING_DECLINED"; + "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED"; /** * Action: Bugreport has been collected and is dispatched to {@code DevicePolicyManagerService}. @@ -6108,8 +6108,6 @@ public class DevicePolicyManager { * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of * an affiliated user or profile. * @see #setLockTaskPackages - * - * @hide */ public @NonNull String[] getLockTaskPackages(@NonNull ComponentName admin) { throwIfParentInstance("getLockTaskPackages"); diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java index a48210340e63..176e48fb6e08 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -37,9 +37,11 @@ public final class BluetoothCodecConfig implements Parcelable { public static final int SOURCE_CODEC_TYPE_APTX = 2; public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; public static final int SOURCE_CODEC_TYPE_LDAC = 4; + public static final int SOURCE_CODEC_TYPE_MAX = 5; public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; + public static final int CODEC_PRIORITY_DISABLED = -1; public static final int CODEC_PRIORITY_DEFAULT = 0; public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; @@ -72,7 +74,7 @@ public final class BluetoothCodecConfig implements Parcelable { public BluetoothCodecConfig(int codecType, int codecPriority, int sampleRate, int bitsPerSample, - int channelMode,long codecSpecific1, + int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) { mCodecType = codecType; diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 3cf36d7e4189..bf8109627e7e 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -753,7 +753,7 @@ public class ResourcesImpl { } final String file = value.string.toString(); - Typeface cached = Typeface.createFromCache(mAssets, file); + Typeface cached = Typeface.findFromCache(mAssets, file); if (cached != null) { return cached; } diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 263750aa9946..3a441c7cb1ca 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -201,6 +201,11 @@ public class BatteryManager { */ public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; + /** + * Battery charge status, from a BATTERY_STATUS_* value. + */ + public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; + private final IBatteryStats mBatteryStats; private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar; diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index 06666f459e5d..5e7f68b794bf 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -16,6 +16,7 @@ package android.preference; +import android.animation.LayoutTransition; import android.annotation.Nullable; import android.annotation.StringRes; import android.annotation.XmlRes; @@ -87,7 +88,7 @@ import java.util.List; * items. Doing this implicitly switches the class into its new "headers * + fragments" mode rather than the old style of just showing a single * preferences list. - * + * * <div class="special reference"> * <h3>Developer Guides</h3> * <p>For information about using {@code PreferenceActivity}, @@ -199,6 +200,9 @@ public abstract class PreferenceActivity extends ListActivity implements private ViewGroup mPrefsContainer; + // Null if in legacy mode. + private ViewGroup mHeadersContainer; + private FragmentBreadCrumbs mFragmentBreadCrumbs; private boolean mSinglePane; @@ -292,7 +296,7 @@ public abstract class PreferenceActivity extends ListActivity implements holder = (HeaderViewHolder) view.getTag(); } - // All view fields must be updated every time, because the view may be recycled + // All view fields must be updated every time, because the view may be recycled Header header = getItem(position); if (mRemoveIconIfEmpty) { if (header.iconRes == 0) { @@ -469,7 +473,7 @@ public abstract class PreferenceActivity extends ListActivity implements } return breadCrumbShortTitle; } - + @Override public int describeContents() { return 0; @@ -558,6 +562,7 @@ public abstract class PreferenceActivity extends ListActivity implements mListFooter = (FrameLayout)findViewById(com.android.internal.R.id.list_footer); mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs_frame); + mHeadersContainer = (ViewGroup) findViewById(com.android.internal.R.id.headers); boolean hidingHeaders = onIsHidingHeaders(); mSinglePane = hidingHeaders || !onIsMultiPane(); String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); @@ -575,66 +580,39 @@ public abstract class PreferenceActivity extends ListActivity implements (int) HEADER_ID_UNDEFINED); if (curHeader >= 0 && curHeader < mHeaders.size()) { setSelectedHeader(mHeaders.get(curHeader)); + } else if (!mSinglePane && initialFragment == null) { + switchToHeader(onGetInitialHeader()); } + } else { + // This will for instance hide breadcrumbs for single pane. + showBreadCrumbs(getTitle(), null); } - } else { - if (initialFragment != null && mSinglePane) { - // If we are just showing a fragment, we want to run in - // new fragment mode, but don't need to compute and show - // the headers. - switchToHeader(initialFragment, initialArguments); - if (initialTitle != 0) { - CharSequence initialTitleStr = getText(initialTitle); - CharSequence initialShortTitleStr = initialShortTitle != 0 - ? getText(initialShortTitle) : null; - showBreadCrumbs(initialTitleStr, initialShortTitleStr); - } - - } else { - // We need to try to build the headers. + if (!onIsHidingHeaders()) { onBuildHeaders(mHeaders); + } - // If there are headers, then at this point we need to show - // them and, depending on the screen, we may also show in-line - // the currently selected preference fragment. - if (mHeaders.size() > 0) { - if (!mSinglePane) { - if (initialFragment == null) { - Header h = onGetInitialHeader(); - switchToHeader(h); - } else { - switchToHeader(initialFragment, initialArguments); - } - } - } + if (initialFragment != null) { + switchToHeader(initialFragment, initialArguments); + } else if (!mSinglePane && mHeaders.size() > 0) { + switchToHeader(onGetInitialHeader()); } } - // The default configuration is to only show the list view. Adjust - // visibility for other configurations. - if (initialFragment != null && mSinglePane) { - // Single pane, showing just a prefs fragment. - findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE); - mPrefsContainer.setVisibility(View.VISIBLE); - if (initialTitle != 0) { - CharSequence initialTitleStr = getText(initialTitle); - CharSequence initialShortTitleStr = initialShortTitle != 0 - ? getText(initialShortTitle) : null; - showBreadCrumbs(initialTitleStr, initialShortTitleStr); - } - } else if (mHeaders.size() > 0) { + if (mHeaders.size() > 0) { setListAdapter(new HeaderAdapter(this, mHeaders, mPreferenceHeaderItemResId, mPreferenceHeaderRemoveEmptyIcon)); - if (!mSinglePane) { - // Multi-pane. - getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); - if (mCurHeader != null) { - setSelectedHeader(mCurHeader); - } - mPrefsContainer.setVisibility(View.VISIBLE); - } - } else { + getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); + } + + if (mSinglePane && initialFragment != null && initialTitle != 0) { + CharSequence initialTitleStr = getText(initialTitle); + CharSequence initialShortTitleStr = initialShortTitle != 0 + ? getText(initialShortTitle) : null; + showBreadCrumbs(initialTitleStr, initialShortTitleStr); + } + + if (mHeaders.size() == 0 && initialFragment == null) { // If there are no headers, we are in the old "just show a screen // of preferences" mode. setContentView(com.android.internal.R.layout.preference_list_content_single); @@ -642,6 +620,25 @@ public abstract class PreferenceActivity extends ListActivity implements mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs); mPreferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE); mPreferenceManager.setOnPreferenceTreeClickListener(this); + mHeadersContainer = null; + } else if (mSinglePane) { + // Single-pane so one of the header or prefs containers must be hidden. + if (initialFragment != null || mCurHeader != null) { + mHeadersContainer.setVisibility(View.GONE); + } else { + mPrefsContainer.setVisibility(View.GONE); + } + + // This animates our manual transitions between headers and prefs panel in single-pane. + // It also comes last so we don't animate any initial layout changes done above. + ViewGroup container = (ViewGroup) findViewById( + com.android.internal.R.id.prefs_container); + container.setLayoutTransition(new LayoutTransition()); + } else { + // Multi-pane + if (mHeaders.size() > 0 && mCurHeader != null) { + setSelectedHeader(mCurHeader); + } } // see if we should show Back/Next buttons @@ -697,12 +694,25 @@ public abstract class PreferenceActivity extends ListActivity implements } } + @Override + public void onBackPressed() { + if (mCurHeader != null && mSinglePane && getFragmentManager().getBackStackEntryCount() == 0 + && getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT) == null) { + mCurHeader = null; + + mPrefsContainer.setVisibility(View.GONE); + mHeadersContainer.setVisibility(View.VISIBLE); + getListView().clearChoices(); + } else { + super.onBackPressed(); + } + } + /** * Returns true if this activity is currently showing the header list. */ public boolean hasHeaders() { - return getListView().getVisibility() == View.VISIBLE - && mPreferenceManager == null; + return mHeadersContainer != null && mHeadersContainer.getVisibility() == View.VISIBLE; } /** @@ -718,7 +728,7 @@ public abstract class PreferenceActivity extends ListActivity implements * and a preference fragment. */ public boolean isMultiPane() { - return hasHeaders() && mPrefsContainer.getVisibility() == View.VISIBLE; + return !mSinglePane; } /** @@ -820,14 +830,14 @@ public abstract class PreferenceActivity extends ListActivity implements if (!"preference-headers".equals(nodeName)) { throw new RuntimeException( "XML document must start with <preference-headers> tag; found" - + nodeName + " at " + parser.getPositionDescription()); + + nodeName + " at " + parser.getPositionDescription()); } Bundle curBundle = null; final int outerDepth = parser.getDepth(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } @@ -889,7 +899,7 @@ public abstract class PreferenceActivity extends ListActivity implements final int innerDepth = parser.getDepth(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { + && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } @@ -939,8 +949,9 @@ public abstract class PreferenceActivity extends ListActivity implements if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.KITKAT) { throw new RuntimeException( "Subclasses of PreferenceActivity must override isValidFragment(String)" - + " to verify that the Fragment class is valid! " + this.getClass().getName() - + " has not checked if fragment " + fragmentName + " is valid."); + + " to verify that the Fragment class is valid! " + + this.getClass().getName() + + " has not checked if fragment " + fragmentName + " is valid."); } else { return true; } @@ -1017,6 +1028,13 @@ public abstract class PreferenceActivity extends ListActivity implements // Only call this if we didn't save the instance state for later. // If we did save it, it will be restored when we bind the adapter. super.onRestoreInstanceState(state); + + if (!mSinglePane) { + // Multi-pane. + if (mCurHeader != null) { + setSelectedHeader(mCurHeader); + } + } } @Override @@ -1061,18 +1079,7 @@ public abstract class PreferenceActivity extends ListActivity implements */ public void onHeaderClick(Header header, int position) { if (header.fragment != null) { - if (mSinglePane) { - int titleRes = header.breadCrumbTitleRes; - int shortTitleRes = header.breadCrumbShortTitleRes; - if (titleRes == 0) { - titleRes = header.titleRes; - shortTitleRes = 0; - } - startWithFragment(header.fragment, header.fragmentArguments, null, 0, - titleRes, shortTitleRes); - } else { - switchToHeader(header); - } + switchToHeader(header); } else if (header.intent != null) { startActivity(header.intent); } @@ -1084,7 +1091,7 @@ public abstract class PreferenceActivity extends ListActivity implements * the selected fragment. The default implementation constructs an Intent * that re-launches the current activity with the appropriate arguments to * display the fragment. - * + * * @param fragmentName The name of the fragment to display. * @param args Optional arguments to supply to the fragment. * @param titleRes Optional resource ID of title to show for this item. @@ -1103,7 +1110,7 @@ public abstract class PreferenceActivity extends ListActivity implements intent.putExtra(EXTRA_NO_HEADERS, true); return intent; } - + /** * Like {@link #startWithFragment(String, Bundle, Fragment, int, int, int)} * but uses a 0 titleRes. @@ -1223,11 +1230,21 @@ public abstract class PreferenceActivity extends ListActivity implements throw new IllegalArgumentException("Invalid fragment for this activity: " + fragmentName); } + Fragment f = Fragment.instantiate(this, fragmentName, args); FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); + transaction.setTransition(mSinglePane + ? FragmentTransaction.TRANSIT_NONE + : FragmentTransaction.TRANSIT_FRAGMENT_FADE); transaction.replace(com.android.internal.R.id.prefs, f); transaction.commitAllowingStateLoss(); + + if (mSinglePane && mPrefsContainer.getVisibility() == View.GONE) { + // We are transitioning from headers to preferences panel in single-pane so we need + // to hide headers and show the prefs container. + mPrefsContainer.setVisibility(View.VISIBLE); + mHeadersContainer.setVisibility(View.GONE); + } } /** @@ -1340,7 +1357,7 @@ public abstract class PreferenceActivity extends ListActivity implements * be instantiated and placed in the appropriate pane. If running in * single-pane mode, a new activity will be launched in which to show the * fragment. - * + * * @param fragmentClass Full name of the class implementing the fragment. * @param args Any desired arguments to supply to the fragment. * @param titleRes Optional resource identifier of the title of this @@ -1355,29 +1372,25 @@ public abstract class PreferenceActivity extends ListActivity implements */ public void startPreferencePanel(String fragmentClass, Bundle args, @StringRes int titleRes, CharSequence titleText, Fragment resultTo, int resultRequestCode) { - if (mSinglePane) { - startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0); - } else { - Fragment f = Fragment.instantiate(this, fragmentClass, args); - if (resultTo != null) { - f.setTargetFragment(resultTo, resultRequestCode); - } - FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.replace(com.android.internal.R.id.prefs, f); - if (titleRes != 0) { - transaction.setBreadCrumbTitle(titleRes); - } else if (titleText != null) { - transaction.setBreadCrumbTitle(titleText); - } - transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); - transaction.addToBackStack(BACK_STACK_PREFS); - transaction.commitAllowingStateLoss(); + Fragment f = Fragment.instantiate(this, fragmentClass, args); + if (resultTo != null) { + f.setTargetFragment(resultTo, resultRequestCode); } + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.replace(com.android.internal.R.id.prefs, f); + if (titleRes != 0) { + transaction.setBreadCrumbTitle(titleRes); + } else if (titleText != null) { + transaction.setBreadCrumbTitle(titleText); + } + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); + transaction.addToBackStack(BACK_STACK_PREFS); + transaction.commitAllowingStateLoss(); } /** * Called by a preference panel fragment to finish itself. - * + * * @param caller The fragment that is asking to be finished. * @param resultCode Optional result code to send back to the original * launching fragment. @@ -1385,21 +1398,16 @@ public abstract class PreferenceActivity extends ListActivity implements * launching fragment. */ public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) { - if (mSinglePane) { - setResult(resultCode, resultData); - finish(); - } else { - // XXX be smarter about popping the stack. - onBackPressed(); - if (caller != null) { - if (caller.getTargetFragment() != null) { - caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(), - resultCode, resultData); - } + // TODO: be smarter about popping the stack. + onBackPressed(); + if (caller != null) { + if (caller.getTargetFragment() != null) { + caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(), + resultCode, resultData); } } } - + @Override public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { startPreferencePanel(pref.getFragment(), pref.getExtras(), pref.getTitleRes(), diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java index aa4d26c18d7c..ab80aa3e23b8 100644 --- a/core/java/android/service/autofill/AutoFillService.java +++ b/core/java/android/service/autofill/AutoFillService.java @@ -67,8 +67,10 @@ public abstract class AutoFillService extends Service { */ public static final String SERVICE_META_DATA = "android.autofill"; - // Internal bundle keys. - /** @hide */ public static final String KEY_CALLBACK = "callback"; + // Internal extras + /** @hide */ + public static final String EXTRA_ACTIVITY_TOKEN = + "android.service.autofill.EXTRA_ACTIVITY_TOKEN"; // Handler messages. private static final int MSG_CONNECT = 1; diff --git a/core/java/android/service/autofill/IAutoFillAppCallback.aidl b/core/java/android/service/autofill/IAutoFillAppCallback.aidl index d9c161c1994b..c2e72e8235a4 100644 --- a/core/java/android/service/autofill/IAutoFillAppCallback.aidl +++ b/core/java/android/service/autofill/IAutoFillAppCallback.aidl @@ -38,4 +38,10 @@ oneway interface IAutoFillAppCallback { * Start an intent sender from the context of the filled app */ void startIntentSender(in IntentSender intent, in Intent fillInIntent); + + /** + * Called by system_service to enable auto-fill in a session, after it was asynchronously + * started by the manager. + */ + void enableSession(); } diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl index 088e6498a0d5..b39c0c8e07d4 100644 --- a/core/java/android/service/autofill/IAutoFillManagerService.aidl +++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl @@ -18,6 +18,7 @@ package android.service.autofill; import android.graphics.Rect; import android.os.Bundle; +import android.os.IBinder; import android.view.autofill.AutoFillId; import android.view.autofill.AutoFillValue; @@ -27,16 +28,13 @@ import android.view.autofill.AutoFillValue; * {@hide} */ oneway interface IAutoFillManagerService { + // Methods called by AutoFillManager + void startSession(in IBinder activityToken, in IBinder appCallback, in AutoFillId autoFillId, + in Rect bounds, in AutoFillValue value); + void updateSession(in IBinder activityToken, in AutoFillId id, in Rect bounds, + in AutoFillValue value, int flags); + void finishSession(in IBinder activityToken); - // Called by AutoFillManager (app). - void requestAutoFill(in AutoFillId id, in Rect bounds, int flags); - - // Called by AutoFillManager (app). - void onValueChanged(in AutoFillId id, in AutoFillValue value); - - // Called by ShellCommand only. - void requestAutoFillForUser(int userId); - - // Called by ShellCommand only. + // Methods called by ShellCommand void requestSaveForUser(int userId); } diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 55aeb1e600a0..ac9c0d782c53 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -456,10 +456,7 @@ public class TextUtils { * @return true if str is null or zero length */ public static boolean isEmpty(@Nullable CharSequence str) { - if (str == null || str.length() == 0) - return true; - else - return false; + return str == null || str.length() == 0; } /** {@hide} */ diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 13ee48ef23ce..4ff4840df453 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -17,9 +17,11 @@ package android.view; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN; +import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; import android.graphics.Point; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Region; import android.os.Binder; import android.os.Bundle; @@ -29,7 +31,6 @@ import android.os.Message; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; -import android.text.TextUtils; import android.text.style.AccessibilityClickableSpan; import android.text.style.ClickableSpan; import android.util.LongSparseArray; @@ -93,6 +94,19 @@ final class AccessibilityInteractionController { mPrefetcher = new AccessibilityNodePrefetcher(); } + private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid) { + // If the interrogation is performed by the same thread as the main UI + // thread in this process, set the message as a static reference so + // after this call completes the same thread but in the interrogating + // client can handle the message to generate the result. + if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { + AccessibilityInteractionClient.getInstanceForThread( + interrogatingTid).setSameThreadMessage(message); + } else { + mHandler.sendMessage(message); + } + } + private boolean isShown(View view) { // The first two checks are made also made by isShown() which // however traverses the tree up to the parent to catch that. @@ -106,7 +120,7 @@ final class AccessibilityInteractionController { public void findAccessibilityNodeInfoByAccessibilityIdClientThread( long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, MagnificationSpec spec) { + long interrogatingTid, MagnificationSpec spec, Bundle arguments) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID; message.arg1 = flags; @@ -118,18 +132,10 @@ final class AccessibilityInteractionController { args.arg1 = callback; args.arg2 = spec; args.arg3 = interactiveRegion; + args.arg4 = arguments; message.obj = args; - // If the interrogation is performed by the same thread as the main UI - // thread in this process, set the message as a static reference so - // after this call completes the same thread but in the interrogating - // client can handle the message to generate the result. - if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { - AccessibilityInteractionClient.getInstanceForThread( - interrogatingTid).setSameThreadMessage(message); - } else { - mHandler.sendMessage(message); - } + scheduleMessage(message, interrogatingPid, interrogatingTid); } private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) { @@ -143,6 +149,7 @@ final class AccessibilityInteractionController { (IAccessibilityInteractionConnectionCallback) args.arg1; final MagnificationSpec spec = (MagnificationSpec) args.arg2; final Region interactiveRegion = (Region) args.arg3; + final Bundle arguments = (Bundle) args.arg4; args.recycle(); @@ -160,29 +167,12 @@ final class AccessibilityInteractionController { root = findViewByAccessibilityId(accessibilityViewId); } if (root != null && isShown(root)) { - mPrefetcher.prefetchAccessibilityNodeInfos(root, virtualDescendantId, flags, infos); + mPrefetcher.prefetchAccessibilityNodeInfos( + root, virtualDescendantId, flags, infos, arguments); } } finally { - try { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - applyAppScaleAndMagnificationSpecIfNeeded(infos, spec); - // Recycle if called from another process. Specs are cached in the - // system process and obtained from a pool when read from parcel. - if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) { - spec.recycle(); - } - adjustIsVisibleToUserIfNeeded(infos, interactiveRegion); - callback.setFindAccessibilityNodeInfosResult(infos, interactionId); - infos.clear(); - } catch (RemoteException re) { - /* ignore - the other side will time out */ - } - - // Recycle if called from the same process. Regions are obtained in - // the system process and instantiated when read from parcel. - if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) { - interactiveRegion.recycle(); - } + updateInfosForViewportAndReturnFindNodeResult( + infos, callback, interactionId, spec, interactiveRegion); } } @@ -201,19 +191,9 @@ final class AccessibilityInteractionController { args.arg2 = spec; args.arg3 = viewId; args.arg4 = interactiveRegion; - message.obj = args; - // If the interrogation is performed by the same thread as the main UI - // thread in this process, set the message as a static reference so - // after this call completes the same thread but in the interrogating - // client can handle the message to generate the result. - if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { - AccessibilityInteractionClient.getInstanceForThread( - interrogatingTid).setSameThreadMessage(message); - } else { - mHandler.sendMessage(message); - } + scheduleMessage(message, interrogatingPid, interrogatingTid); } private void findAccessibilityNodeInfosByViewIdUiThread(Message message) { @@ -227,7 +207,6 @@ final class AccessibilityInteractionController { final MagnificationSpec spec = (MagnificationSpec) args.arg2; final String viewId = (String) args.arg3; final Region interactiveRegion = (Region) args.arg4; - args.recycle(); final List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList; @@ -257,25 +236,8 @@ final class AccessibilityInteractionController { mAddNodeInfosForViewId.reset(); } } finally { - try { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - applyAppScaleAndMagnificationSpecIfNeeded(infos, spec); - // Recycle if called from another process. Specs are cached in the - // system process and obtained from a pool when read from parcel. - if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) { - spec.recycle(); - } - adjustIsVisibleToUserIfNeeded(infos, interactiveRegion); - callback.setFindAccessibilityNodeInfosResult(infos, interactionId); - } catch (RemoteException re) { - /* ignore - the other side will time out */ - } - - // Recycle if called from the same process. Regions are obtained in - // the system process and instantiated when read from parcel. - if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) { - interactiveRegion.recycle(); - } + updateInfosForViewportAndReturnFindNodeResult( + infos, callback, interactionId, spec, interactiveRegion); } } @@ -297,16 +259,7 @@ final class AccessibilityInteractionController { args.arg4 = interactiveRegion; message.obj = args; - // If the interrogation is performed by the same thread as the main UI - // thread in this process, set the message as a static reference so - // after this call completes the same thread but in the interrogating - // client can handle the message to generate the result. - if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { - AccessibilityInteractionClient.getInstanceForThread( - interrogatingTid).setSameThreadMessage(message); - } else { - mHandler.sendMessage(message); - } + scheduleMessage(message, interrogatingPid, interrogatingTid); } private void findAccessibilityNodeInfosByTextUiThread(Message message) { @@ -375,31 +328,14 @@ final class AccessibilityInteractionController { } } } finally { - try { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - applyAppScaleAndMagnificationSpecIfNeeded(infos, spec); - // Recycle if called from another process. Specs are cached in the - // system process and obtained from a pool when read from parcel. - if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) { - spec.recycle(); - } - adjustIsVisibleToUserIfNeeded(infos, interactiveRegion); - callback.setFindAccessibilityNodeInfosResult(infos, interactionId); - } catch (RemoteException re) { - /* ignore - the other side will time out */ - } - - // Recycle if called from the same process. Regions are obtained in - // the system process and instantiated when read from parcel. - if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) { - interactiveRegion.recycle(); - } + updateInfosForViewportAndReturnFindNodeResult( + infos, callback, interactionId, spec, interactiveRegion); } } public void findFocusClientThread(long accessibilityNodeId, int focusType, Region interactiveRegion, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid, + IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_FOCUS; @@ -416,16 +352,7 @@ final class AccessibilityInteractionController { message.obj = args; - // If the interrogation is performed by the same thread as the main UI - // thread in this process, set the message as a static reference so - // after this call completes the same thread but in the interrogating - // client can handle the message to generate the result. - if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { - AccessibilityInteractionClient.getInstanceForThread( - interrogatingTid).setSameThreadMessage(message); - } else { - mHandler.sendMessage(message); - } + scheduleMessage(message, interrogatingPid, interrogatingTid); } private void findFocusUiThread(Message message) { @@ -497,31 +424,14 @@ final class AccessibilityInteractionController { } } } finally { - try { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - applyAppScaleAndMagnificationSpecIfNeeded(focused, spec); - // Recycle if called from another process. Specs are cached in the - // system process and obtained from a pool when read from parcel. - if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) { - spec.recycle(); - } - adjustIsVisibleToUserIfNeeded(focused, interactiveRegion); - callback.setFindAccessibilityNodeInfoResult(focused, interactionId); - } catch (RemoteException re) { - /* ignore - the other side will time out */ - } - - // Recycle if called from the same process. Regions are obtained in - // the system process and instantiated when read from parcel. - if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) { - interactiveRegion.recycle(); - } + updateInfoForViewportAndReturnFindNodeResult( + focused, callback, interactionId, spec, interactiveRegion); } } public void focusSearchClientThread(long accessibilityNodeId, int direction, Region interactiveRegion, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid, + IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FOCUS_SEARCH; @@ -537,16 +447,7 @@ final class AccessibilityInteractionController { message.obj = args; - // If the interrogation is performed by the same thread as the main UI - // thread in this process, set the message as a static reference so - // after this call completes the same thread but in the interrogating - // client can handle the message to generate the result. - if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { - AccessibilityInteractionClient.getInstanceForThread( - interrogatingTid).setSameThreadMessage(message); - } else { - mHandler.sendMessage(message); - } + scheduleMessage(message, interrogatingPid, interrogatingTid); } private void focusSearchUiThread(Message message) { @@ -582,31 +483,14 @@ final class AccessibilityInteractionController { } } } finally { - try { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - applyAppScaleAndMagnificationSpecIfNeeded(next, spec); - // Recycle if called from another process. Specs are cached in the - // system process and obtained from a pool when read from parcel. - if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) { - spec.recycle(); - } - adjustIsVisibleToUserIfNeeded(next, interactiveRegion); - callback.setFindAccessibilityNodeInfoResult(next, interactionId); - } catch (RemoteException re) { - /* ignore - the other side will time out */ - } - - // Recycle if called from the same process. Regions are obtained in - // the system process and instantiated when read from parcel. - if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) { - interactiveRegion.recycle(); - } + updateInfoForViewportAndReturnFindNodeResult( + next, callback, interactionId, spec, interactiveRegion); } } public void performAccessibilityActionClientThread(long accessibilityNodeId, int action, Bundle arguments, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid, + IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_PERFORM_ACCESSIBILITY_ACTION; @@ -622,16 +506,7 @@ final class AccessibilityInteractionController { message.obj = args; - // If the interrogation is performed by the same thread as the main UI - // thread in this process, set the message as a static reference so - // after this call completes the same thread but in the interrogating - // client can handle the message to generate the result. - if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { - AccessibilityInteractionClient.getInstanceForThread( - interrogatingTid).setSameThreadMessage(message); - } else { - mHandler.sendMessage(message); - } + scheduleMessage(message, interrogatingPid, interrogatingTid); } private void performAccessibilityActionUiThread(Message message) { @@ -742,26 +617,6 @@ final class AccessibilityInteractionController { } } - private void applyAppScaleAndMagnificationSpecIfNeeded(Point point, - MagnificationSpec spec) { - final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale; - if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) { - return; - } - - if (applicationScale != 1.0f) { - point.x *= applicationScale; - point.y *= applicationScale; - } - - if (spec != null) { - point.x *= spec.scale; - point.y *= spec.scale; - point.x += (int) spec.offsetX; - point.y += (int) spec.offsetY; - } - } - private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info, MagnificationSpec spec) { if (info == null) { @@ -791,6 +646,25 @@ final class AccessibilityInteractionController { info.setBoundsInParent(boundsInParent); info.setBoundsInScreen(boundsInScreen); + // Scale text locations if they are present + if (info.hasExtras()) { + Bundle extras = info.getExtras(); + Parcelable[] textLocations = + extras.getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY); + if (textLocations != null) { + for (int i = 0; i < textLocations.length; i++) { + // Unchecked cast - an app that puts other objects in this bundle with this + // key will crash. + RectF textLocation = ((RectF) textLocations[i]); + textLocation.scale(applicationScale); + if (spec != null) { + textLocation.scale(spec.scale); + textLocation.offset(spec.offsetX, spec.offsetY); + } + } + } + } + if (spec != null) { AttachInfo attachInfo = mViewRootImpl.mAttachInfo; if (attachInfo.mDisplay == null) { @@ -829,6 +703,53 @@ final class AccessibilityInteractionController { return (appScale != 1.0f || (spec != null && !spec.isNop())); } + private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos, + IAccessibilityInteractionConnectionCallback callback, int interactionId, + MagnificationSpec spec, Region interactiveRegion) { + try { + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; + applyAppScaleAndMagnificationSpecIfNeeded(infos, spec); + adjustIsVisibleToUserIfNeeded(infos, interactiveRegion); + callback.setFindAccessibilityNodeInfosResult(infos, interactionId); + infos.clear(); + } catch (RemoteException re) { + /* ignore - the other side will time out */ + } finally { + recycleMagnificationSpecAndRegionIfNeeded(spec, interactiveRegion); + } + } + + private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info, + IAccessibilityInteractionConnectionCallback callback, int interactionId, + MagnificationSpec spec, Region interactiveRegion) { + try { + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; + applyAppScaleAndMagnificationSpecIfNeeded(info, spec); + adjustIsVisibleToUserIfNeeded(info, interactiveRegion); + callback.setFindAccessibilityNodeInfoResult(info, interactionId); + } catch (RemoteException re) { + /* ignore - the other side will time out */ + } finally { + recycleMagnificationSpecAndRegionIfNeeded(spec, interactiveRegion); + } + } + + private void recycleMagnificationSpecAndRegionIfNeeded(MagnificationSpec spec, Region region) { + if (android.os.Process.myPid() != Binder.getCallingPid()) { + // Specs are cached in the system process and obtained from a pool when read from + // a parcel, so only recycle the spec if called from another process. + if (spec != null) { + spec.recycle(); + } + } else { + // Regions are obtained in the system process and instantiated when read from + // a parcel, so only recycle the region if caled from the same process. + if (region != null) { + region.recycle(); + } + } + } + private boolean handleClickableSpanActionUiThread( View view, int virtualDescendantId, Bundle arguments) { Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN); @@ -872,11 +793,18 @@ final class AccessibilityInteractionController { private final ArrayList<View> mTempViewList = new ArrayList<View>(); public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int fetchFlags, - List<AccessibilityNodeInfo> outInfos) { + List<AccessibilityNodeInfo> outInfos, Bundle arguments) { AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider(); + // Determine if we'll be populating extra data + final String extraDataRequested = (arguments == null) ? null + : arguments.getString(AccessibilityNodeInfo.EXTRA_DATA_REQUESTED_KEY); if (provider == null) { AccessibilityNodeInfo root = view.createAccessibilityNodeInfo(); if (root != null) { + if (extraDataRequested != null) { + view.addExtraDataToAccessibilityNodeInfo( + root, extraDataRequested, arguments); + } outInfos.add(root); if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { prefetchPredecessorsOfRealNode(view, outInfos); @@ -889,14 +817,14 @@ final class AccessibilityInteractionController { } } } else { - final AccessibilityNodeInfo root; - if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { - root = provider.createAccessibilityNodeInfo(virtualViewId); - } else { - root = provider.createAccessibilityNodeInfo( - AccessibilityNodeProvider.HOST_VIEW_ID); - } + final int idForRoot = (virtualViewId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) + ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualViewId; + final AccessibilityNodeInfo root = provider.createAccessibilityNodeInfo(idForRoot); if (root != null) { + if (extraDataRequested != null) { + provider.addExtraDataToAccessibilityNodeInfo( + idForRoot, root, extraDataRequested, arguments); + } outInfos.add(root); if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos); @@ -1202,12 +1130,12 @@ final class AccessibilityInteractionController { } private class PrivateHandler extends Handler { - private final static int MSG_PERFORM_ACCESSIBILITY_ACTION = 1; - private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2; - private final static int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3; - private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4; - private final static int MSG_FIND_FOCUS = 5; - private final static int MSG_FOCUS_SEARCH = 6; + private static final int MSG_PERFORM_ACCESSIBILITY_ACTION = 1; + private static final int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2; + private static final int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3; + private static final int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4; + private static final int MSG_FIND_FOCUS = 5; + private static final int MSG_FOCUS_SEARCH = 6; public PrivateHandler(Looper looper) { super(looper); diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java index 41a13cf59bd8..7fde8a652001 100644 --- a/core/java/android/view/FocusFinder.java +++ b/core/java/android/view/FocusFinder.java @@ -52,7 +52,9 @@ public class FocusFinder { final Rect mFocusedRect = new Rect(); final Rect mOtherRect = new Rect(); final Rect mBestCandidateRect = new Rect(); - final SequentialFocusComparator mSequentialFocusComparator = new SequentialFocusComparator(); + private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator = + new UserSpecifiedFocusComparator(); + private final FocusComparator mFocusComparator = new FocusComparator(); private final ArrayList<View> mTempList = new ArrayList<View>(); @@ -225,12 +227,10 @@ public class FocusFinder { View focused, Rect focusedRect, int direction) { try { // Note: This sort is stable. - mSequentialFocusComparator.setRoot(root); - mSequentialFocusComparator.setIsLayoutRtl(root.isLayoutRtl()); - mSequentialFocusComparator.setFocusables(focusables); - Collections.sort(focusables, mSequentialFocusComparator); + mUserSpecifiedFocusComparator.setFocusables(focusables); + Collections.sort(focusables, mUserSpecifiedFocusComparator); } finally { - mSequentialFocusComparator.recycle(); + mUserSpecifiedFocusComparator.recycle(); } final int count = focusables.size(); @@ -703,36 +703,80 @@ public class FocusFinder { return id != 0 && id != View.NO_ID; } - /** - * Sorts views according to their visual layout and geometry for default tab order. - * If views are part of a focus chain (nextFocusForwardId), then they are all grouped - * together. The head of the chain is used to determine the order of the chain and is - * first in the order and the tail of the chain is the last in the order. The views - * in the middle of the chain can be arbitrary order. - * This is used for sequential focus traversal. - */ - private static final class SequentialFocusComparator implements Comparator<View> { + static FocusComparator getFocusComparator(ViewGroup root, boolean isRtl) { + FocusComparator comparator = getInstance().mFocusComparator; + comparator.setRoot(root); + comparator.setIsLayoutRtl(isRtl); + return comparator; + } + + static final class FocusComparator implements Comparator<View> { private final Rect mFirstRect = new Rect(); private final Rect mSecondRect = new Rect(); - private ViewGroup mRoot; + private ViewGroup mRoot = null; private boolean mIsLayoutRtl; + + public void setIsLayoutRtl(boolean b) { + mIsLayoutRtl = b; + } + + public void setRoot(ViewGroup root) { + mRoot = root; + } + + public int compare(View first, View second) { + if (first == second) { + return 0; + } + + getRect(first, mFirstRect); + getRect(second, mSecondRect); + + if (mFirstRect.top < mSecondRect.top) { + return -1; + } else if (mFirstRect.top > mSecondRect.top) { + return 1; + } else if (mFirstRect.left < mSecondRect.left) { + return mIsLayoutRtl ? 1 : -1; + } else if (mFirstRect.left > mSecondRect.left) { + return mIsLayoutRtl ? -1 : 1; + } else if (mFirstRect.bottom < mSecondRect.bottom) { + return -1; + } else if (mFirstRect.bottom > mSecondRect.bottom) { + return 1; + } else if (mFirstRect.right < mSecondRect.right) { + return mIsLayoutRtl ? 1 : -1; + } else if (mFirstRect.right > mSecondRect.right) { + return mIsLayoutRtl ? -1 : 1; + } else { + // The view are distinct but completely coincident so we consider + // them equal for our purposes. Since the sort is stable, this + // means that the views will retain their layout order relative to one another. + return 0; + } + } + + private void getRect(View view, Rect rect) { + view.getDrawingRect(rect); + mRoot.offsetDescendantRectToMyCoords(view, rect); + } + } + + /** + * Sorts views according to any explicitly-specified focus-chains. If there are no explicitly + * specified focus chains (eg. no nextFocusForward attributes defined), this should be a no-op. + */ + private static final class UserSpecifiedFocusComparator implements Comparator<View> { private final SparseArray<View> mFocusables = new SparseArray<View>(); private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray(); private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>(); + private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>(); public void recycle() { - mRoot = null; mFocusables.clear(); mHeadsOfChains.clear(); mIsConnectedTo.clear(); - } - - public void setRoot(ViewGroup root) { - mRoot = root; - } - - public void setIsLayoutRtl(boolean b) { - mIsLayoutRtl = b; + mOriginalOrdinal.clear(); } public void setFocusables(ArrayList<View> focusables) { @@ -755,6 +799,10 @@ public class FocusFinder { setHeadOfChain(view); } } + + for (int i = 0; i < focusables.size(); ++i) { + mOriginalOrdinal.put(focusables.get(i), i); + } } private void setHeadOfChain(View head) { @@ -793,44 +841,22 @@ public class FocusFinder { return 1; // first is end of chain } } + boolean involvesChain = false; if (firstHead != null) { first = firstHead; + involvesChain = true; } if (secondHead != null) { second = secondHead; + involvesChain = true; } - // First see if they belong to the same focus chain. - getRect(first, mFirstRect); - getRect(second, mSecondRect); - - if (mFirstRect.top < mSecondRect.top) { - return -1; - } else if (mFirstRect.top > mSecondRect.top) { - return 1; - } else if (mFirstRect.left < mSecondRect.left) { - return mIsLayoutRtl ? 1 : -1; - } else if (mFirstRect.left > mSecondRect.left) { - return mIsLayoutRtl ? -1 : 1; - } else if (mFirstRect.bottom < mSecondRect.bottom) { - return -1; - } else if (mFirstRect.bottom > mSecondRect.bottom) { - return 1; - } else if (mFirstRect.right < mSecondRect.right) { - return mIsLayoutRtl ? 1 : -1; - } else if (mFirstRect.right > mSecondRect.right) { - return mIsLayoutRtl ? -1 : 1; + if (involvesChain) { + // keep original order between chains + return mOriginalOrdinal.get(first) < mOriginalOrdinal.get(second) ? -1 : 1; } else { - // The view are distinct but completely coincident so we consider - // them equal for our purposes. Since the sort is stable, this - // means that the views will retain their layout order relative to one another. return 0; } } - - private void getRect(View view, Rect rect) { - view.getDrawingRect(rect); - mRoot.offsetDescendantRectToMyCoords(view, rect); - } } } diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index d59be02c7371..2fe98c0b6f05 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -16,8 +16,6 @@ package android.view; -import android.graphics.Rect; - /** * An interface to the PinnedStackController to update it of state changes, and to query * information based on the current state. @@ -27,17 +25,7 @@ import android.graphics.Rect; interface IPinnedStackController { /** - * Notifies the controller that the user is currently interacting with the PIP. - */ - oneway void setInInteractiveMode(boolean inInteractiveMode); - - /** - * Notifies the controller that the PIP is currently minimized. + * Notifies the controller that the PiP is currently minimized. */ oneway void setIsMinimized(boolean isMinimized); - - /** - * Notifies the controller that the desired snap mode is to the closest edge. - */ - oneway void setSnapToEdge(boolean snapToEdge); } diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl index 3c348c50369f..c7340bfa329e 100644 --- a/core/java/android/view/IPinnedStackListener.aidl +++ b/core/java/android/view/IPinnedStackListener.aidl @@ -17,6 +17,7 @@ package android.view; import android.content.pm.ParceledListSlice; +import android.graphics.Rect; import android.view.IPinnedStackController; /** @@ -33,24 +34,28 @@ oneway interface IPinnedStackListener { void onListenerRegistered(IPinnedStackController controller); /** - * Called when window manager decides to adjust the pinned stack bounds, or when the listener - * is first registered to allow the listener to synchronized its state with the controller. + * Called when the window manager has detected a change that would cause the movement bounds + * to be changed (ie. after configuration change, aspect ratio change, etc). It then provides + * the components that allow the listener to calculate the movement bounds itself. The + * {@param normalBounds} are also the default bounds that the PiP would be entered in its + * current state with the aspect ratio applied. */ - void onBoundsChanged(boolean adjustedForIme); + void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, + boolean fromImeAdjustement); /** - * Called when window manager decides to adjust the minimized state, or when the listener - * is first registered to allow the listener to synchronized its state with the controller. + * Called when window manager decides to adjust the pinned stack bounds because of the IME, or + * when the listener is first registered to allow the listener to synchronized its state with + * the controller. This call will always be followed by a onMovementBoundsChanged() call + * with fromImeAdjustement set to true. */ - void onMinimizedStateChanged(boolean isMinimized); + void onImeVisibilityChanged(boolean imeVisible, int imeHeight); /** - * Called when window manager decides to adjust the snap-to-edge state, which determines whether - * to snap only to the corners of the screen or to the closest edge. It is called when the - * listener is first registered to allow the listener to synchronized its state with the - * controller. + * Called when window manager decides to adjust the minimized state, or when the listener + * is first registered to allow the listener to synchronized its state with the controller. */ - void onSnapToEdgeStateChanged(boolean isSnapToEdge); + void onMinimizedStateChanged(boolean isMinimized); /** * Called when the set of actions for the current PiP activity changes, or when the listener diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index c789f8c16324..dd76fcff6ec8 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -337,16 +337,6 @@ interface IWindowManager void registerPinnedStackListener(int displayId, IPinnedStackListener listener); /** - * Returns the initial bounds that PIP will be shown when it is first started. - */ - Rect getPictureInPictureDefaultBounds(int displayId); - - /** - * Returns the bounds that the PIP can move on the screen in the current PIP state. - */ - Rect getPictureInPictureMovementBounds(int displayId); - - /** * Updates the dim layer used while resizing. * * @param visible Whether the dim layer should be visible. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a150529cc66e..ee979844bd20 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6424,9 +6424,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (isAutoFillable()) { AutoFillManager afm = getAutoFillManager(); if (afm != null) { - afm.updateAutoFillInput(this, gainFocus - ? AutoFillManager.FLAG_UPDATE_UI_SHOW - : AutoFillManager.FLAG_UPDATE_UI_HIDE); + afm.focusChanged(this, gainFocus); } } @@ -6916,10 +6914,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (forAutoFill) { - // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to - // reuse the accessibility id to save space. - structure.setAutoFillId(getAccessibilityViewId()); - structure.setAutoFillType(getAutoFillType()); + final AutoFillType autoFillType = getAutoFillType(); + // Don't need to fill auto-fill info if view does not support it. + // For example, only TextViews that are editable support auto-fill + if (autoFillType != null) { + // The auto-fill id needs to be unique, but its value doesn't matter, so it's better + // to reuse the accessibility id to save space. + structure.setAutoFillId(getAccessibilityViewId()); + structure.setAutoFillType(autoFillType); + structure.setAutoFillValue(getAutoFillValue()); + } } structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop); @@ -7015,16 +7019,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * hierachy on {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}. */ @Nullable - public VirtualViewDelegate getAutoFillVirtualViewDelegate( - @SuppressWarnings("unused") VirtualViewDelegate.Callback callback) { + public VirtualViewDelegate getAutoFillVirtualViewDelegate() { return null; } /** * Automatically fills the content of this view with the {@code value}. * - * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()} to - * support the AutoFill Framework. + * <p>By default does nothing, but views should override it (and {@link #getAutoFillType() + * and #getAutoFillValue()} to support the AutoFill Framework. * * <p>Typically, it is implemented by: * @@ -7058,6 +7061,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return null; } + /** + * Gets the {@link View}'s current auto-fill value. + * + * <p>By default returns {@code null}, but views should override it, + * {@link #autoFill(AutoFillValue)}, and {@link #getAutoFillType()} to support the AutoFill + * Framework. + */ + @Nullable + public AutoFillValue getAutoFillValue() { + return null; + } + @Nullable private AutoFillManager getAutoFillManager() { return mContext.getSystemService(AutoFillManager.class); @@ -7318,6 +7333,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the + * additional data. + * <p> + * This method only needs overloading if the node is marked as having extra data available. + * </p> + * + * @param info The info to which to add the extra data + * @param extraDataKey A key specifying the type of extra data to add to the info. The + * extra data should be added to the {@link Bundle} returned by + * the info's {@link AccessibilityNodeInfo#getExtras} method. + * @param arguments A {@link Bundle} holding any arguments relevant for this request. + * + * @see AccessibilityNodeInfo#setExtraAvailableData + */ + public void addExtraDataToAccessibilityNodeInfo( + AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) { + } + + /** * Determine the order in which this view will be drawn relative to its siblings for a11y * * @param info The info whose drawing order should be populated @@ -24319,6 +24353,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the + * additional data. + * <p> + * This method only needs to be implemented if the View offers to provide additional data. + * </p> + * <p> + * The default implementation behaves as + * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for + * the case where no accessibility delegate is set. + * </p> + * + * @param host The View hosting the delegate. + * @param info The info to which to add the extra data + * @param extraDataKey A key specifying the type of extra data to add to the info. The + * extra data should be added to the {@link Bundle} returned by + * the info's {@link AccessibilityNodeInfo#getExtras} method. + * @param arguments A {@link Bundle} holding any arguments relevant for this request. + * + * @see AccessibilityNodeInfo#setExtraAvailableData + */ + public void addExtraDataToAccessibilityNodeInfo( + View host, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) { + host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments); + } + + /** * Called when a child of the host View has requested sending an * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) * to augment the event. diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index aa580fae1cea..36beaaae864a 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -60,6 +60,7 @@ import com.android.internal.R; import com.android.internal.util.Predicate; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -1140,31 +1141,42 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final int focusableCount = views.size(); final int descendantFocusability = getDescendantFocusability(); + final boolean focusSelf = (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen()); - if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { - if (shouldBlockFocusForTouchscreen()) { - focusableMode |= FOCUSABLES_TOUCH_MODE; + if (descendantFocusability == FOCUS_BLOCK_DESCENDANTS) { + if (focusSelf) { + super.addFocusables(views, direction, focusableMode); } + return; + } - final int count = mChildrenCount; - final View[] children = mChildren; + if (shouldBlockFocusForTouchscreen()) { + focusableMode |= FOCUSABLES_TOUCH_MODE; + } - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - child.addFocusables(views, direction, focusableMode); - } + if ((descendantFocusability == FOCUS_BEFORE_DESCENDANTS) && focusSelf) { + super.addFocusables(views, direction, focusableMode); + } + + int count = 0; + final View[] children = new View[mChildrenCount]; + for (int i = 0; i < mChildrenCount; ++i) { + View child = mChildren[i]; + if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { + children[count++] = child; } } + Arrays.sort(children, 0, count, FocusFinder.getFocusComparator(this, false)); + for (int i = 0; i < count; ++i) { + children[i].addFocusables(views, direction, focusableMode); + } - // we add ourselves (if focusable) in all cases except for when we are - // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is + // When set to FOCUS_AFTER_DESCENDANTS, we only add ourselves if + // there aren't any focusable descendants. this is // to avoid the focus search finding layouts when a more precise search // among the focusable children would be more interesting. - if ((descendantFocusability != FOCUS_AFTER_DESCENDANTS - // No focusable descendants - || (focusableCount == views.size())) && - (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())) { + if ((descendantFocusability == FOCUS_AFTER_DESCENDANTS) && focusSelf + && focusableCount == views.size()) { super.addFocusables(views, direction, focusableMode); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9bfc2600d0e1..9e8dda8389bf 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -7492,13 +7492,13 @@ public final class ViewRootImpl implements ViewParent, public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, Bundle args) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId, interactiveRegion, interactionId, callback, flags, interrogatingPid, - interrogatingTid, spec); + interrogatingTid, spec, args); } else { // We cannot make the call and notify the caller so it does not wait. try { diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index db2ea483f3ab..143c49a7db7e 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -554,7 +554,7 @@ public final class AccessibilityCache { // Layer of indirection included to break dependency chain for testing public static class AccessibilityNodeRefresher { public boolean refreshNode(AccessibilityNodeInfo info, boolean bypassCache) { - return info.refresh(bypassCache); + return info.refresh(null, bypassCache); } } } diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java index 1543597efe10..828583cdfe81 100644 --- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java +++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java @@ -159,7 +159,7 @@ public final class AccessibilityInteractionClient public AccessibilityNodeInfo getRootInActiveWindow(int connectionId) { return findAccessibilityNodeInfoByAccessibilityId(connectionId, AccessibilityNodeInfo.ACTIVE_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, - false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS); + false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS, null); } /** @@ -259,7 +259,7 @@ public final class AccessibilityInteractionClient */ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId, int accessibilityWindowId, long accessibilityNodeId, boolean bypassCache, - int prefetchFlags) { + int prefetchFlags, Bundle arguments) { if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0 && (prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) == 0) { throw new IllegalArgumentException("FLAG_PREFETCH_SIBLINGS" @@ -285,9 +285,8 @@ public final class AccessibilityInteractionClient final long identityToken = Binder.clearCallingIdentity(); final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId( accessibilityWindowId, accessibilityNodeId, interactionId, this, - prefetchFlags, Thread.currentThread().getId()); + prefetchFlags, Thread.currentThread().getId(), arguments); Binder.restoreCallingIdentity(identityToken); - // If the scale is zero the call has failed. if (success) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 56d45b097272..b0a11cd5b8e9 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -16,6 +16,8 @@ package android.view.accessibility; +import static java.util.Collections.EMPTY_LIST; + import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.Nullable; @@ -517,6 +519,46 @@ public class AccessibilityNodeInfo implements Parcelable { */ public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010; + /** + * Key used to request and locate extra data for text character location. This key requests that + * an array of {@link android.graphics.RectF}s be added to the extras. This request is made with + * {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by this request are two + * integers: {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and + * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index must be valid + * inside the CharSequence returned by {@link #getText()}, and the length must be positive. + * <p> + * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this + * string as a key for {@link Bundle#getParcelableArray(String)}. The + * {@link android.graphics.RectF} will be null for characters that either do not exist or are + * off the screen. + * + * {@see #refreshWithExtraData(String, Bundle)} + */ + public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = + "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; + + /** + * Integer argument specifying the start index of the requested text location data. Must be + * valid inside the CharSequence returned by {@link #getText()}. + * + * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} + */ + public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = + "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX"; + + /** + * Integer argument specifying the end index of the requested text location data. Must be + * positive. + * + * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} + */ + public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = + "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH"; + + /** @hide */ + public static final String EXTRA_DATA_REQUESTED_KEY = + "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested"; + // Boolean attributes. private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001; @@ -651,6 +693,7 @@ public class AccessibilityNodeInfo implements Parcelable { private CharSequence mError; private CharSequence mContentDescription; private String mViewIdResourceName; + private ArrayList<String> mExtraDataKeys; private LongArray mChildNodeIds; private ArrayList<AccessibilityAction> mActions; @@ -786,14 +829,14 @@ public class AccessibilityNodeInfo implements Parcelable { * * @hide */ - public boolean refresh(boolean bypassCache) { + public boolean refresh(Bundle arguments, boolean bypassCache) { enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return false; } AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId( - mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0); + mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments); if (refreshedInfo == null) { return false; } @@ -804,15 +847,33 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Refreshes this info with the latest state of the view it represents. - * <p> - * <strong>Note:</strong> If this method returns false this info is obsolete - * since it represents a view that is no longer in the view tree and should - * be recycled. - * </p> - * @return Whether the refresh succeeded. + * + * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented + * by this node is no longer in the view tree (and thus this node is obsolete and should be + * recycled). */ public boolean refresh() { - return refresh(true); + return refresh(null, true); + } + + /** + * Refreshes this info with the latest state of the view it represents, and request new + * data be added by the View. + * + * @param extraDataKey A bitmask of the extra data requested. Data that must be requested + * with this mechanism is generally expensive to retrieve, so should only be + * requested when needed. See + * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and + * {@link #getAvailableExtraData()}. + * @param args A bundle of arguments for the request. These depend on the particular request. + * + * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented + * by this node is no longer in the view tree (and thus this node is obsolete and should be + * recycled). + */ + public boolean refreshWithExtraData(String extraDataKey, Bundle args) { + args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey); + return refresh(args, true); } /** @@ -872,7 +933,7 @@ public class AccessibilityNodeInfo implements Parcelable { final long childId = mChildNodeIds.get(index); AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId, - childId, false, FLAG_PREFETCH_DESCENDANTS); + childId, false, FLAG_PREFETCH_DESCENDANTS, null); } /** @@ -1263,6 +1324,45 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Get the extra data available for this node. + * <p> + * Some data that is useful for some accessibility services is expensive to compute, and would + * place undue overhead on apps to compute all the time. That data can be requested with + * {@link #refreshWithExtraData(String, Bundle)}. + * + * @return An unmodifiable list of keys corresponding to extra data that can be requested. + * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY + */ + public List<String> getAvailableExtraData() { + if (mExtraDataKeys != null) { + return Collections.unmodifiableList(mExtraDataKeys); + } else { + return EMPTY_LIST; + } + } + + /** + * Set the extra data available for this node. + * <p> + * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that + * it will populate the node's extras with corresponding pieces of information in + * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * + * @param extraDataKeys A list of types of extra data that are available. + * @see #getAvailableExtraData() + * + * @throws IllegalStateException If called from an AccessibilityService. + */ + public void setAvailableExtraData(List<String> extraDataKeys) { + enforceNotSealed(); + mExtraDataKeys = new ArrayList<>(extraDataKeys); + } + + /** * Sets the maximum text length, or -1 for no limit. * <p> * Typically used to indicate that an editable text field has a limit on @@ -2658,6 +2758,14 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Check if a node has an extras bundle + * @hide + */ + public boolean hasExtras() { + return mExtras != null; + } + + /** * Gets the value of a boolean property. * * @param property The property. @@ -2955,6 +3063,12 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeInt(mInputType); parcel.writeInt(mLiveRegion); parcel.writeInt(mDrawingOrderInParent); + if (mExtraDataKeys != null) { + parcel.writeInt(1); + parcel.writeStringList(mExtraDataKeys); + } else { + parcel.writeInt(0); + } if (mExtras != null) { parcel.writeInt(1); @@ -3054,6 +3168,8 @@ public class AccessibilityNodeInfo implements Parcelable { mInputType = other.mInputType; mLiveRegion = other.mLiveRegion; mDrawingOrderInParent = other.mDrawingOrderInParent; + mExtraDataKeys = other.mExtraDataKeys; + if (other.mExtras != null) { mExtras = new Bundle(other.mExtras); } else { @@ -3137,6 +3253,12 @@ public class AccessibilityNodeInfo implements Parcelable { mDrawingOrderInParent = parcel.readInt(); if (parcel.readInt() == 1) { + mExtraDataKeys = parcel.createStringArrayList(); + } else { + mExtraDataKeys = null; + } + + if (parcel.readInt() == 1) { mExtras = parcel.readBundle(); } else { mExtras = null; @@ -3455,7 +3577,7 @@ public class AccessibilityNodeInfo implements Parcelable { AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null); } /** diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java index abcbb7044de8..722b659e8fdc 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java +++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java @@ -102,6 +102,27 @@ public abstract class AccessibilityNodeProvider { } /** + * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the + * additional data. + * <p> + * This method only needs to be implemented if a virtual view offers to provide additional + * data. + * </p> + * + * @param virtualViewId The virtual view id used to create the node + * @param info The info to which to add the extra data + * @param extraDataKey A key specifying the type of extra data to add to the info. The + * extra data should be added to the {@link Bundle} returned by + * the info's {@link AccessibilityNodeInfo#getExtras} method. + * @param arguments A {@link Bundle} holding any arguments relevant for this request. + * + * @see AccessibilityNodeInfo#setExtraAvailableData + */ + public void addExtraDataToAccessibilityNodeInfo( + int virtualViewId, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) { + } + + /** * Performs an accessibility action on a virtual view, i.e. a descendant of the * host View, with the given <code>virtualViewId</code> or the host View itself * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index 3287298c5a6b..c3904060247a 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -183,7 +183,7 @@ public final class AccessibilityWindowInfo implements Parcelable { AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mId, AccessibilityNodeInfo.ROOT_NODE_ID, - true, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS); + true, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS, null); } /** @@ -209,7 +209,7 @@ public final class AccessibilityWindowInfo implements Parcelable { AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mParentId, mAnchorId, true, 0); + mParentId, mAnchorId, true, 0, null); } /** diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl index cecc4af49e2e..4c0fdfd5afdf 100644 --- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl +++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl @@ -33,7 +33,8 @@ oneway interface IAccessibilityInteractionConnection { void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, in MagnificationSpec spec); + int interrogatingPid, long interrogatingTid, in MagnificationSpec spec, + in Bundle arguments); void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java index 147d72a09f14..58607ba51579 100644 --- a/core/java/android/view/autofill/AutoFillManager.java +++ b/core/java/android/view/autofill/AutoFillManager.java @@ -16,11 +16,12 @@ package android.view.autofill; -import static android.view.autofill.Helper.DEBUG; +import static android.view.autofill.Helper.VERBOSE; import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; +import android.os.IBinder; import android.os.RemoteException; import android.service.autofill.IAutoFillManagerService; import android.util.Log; @@ -30,94 +31,181 @@ import android.view.View; * App entry point to the AutoFill Framework. */ // TODO(b/33197203): improve this javadoc +//TODO(b/33197203): restrict manager calls to activity public final class AutoFillManager { private static final String TAG = "AutoFillManager"; - /** - * Flag used to show the auto-fill UI affordance for a view. - */ - public static final int FLAG_UPDATE_UI_SHOW = 0x1; - - /** - * Flag used to hide the auto-fill UI affordance for a view. - */ - public static final int FLAG_UPDATE_UI_HIDE = 0x2; + /** @hide */ public static final int FLAG_START_SESSION = 0x1; + /** @hide */ public static final int FLAG_FOCUS_GAINED = 0x2; + /** @hide */ public static final int FLAG_FOCUS_LOST = 0x4; + /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x8; private final IAutoFillManagerService mService; + private final Context mContext; + + private AutoFillSession mSession; /** * @hide */ - public AutoFillManager(@SuppressWarnings("unused") Context context, - IAutoFillManagerService service) { + public AutoFillManager(Context context, IAutoFillManagerService service) { + mContext = context; mService = service; } /** - * Updates the auto-fill bar for a given {@link View}. - * - * <b>Typically called twice, with different flags ({@link #FLAG_UPDATE_UI_SHOW} and - * {@link #FLAG_UPDATE_UI_HIDE} respectively), as the user "entered" and "exited" a view. + * Called to indicate the focus on an auto-fillable {@link View} changed. * - * @param view view to be updated. - * @param flags either {@link #FLAG_UPDATE_UI_SHOW} or - * {@link #FLAG_UPDATE_UI_HIDE}. + * @param view view whose focus changed. + * @param gainFocus whether focus was gained or lost. */ - public void updateAutoFillInput(View view, int flags) { + public void focusChanged(View view, boolean gainFocus) { + if (mSession == null) { + // Starts new session. + final Rect bounds = new Rect(); + view.getBoundsOnScreen(bounds); + final AutoFillId id = getAutoFillId(view); + final AutoFillValue value = view.getAutoFillValue(); + startSession(id, bounds, value); + return; + } + + if (!mSession.isEnabled()) { + // Auto-fill is disabled for this session. + return; + } + + // Update focus on existing session. final Rect bounds = new Rect(); view.getBoundsOnScreen(bounds); + final AutoFillId id = getAutoFillId(view); + final AutoFillValue value = view.getAutoFillValue(); + updateSession(id, bounds, value, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST); + } - requestAutoFill(getAutoFillId(view), bounds, flags); + /** + * Called to indicate the focus on an auto-fillable virtual {@link View} changed. + * + * @param parent parent view whose focus changed. + * @param childId id identifying the virtual child inside the parent view. + * @param bounds child boundaries, relative to the top window. + * @param gainFocus whether focus was gained or lost. + */ + public void virtualFocusChanged(View parent, int childId, Rect bounds, boolean gainFocus) { + if (mSession == null) { + // Starts new session. + final AutoFillId id = getAutoFillId(parent, childId); + startSession(id, bounds, null); + return; + } + + if (!mSession.isEnabled()) { + // Auto-fill is disabled for this session. + return; + } + + // Update focus on existing session. + final AutoFillId id = getAutoFillId(parent, childId); + updateSession(id, bounds, null, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST); } /** - * Updates the auto-fill bar for a virtual child of a given {@link View}. + * Called to indicate the value of an auto-fillable {@link View} changed. * - * <b>Typically called twice, with different flags ({@link #FLAG_UPDATE_UI_SHOW} and - * {@link #FLAG_UPDATE_UI_HIDE} respectively), as the user "entered" and "exited" a view. + * @param view view whose focus changed. + */ + public void valueChanged(View view) { + if (mSession == null) return; + + final AutoFillId id = getAutoFillId(view); + final AutoFillValue value = view.getAutoFillValue(); + updateSession(id, null, value, FLAG_VALUE_CHANGED); + } + + + /** + * Called to indicate the value of an auto-fillable virtual {@link View} changed. * - * @param parent parent view. + * @param parent parent view whose value changed. * @param childId id identifying the virtual child inside the parent view. - * @param bounds absolute boundaries of the child in the window (could be {@code null} when - * flag is {@link #FLAG_UPDATE_UI_HIDE}. - * @param flags either {@link #FLAG_UPDATE_UI_SHOW} or - * {@link #FLAG_UPDATE_UI_HIDE}. + * @param value new value of the child. */ - public void updateAutoFillInput(View parent, int childId, @Nullable Rect bounds, - int flags) { - requestAutoFill(new AutoFillId(parent.getAccessibilityViewId(), childId), bounds, flags); + public void virtualValueChanged(View parent, int childId, AutoFillValue value) { + if (mSession == null) return; + + final AutoFillId id = getAutoFillId(parent, childId); + updateSession(id, null, value, FLAG_VALUE_CHANGED); } /** - * Notifies the framework that the value of a view changed. - * @param view view whose value was updated - * @param value new value. + * Called to indicate the current auto-fill context should be reset. + * + * <p>For example, when a virtual view is rendering an {@code HTML} page with a form, it should + * call this method after the form is submitted and another page is rendered. */ - public void onValueChanged(View view, AutoFillValue value) { - // TODO(b/33197203): optimize it by not calling service when the view does not belong to - // the session. - final AutoFillId id = getAutoFillId(view); - if (DEBUG) Log.v(TAG, "onValueChanged(): id=" + id + ", value=" + value); + public void reset() { + if (mSession == null) return; + + final IBinder activityToken = mSession.mToken.get(); + if (activityToken == null) { + Log.wtf(TAG, "finishSession(): token already GC'ed"); + return; + } try { - mService.onValueChanged(id, value); + mService.finishSession(activityToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } finally { + mSession = null; } } + /** + * Gets the current session, if any. + * + * @hide + */ + @Nullable + public AutoFillSession getSession() { + return mSession; + } + private AutoFillId getAutoFillId(View view) { return new AutoFillId(view.getAccessibilityViewId()); } - private void requestAutoFill(AutoFillId id, Rect bounds, int flags) { - // TODO(b/33197203): optimize it by not calling service when the view does not belong to - // the session. - if (DEBUG) { - Log.v(TAG, "requestAutoFill(): id=" + id + ", bounds=" + bounds + ", flags=" + flags); + private AutoFillId getAutoFillId(View parent, int childId) { + return new AutoFillId(parent.getAccessibilityViewId(), childId); + } + + private void startSession(AutoFillId id, Rect bounds, AutoFillValue value) { + if (VERBOSE) { + Log.v(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value); + } + + final IBinder activityToken = mContext.getActivityToken(); + mSession = new AutoFillSession(this, activityToken); + final IBinder appCallback = mSession.getCallback().asBinder(); + try { + mService.startSession(activityToken, appCallback, id, bounds, value); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private void updateSession(AutoFillId id, Rect bounds, AutoFillValue value, int flags) { + if (VERBOSE) { + Log.v(TAG, "updateSession(): id=" + id + ", bounds=" + bounds + ", value=" + value + + ", flags=" + flags); + } + + final IBinder activityToken = mSession.mToken.get(); + if (activityToken == null) { + return; } try { - mService.requestAutoFill(id, bounds, flags); + mService.updateSession(activityToken, id, bounds, value, flags); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/view/autofill/AutoFillSession.java b/core/java/android/view/autofill/AutoFillSession.java index efc1df6c6e84..e10ba373cf40 100644 --- a/core/java/android/view/autofill/AutoFillSession.java +++ b/core/java/android/view/autofill/AutoFillSession.java @@ -21,12 +21,11 @@ import static android.view.autofill.Helper.DEBUG; import android.app.Activity; import android.content.Intent; import android.content.IntentSender; +import android.os.IBinder; import android.service.autofill.IAutoFillAppCallback; import android.util.Log; import android.view.View; -import com.android.internal.annotations.GuardedBy; - import java.lang.ref.WeakReference; /** @@ -39,6 +38,14 @@ public final class AutoFillSession { private static final String TAG = "AutoFillSession"; private final IAutoFillAppCallback mCallback = new IAutoFillAppCallback.Stub() { + + @Override + public void enableSession() { + if (DEBUG) Log.d(TAG, "enableSession()"); + + mEnabled = true; + } + @Override public void autoFill(Dataset dataset) { final Activity activity = mActivity.get(); @@ -64,10 +71,8 @@ public final class AutoFillSession { // TODO(b/33197203): handle protected value (like credit card) if (id.isVirtual()) { // Delegate virtual fields. - setAutoFillDelegateCallback(); final VirtualViewDelegate delegate = view - .getAutoFillVirtualViewDelegate( - mAutoFillDelegateCallback); + .getAutoFillVirtualViewDelegate(); if (delegate == null) { Log.w(TAG, "autoFill(): cannot fill virtual " + id + "; no VirtualViewDelegate for view " @@ -102,29 +107,60 @@ public final class AutoFillSession { } }; - private final WeakReference<Activity> mActivity; + private final AutoFillManager mAfm; + private WeakReference<Activity> mActivity; - @GuardedBy("this") - private VirtualViewDelegate.Callback mAutoFillDelegateCallback; + // Reference to the token, which is used by the server. + final WeakReference<IBinder> mToken; - public AutoFillSession(Activity activity) { + private boolean mEnabled; + + public AutoFillSession(AutoFillManager afm, IBinder token) { + mToken = new WeakReference<>(token); + mAfm = afm; + } + + /** + * Called by the {@link Activity} when it was asked to provider auto-fill data. + */ + public void attachActivity(Activity activity) { + if (mActivity != null) { + Log.w(TAG, "attachActivity(): already attached"); + return; + } mActivity = new WeakReference<>(activity); } - public IAutoFillAppCallback getCallback() { - return mCallback; + /** + * Checks whether auto-fill is enabled for this session, as decided by the + * {@code AutoFillManagerService}. + */ + public boolean isEnabled() { + return mEnabled; } /** - * Lazily sets the {@link #mAutoFillDelegateCallback}. + * Notifies the manager that a session finished. */ - private void setAutoFillDelegateCallback() { - synchronized (this) { - if (mAutoFillDelegateCallback == null) { - mAutoFillDelegateCallback = new VirtualViewDelegate.Callback() { - // TODO(b/33197203): implement - }; + // TODO(b/33197203): hook it to other lifecycle events like fragments transition + public void finishSession() { + if (mAfm != null) { + try { + mAfm.reset(); + } catch (RuntimeException e) { + Log.w(TAG, "Failed to finish session for " + mToken.get() + ": " + e); } } } + + public IAutoFillAppCallback getCallback() { + return mCallback; + } + + @Override + public String toString() { + if (!DEBUG) return super.toString(); + + return "AutoFillSession[activityoken=" + mToken.get() + "]"; + } } diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java index 57b23ef4976e..b31f4aff2b1c 100644 --- a/core/java/android/view/autofill/AutoFillValue.java +++ b/core/java/android/view/autofill/AutoFillValue.java @@ -18,6 +18,7 @@ package android.view.autofill; import static android.view.autofill.Helper.DEBUG; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.view.View; @@ -32,12 +33,12 @@ import android.view.View; */ public final class AutoFillValue implements Parcelable { - private final CharSequence mText; + private final String mText; private final int mListIndex; private final boolean mToggle; private AutoFillValue(CharSequence text, int listIndex, boolean toggle) { - mText = text; + mText = (text == null) ? null : text.toString(); mListIndex = listIndex; mToggle = toggle; } @@ -74,6 +75,32 @@ public final class AutoFillValue implements Parcelable { ///////////////////////////////////// @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + mListIndex; + result = prime * result + ((mText == null) ? 0 : mText.hashCode()); + result = prime * result + (mToggle ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + final AutoFillValue other = (AutoFillValue) obj; + if (mListIndex != other.mListIndex) return false; + if (mText == null) { + if (other.mText != null) return false; + } else { + if (!mText.equals(other.mText)) return false; + } + if (mToggle != other.mToggle) return false; + return true; + } + + @Override public String toString() { if (!DEBUG) return super.toString(); @@ -92,13 +119,13 @@ public final class AutoFillValue implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeCharSequence(mText); + parcel.writeString(mText); parcel.writeInt(mListIndex); parcel.writeInt(mToggle ? 1 : 0); } private AutoFillValue(Parcel parcel) { - mText = parcel.readCharSequence(); + mText = parcel.readString(); mListIndex = parcel.readInt(); mToggle = parcel.readInt() == 1; } @@ -127,8 +154,9 @@ public final class AutoFillValue implements Parcelable { * <p>See {@link AutoFillType#isText()} for more info. */ // TODO(b/33197203): use cache - public static AutoFillValue forText(CharSequence value) { - return new AutoFillValue(value, 0, false); + @Nullable + public static AutoFillValue forText(@Nullable CharSequence value) { + return value == null ? null : new AutoFillValue(value, 0, false); } /** diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java index 14cf9e883862..a9844d7f0b47 100644 --- a/core/java/android/view/autofill/Helper.java +++ b/core/java/android/view/autofill/Helper.java @@ -26,6 +26,7 @@ import java.util.Set; public final class Helper { static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable + static final boolean VERBOSE = false; static final String REDACTED = "[REDACTED]"; static StringBuilder append(StringBuilder builder, Bundle bundle) { diff --git a/core/java/android/view/autofill/VirtualViewDelegate.java b/core/java/android/view/autofill/VirtualViewDelegate.java index e465c679e5f7..3dda7f7d2782 100644 --- a/core/java/android/view/autofill/VirtualViewDelegate.java +++ b/core/java/android/view/autofill/VirtualViewDelegate.java @@ -15,9 +15,6 @@ */ package android.view.autofill; -import android.annotation.Nullable; -import android.graphics.Rect; -import android.util.Log; import android.view.View; import android.view.ViewStructure; @@ -33,7 +30,7 @@ import android.view.ViewStructure; * class. * * <p>Objects of this class are typically created by overriding - * {@link View#getAutoFillVirtualViewDelegate(Callback)} and saving the passed callback, which must + * {@link View#getAutoFillVirtualViewDelegate()} and saving the passed callback, which must * be notified upon changes on the hierarchy. * * <p>The main use case of these API is to enable custom views that draws its content - such as @@ -43,82 +40,22 @@ import android.view.ViewStructure; * <li>Client populates the virtual hierarchy on * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)} * <li>Android System generates the proper {@link AutoFillId} - encapsulating the view and the - * virtual node ids - and pass it to the {@link android.service.autofill.AutoFillService}. + * virtual child ids - and pass it to the {@link android.service.autofill.AutoFillService}. * <li>The service uses the {@link AutoFillId} to populate the auto-fill {@link Dataset}s and pass * it back to the Android System. * <li>Android System uses the {@link AutoFillId} to find the proper custom view and calls * {@link #autoFill(int, AutoFillValue)} on that view passing the virtual id. - * <li>This provider than finds the node in the hierarchy and auto-fills it. + * <li>This provider than finds the child in the hierarchy and auto-fills it. * </ol> * */ public abstract class VirtualViewDelegate { - // TODO(b/33197203): set to false once stable - private static final boolean DEBUG = true; - - private static final String TAG = "VirtualViewDelegate"; - /** * Auto-fills a virtual view with the {@code value}. * - * @param virtualId id identifying the virtual node inside the custom view. + * @param virtualId id identifying the virtual child inside the custom view. * @param value value to be auto-filled. */ public abstract void autoFill(int virtualId, AutoFillValue value); - - /** - * Callback used to notify the AutoFill Framework of changes made on the view hierarchy while - * an {@link android.app.Activity} is being auto filled. - */ - public abstract static class Callback { - - /** - * Sent when the auto-fill bar for a child must be updated. - * - * See {@link AutoFillManager#updateAutoFillInput(View, int, android.graphics.Rect, int)} - * for more details. - */ - // TODO(b/33197203): do we really need it, or should the parent view just call - // AutoFillManager.updateAutoFillInput() directly? - public void onAutoFillInputUpdated(int virtualId, @Nullable Rect boundaries, int flags) { - if (DEBUG) { - Log.v(TAG, "onAutoFillInputUpdated(): virtualId=" + virtualId + ", boundaries=" - + boundaries + ", flags=" + flags); - } - } - - /** - * Sent when the value of a node was changed. - * - * <p>This method should only be called when the change was not caused by the AutoFill - * Framework itselft (i.e, through {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}, - * but by external causes (for example, when the user changed the value through the view's - * UI). - * - * @param virtualId id of the node whose value changed. - */ - public void onValueChanged(int virtualId) { - if (DEBUG) Log.d(TAG, "onValueChanged() for" + virtualId); - } - - /** - * Sent when nodes were removed (or had their ids changed) after the hierarchy has been - * committed to - * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)}. - * - * <p>For example, when the view is rendering an {@code HTML} page, it should call this - * method when: - * <ul> - * <li>User navigated to another page and some (or all) nodes are gone. - * <li>The page's {@code DOM} was changed by {@code JavaScript} and some nodes moved (and - * are now identified by different ids). - * </ul> - * - * @param virtualIds id of the nodes that were removed. - */ - public void onNodeRemoved(int... virtualIds) { - if (DEBUG) Log.d(TAG, "onNodeRemoved(): " + virtualIds); - } - } } diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java index a85dea9e96bc..a4e524f9882b 100644 --- a/core/java/android/view/textclassifier/TextClassificationManager.java +++ b/core/java/android/view/textclassifier/TextClassificationManager.java @@ -41,6 +41,9 @@ public final class TextClassificationManager { private static final String LOG_TAG = "TextClassificationManager"; + private final Object mTextClassifierLock = new Object(); + private final Object mLangIdLock = new Object(); + private final Context mContext; // TODO: Implement a way to close the file descriptor. private ParcelFileDescriptor mFd; @@ -55,19 +58,21 @@ public final class TextClassificationManager { /** * Returns the default text classifier. */ - public synchronized TextClassifier getDefaultTextClassifier() { - if (mDefault == null) { - try { - mFd = ParcelFileDescriptor.open( - new File("/etc/assistant/smart-selection.model"), - ParcelFileDescriptor.MODE_READ_ONLY); - mDefault = new TextClassifierImpl(mContext, mFd); - } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "Error accessing 'text classifier selection' model file.", e); - mDefault = TextClassifier.NO_OP; + public TextClassifier getDefaultTextClassifier() { + synchronized (mTextClassifierLock) { + if (mDefault == null) { + try { + mFd = ParcelFileDescriptor.open( + new File("/etc/assistant/smart-selection.model"), + ParcelFileDescriptor.MODE_READ_ONLY); + mDefault = new TextClassifierImpl(mContext, mFd); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "Error accessing 'text classifier selection' model file.", e); + mDefault = TextClassifier.NO_OP; + } } + return mDefault; } - return mDefault; } /** @@ -95,12 +100,14 @@ public final class TextClassificationManager { return Collections.emptyList(); } - private synchronized LangId getLanguageDetector() { - if (mLangId == null) { - // TODO: Use a file descriptor as soon as we start to depend on a model file - // for language detection. - mLangId = new LangId(0); + private LangId getLanguageDetector() { + synchronized (mLangIdLock) { + if (mLangId == null) { + // TODO: Use a file descriptor as soon as we start to depend on a model file + // for language detection. + mLangId = new LangId(0); + } + return mLangId; } - return mLangId; } } diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 783891838fe0..e2ff44cb3793 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -60,6 +60,8 @@ final class TextClassifierImpl implements TextClassifier { private static final String LOG_TAG = "TextClassifierImpl"; + private final Object mSmartSelectionLock = new Object(); + private final Context mContext; private final ParcelFileDescriptor mFd; private SmartSelection mSmartSelection; @@ -140,11 +142,13 @@ final class TextClassifierImpl implements TextClassifier { return TextClassifier.NO_OP.getLinks(text, linkMask); } - private synchronized SmartSelection getSmartSelection() throws FileNotFoundException { - if (mSmartSelection == null) { - mSmartSelection = new SmartSelection(mFd.getFd()); + private SmartSelection getSmartSelection() throws FileNotFoundException { + synchronized (mSmartSelectionLock) { + if (mSmartSelection == null) { + mSmartSelection = new SmartSelection(mFd.getFd()); + } + return mSmartSelection; } - return mSmartSelection; } private TextClassificationResult createClassificationResult(String type, CharSequence text) { diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 500f381e6bb8..6f687fe5f14c 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -32,7 +32,6 @@ import android.view.Gravity; import android.view.SoundEffectConstants; import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; -import android.view.ViewStructure; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.autofill.AutoFillType; @@ -562,17 +561,14 @@ public abstract class CompoundButton extends Button implements Checkable { stream.addProperty("checked", isChecked()); } - // TODO(b/33197203): add unit/CTS tests for auto-fill methods + // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable) - @Override - public void onProvideAutoFillStructure(ViewStructure structure, int flags) { - super.onProvideAutoFillStructure(structure, flags); - structure.setAutoFillValue(AutoFillValue.forToggle(isChecked())); - // TODO(b/33197203): add unit/CTS tests for auto-fill methods - } + // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener @Override public void autoFill(AutoFillValue value) { + if (!isEnabled()) return; + setChecked(value.getToggleValue()); } @@ -580,4 +576,9 @@ public abstract class CompoundButton extends Button implements Checkable { public AutoFillType getAutoFillType() { return AutoFillType.forToggle(); } + + @Override + public AutoFillValue getAutoFillValue() { + return isEnabled() ? null : AutoFillValue.forToggle(isChecked()); + } } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index a2cb491bbb7a..8cb2d23a0636 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -95,7 +95,6 @@ import android.view.View.OnClickListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.accessibility.AccessibilityNodeInfo; @@ -107,7 +106,6 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassificationResult; -import android.view.textclassifier.TextSelection; import android.widget.AdapterView.OnItemClickListener; import android.widget.TextView.Drawables; import android.widget.TextView.OnEditorActionListener; @@ -140,7 +138,6 @@ public class Editor { private static final boolean DEBUG_UNDO = false; static final int BLINK = 500; - private static final float[] TEMP_POSITION = new float[2]; private static final int DRAG_SHADOW_MAX_TEXT_LENGTH = 20; private static final float LINE_SLOP_MULTIPLIER_FOR_HANDLEVIEWS = 0.5f; private static final int UNSET_X_VALUE = -1; @@ -171,7 +168,7 @@ public class Editor { private InsertionPointCursorController mInsertionPointCursorController; SelectionModifierCursorController mSelectionModifierCursorController; // Action mode used when text is selected or when actions on an insertion cursor are triggered. - ActionMode mTextActionMode; + private ActionMode mTextActionMode; private boolean mInsertionControllerEnabled; private boolean mSelectionControllerEnabled; @@ -238,7 +235,7 @@ public class Editor { private boolean mPreserveSelection; private boolean mRestartActionModeOnNextRefresh; - private TextClassificationResult mTextClassificationResult; + private SelectionActionModeHelper mSelectionActionModeHelper; boolean mIsBeingLongClicked; @@ -294,7 +291,7 @@ public class Editor { private Rect mTempRect; - private TextView mTextView; + private final TextView mTextView; final ProcessTextIntentActionsHandler mProcessTextIntentActionsHandler; @@ -1032,46 +1029,6 @@ public class Editor { boolean parentPositionChanged, boolean parentScrolled); } - private boolean isPositionVisible(final float positionX, final float positionY) { - synchronized (TEMP_POSITION) { - final float[] position = TEMP_POSITION; - position[0] = positionX; - position[1] = positionY; - View view = mTextView; - - while (view != null) { - if (view != mTextView) { - // Local scroll is already taken into account in positionX/Y - position[0] -= view.getScrollX(); - position[1] -= view.getScrollY(); - } - - if (position[0] < 0 || position[1] < 0 || position[0] > view.getWidth() - || position[1] > view.getHeight()) { - return false; - } - - if (!view.getMatrix().isIdentity()) { - view.getMatrix().mapPoints(position); - } - - position[0] += view.getLeft(); - position[1] += view.getTop(); - - final ViewParent parent = view.getParent(); - if (parent instanceof View) { - view = (View) parent; - } else { - // We've reached the ViewRoot, stop iterating - view = null; - } - } - } - - // We've been able to walk up the view hierarchy and the position was never clipped - return true; - } - private boolean isOffsetVisible(int offset) { Layout layout = mTextView.getLayout(); if (layout == null) return false; @@ -1079,7 +1036,8 @@ public class Editor { final int line = layout.getLineForOffset(offset); final int lineBottom = layout.getLineBottom(line); final int primaryHorizontal = (int) layout.getPrimaryHorizontal(offset); - return isPositionVisible(primaryHorizontal + mTextView.viewportToContentHorizontalOffset(), + return mTextView.isPositionVisible( + primaryHorizontal + mTextView.viewportToContentHorizontalOffset(), lineBottom + mTextView.viewportToContentVerticalOffset()); } @@ -1891,7 +1849,7 @@ public class Editor { mInsertionPointCursorController.invalidateHandle(); } if (mTextActionMode != null) { - invalidateActionMode(getTextClassifierInfo(false)); + invalidateActionModeAsync(); } } @@ -1984,12 +1942,12 @@ public class Editor { if (mRestartActionModeOnNextRefresh) { // To avoid distraction, newly start action mode only when selection action // mode is being restarted. - startSelectionActionMode(null); + startSelectionActionMode(); } } else if (selectionController == null || !selectionController.isActive()) { // Insertion action mode is active. Avoid dismissing the selection. stopTextActionModeWithPreservingSelection(); - startSelectionActionMode(null); + startSelectionActionMode(); } else { mTextActionMode.invalidateContentRect(); } @@ -2026,55 +1984,46 @@ public class Editor { } } + @NonNull + TextView getTextView() { + return mTextView; + } + + @Nullable + ActionMode getTextActionMode() { + return mTextActionMode; + } + + void setRestartActionModeOnNextRefresh(boolean value) { + mRestartActionModeOnNextRefresh = value; + } + /** - * Starts a Selection Action Mode with the current selection and ensures the selection handles - * are shown if there is a selection. This should be used when the mode is started from a - * non-touch event. - * - * @return true if the selection mode was actually started. + * Asynchronously starts a selection action mode using the TextClassifier. */ - boolean startSelectionActionMode(@Nullable TextClassificationResult textClassificationResult) { - mTextClassificationResult = textClassificationResult; - boolean selectionStarted = startSelectionActionModeInternal(); - if (selectionStarted) { - getSelectionController().show(); - } - mRestartActionModeOnNextRefresh = false; - return selectionStarted; + void startSelectionActionModeAsync() { + getSelectionActionModeHelper().startActionModeAsync(); } - private boolean startSelectionActionModeWithTextAssistant() { - return startSelectionActionMode(getTextClassifierInfo(true)); + /** + * Synchronously starts a selection action mode without the TextClassifier. + */ + void startSelectionActionMode() { + getSelectionActionModeHelper().startActionMode(); } - private void invalidateActionMode(TextClassificationResult textClassificationResult) { - mTextClassificationResult = textClassificationResult; - mTextActionMode.invalidate(); + /** + * Asynchronously invalidates an action mode using the TextClassifier. + */ + private void invalidateActionModeAsync() { + getSelectionActionModeHelper().invalidateActionModeAsync(); } - // TODO: Make this a non-blocking call. - private TextClassificationResult getTextClassifierInfo(boolean updateSelection) { - // TODO: Trim the text so that only text necessary to provide context of the selected - // text is sent to the assistant. - final int trimStartIndex = 0; - final int trimEndIndex = mTextView.getText().length(); - CharSequence trimmedText = - mTextView.getText().subSequence(trimStartIndex, trimEndIndex); - int startIndex = mTextView.getSelectionStart() - trimStartIndex; - int endIndex = mTextView.getSelectionEnd() - trimStartIndex; - - if (updateSelection) { - TextSelection textSelection = mTextView.getTextClassifier() - .suggestSelection(trimmedText, startIndex, endIndex); - startIndex = Math.max(0, textSelection.getSelectionStartIndex() + trimStartIndex); - endIndex = Math.min(mTextView.getText().length(), - textSelection.getSelectionEndIndex() + trimStartIndex); - Selection.setSelection((Spannable) mTextView.getText(), startIndex, endIndex); - return getTextClassifierInfo(false); + private SelectionActionModeHelper getSelectionActionModeHelper() { + if (mSelectionActionModeHelper == null) { + mSelectionActionModeHelper = new SelectionActionModeHelper(this); } - - return mTextView.getTextClassifier() - .getTextClassificationResult(trimmedText, startIndex, endIndex); + return mSelectionActionModeHelper; } /** @@ -2117,13 +2066,13 @@ public class Editor { return true; } - private boolean startSelectionActionModeInternal() { + boolean startSelectionActionModeInternal() { if (extractedTextModeWillBeStarted()) { return false; } if (mTextActionMode != null) { // Text action mode is already started - invalidateActionMode(getTextClassifierInfo(false)); + invalidateActionModeAsync(); return false; } @@ -2314,7 +2263,8 @@ public class Editor { return mInsertionPointCursorController; } - private SelectionModifierCursorController getSelectionController() { + @Nullable + SelectionModifierCursorController getSelectionController() { if (!mSelectionControllerEnabled) { return null; } @@ -3813,7 +3763,7 @@ public class Editor { mode.setSubtitle(null); mode.setTitleOptionalHint(true); populateMenuWithItems(menu); - updateAssistMenuItem(menu, mTextClassificationResult); + updateAssistMenuItem(menu); Callback customCallback = getCustomCallback(); if (customCallback != null) { @@ -3881,7 +3831,7 @@ public class Editor { public boolean onPrepareActionMode(ActionMode mode, Menu menu) { updateSelectAllItem(menu); updateReplaceItem(menu); - updateAssistMenuItem(menu, mTextClassificationResult); + updateAssistMenuItem(menu); Callback customCallback = getCustomCallback(); if (customCallback != null) { @@ -3914,9 +3864,10 @@ public class Editor { } } - private void updateAssistMenuItem( - Menu menu, TextClassificationResult textClassificationResult) { + private void updateAssistMenuItem(Menu menu) { menu.removeItem(TextView.ID_ASSIST); + final TextClassificationResult textClassificationResult = + getSelectionActionModeHelper().getTextClassificationResult(); if (textClassificationResult != null) { final Drawable icon = textClassificationResult.getIcon(); final CharSequence label = textClassificationResult.getLabel(); @@ -3941,7 +3892,8 @@ public class Editor { if (customCallback != null && customCallback.onActionItemClicked(mode, item)) { return true; } - final TextClassificationResult textClassificationResult = mTextClassificationResult; + final TextClassificationResult textClassificationResult = + getSelectionActionModeHelper().getTextClassificationResult(); if (TextView.ID_ASSIST == item.getItemId() && textClassificationResult != null) { final OnClickListener onClickListener = textClassificationResult.getOnClickListener(); @@ -3964,8 +3916,8 @@ public class Editor { @Override public void onDestroyActionMode(ActionMode mode) { // Clear mTextActionMode not to recursively destroy action mode by clearing selection. + getSelectionActionModeHelper().cancelAsyncTask(); mTextActionMode = null; - mTextClassificationResult = null; Callback customCallback = getCustomCallback(); if (customCallback != null) { customCallback.onDestroyActionMode(mode); @@ -4099,69 +4051,9 @@ public class Editor { final CharSequence composingText = text.subSequence(composingTextStart, composingTextEnd); builder.setComposingText(composingTextStart, composingText); - - final int minLine = layout.getLineForOffset(composingTextStart); - final int maxLine = layout.getLineForOffset(composingTextEnd - 1); - for (int line = minLine; line <= maxLine; ++line) { - final int lineStart = layout.getLineStart(line); - final int lineEnd = layout.getLineEnd(line); - final int offsetStart = Math.max(lineStart, composingTextStart); - final int offsetEnd = Math.min(lineEnd, composingTextEnd); - final boolean ltrLine = - layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT; - final float[] widths = new float[offsetEnd - offsetStart]; - layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths); - final float top = layout.getLineTop(line); - final float bottom = layout.getLineBottom(line); - for (int offset = offsetStart; offset < offsetEnd; ++offset) { - final float charWidth = widths[offset - offsetStart]; - final boolean isRtl = layout.isRtlCharAt(offset); - final float primary = layout.getPrimaryHorizontal(offset); - final float secondary = layout.getSecondaryHorizontal(offset); - // TODO: This doesn't work perfectly for text with custom styles and - // TAB chars. - final float left; - final float right; - if (ltrLine) { - if (isRtl) { - left = secondary - charWidth; - right = secondary; - } else { - left = primary; - right = primary + charWidth; - } - } else { - if (!isRtl) { - left = secondary; - right = secondary + charWidth; - } else { - left = primary - charWidth; - right = primary; - } - } - // TODO: Check top-right and bottom-left as well. - final float localLeft = left + viewportToContentHorizontalOffset; - final float localRight = right + viewportToContentHorizontalOffset; - final float localTop = top + viewportToContentVerticalOffset; - final float localBottom = bottom + viewportToContentVerticalOffset; - final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop); - final boolean isBottomRightVisible = - isPositionVisible(localRight, localBottom); - int characterBoundsFlags = 0; - if (isTopLeftVisible || isBottomRightVisible) { - characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; - } - if (!isTopLeftVisible || !isBottomRightVisible) { - characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; - } - if (isRtl) { - characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL; - } - // Here offset is the index in Java chars. - builder.addCharacterBounds(offset, localLeft, localTop, localRight, - localBottom, characterBoundsFlags); - } - } + mTextView.populateCharacterBounds(builder, composingTextStart, + composingTextEnd, viewportToContentHorizontalOffset, + viewportToContentVerticalOffset); } } @@ -4177,10 +4069,10 @@ public class Editor { + viewportToContentVerticalOffset; final float insertionMarkerBottom = layout.getLineBottom(line) + viewportToContentVerticalOffset; - final boolean isTopVisible = - isPositionVisible(insertionMarkerX, insertionMarkerTop); - final boolean isBottomVisible = - isPositionVisible(insertionMarkerX, insertionMarkerBottom); + final boolean isTopVisible = mTextView + .isPositionVisible(insertionMarkerX, insertionMarkerTop); + final boolean isBottomVisible = mTextView + .isPositionVisible(insertionMarkerX, insertionMarkerBottom); int insertionMarkerFlags = 0; if (isTopVisible || isBottomVisible) { insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; @@ -4388,7 +4280,8 @@ public class Editor { return false; } - return isPositionVisible(mPositionX + mHotspotX + getHorizontalOffset(), mPositionY); + return mTextView.isPositionVisible( + mPositionX + mHotspotX + getHorizontalOffset(), mPositionY); } public abstract int getCurrentCursorOffset(); @@ -4783,7 +4676,7 @@ public class Editor { } positionAtCursorOffset(offset, false); if (mTextActionMode != null) { - invalidateActionMode(getTextClassifierInfo(false)); + invalidateActionModeAsync(); } } @@ -4867,7 +4760,7 @@ public class Editor { } updateDrawable(); if (mTextActionMode != null) { - invalidateActionMode(getTextClassifierInfo(false)); + invalidateActionModeAsync(); } } @@ -5516,8 +5409,12 @@ public class Editor { if (mTextView.hasSelection()) { // Do not invoke the text assistant if this was a drag selection. - startSelectionActionMode( - mHaventMovedEnoughToStartDrag ? getTextClassifierInfo(true) : null); + if (mHaventMovedEnoughToStartDrag) { + startSelectionActionModeAsync(); + } else { + startSelectionActionMode(); + } + } break; } diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java index 72dc1cc5c63c..8ba4694c331c 100644 --- a/core/java/android/widget/RadioGroup.java +++ b/core/java/android/widget/RadioGroup.java @@ -24,7 +24,6 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; -import android.view.ViewStructure; import android.view.autofill.AutoFillType; import android.view.autofill.AutoFillValue; @@ -404,16 +403,14 @@ public class RadioGroup extends LinearLayout { } } - // TODO(b/33197203): add unit/CTS tests for auto-fill methods + // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable) - @Override - public void onProvideAutoFillStructure(ViewStructure structure, int flags) { - super.onProvideAutoFillStructure(structure, flags); - structure.setAutoFillValue(AutoFillValue.forList(getCheckedRadioButtonId())); - } + // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener @Override public void autoFill(AutoFillValue value) { + if (!isEnabled()) return; + final int index = value.getListValue(); final View child = getChildAt(index); if (child == null) { @@ -427,4 +424,9 @@ public class RadioGroup extends LinearLayout { public AutoFillType getAutoFillType() { return AutoFillType.forList(); } + + @Override + public AutoFillValue getAutoFillValue() { + return isEnabled() ? AutoFillValue.forList(getCheckedRadioButtonId()) : null; + } } diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java new file mode 100644 index 000000000000..770d9eec792a --- /dev/null +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.widget; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UiThread; +import android.annotation.WorkerThread; +import android.os.AsyncTask; +import android.text.Selection; +import android.text.Spannable; +import android.text.TextUtils; +import android.view.ActionMode; +import android.view.textclassifier.TextClassificationResult; +import android.view.textclassifier.TextClassifier; +import android.view.textclassifier.TextSelection; +import android.widget.Editor.SelectionModifierCursorController; + +import com.android.internal.util.Preconditions; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Helper class for starting selection action mode + * (synchronously without the TextClassifier, asynchronously with the TextClassifier). + */ +@UiThread +final class SelectionActionModeHelper { + + /** + * Maximum time (in milliseconds) to wait for a result before timing out. + */ + // TODO: Consider making this a ViewConfiguration. + private static final int TIMEOUT_DURATION = 200; + + private final Editor mEditor; + private final TextClassificationHelper mTextClassificationHelper; + + private TextClassificationResult mTextClassificationResult; + private AsyncTask mTextClassificationAsyncTask; + + SelectionActionModeHelper(@NonNull Editor editor) { + mEditor = Preconditions.checkNotNull(editor); + final TextView textView = mEditor.getTextView(); + mTextClassificationHelper = new TextClassificationHelper( + textView.getTextClassifier(), textView.getText(), + textView.getSelectionStart(), textView.getSelectionEnd()); + } + + public void startActionModeAsync() { + cancelAsyncTask(); + if (isNoOpTextClassifier()) { + // No need to make an async call for a no-op TextClassifier. + startActionMode(null); + } else { + resetTextClassificationHelper(); + mTextClassificationAsyncTask = new TextClassificationAsyncTask( + mEditor.getTextView(), TIMEOUT_DURATION, + mTextClassificationHelper::suggestSelection, this::startActionMode) + .execute(); + } + } + + public void startActionMode() { + startActionMode(null); + } + + public void invalidateActionModeAsync() { + cancelAsyncTask(); + if (isNoOpTextClassifier()) { + // No need to make an async call for a no-op TextClassifier. + invalidateActionMode(null); + } else { + resetTextClassificationHelper(); + mTextClassificationAsyncTask = new TextClassificationAsyncTask( + mEditor.getTextView(), TIMEOUT_DURATION, + mTextClassificationHelper::classifyText, this::invalidateActionMode) + .execute(); + } + } + + public void cancelAsyncTask() { + if (mTextClassificationAsyncTask != null) { + mTextClassificationAsyncTask.cancel(true); + mTextClassificationAsyncTask = null; + } + mTextClassificationResult = null; + } + + @Nullable + public TextClassificationResult getTextClassificationResult() { + return mTextClassificationResult; + } + + private boolean isNoOpTextClassifier() { + return mEditor.getTextView().getTextClassifier() == TextClassifier.NO_OP; + } + + private void startActionMode(@Nullable SelectionResult result) { + final CharSequence text = mEditor.getTextView().getText(); + if (result != null && text instanceof Spannable) { + Selection.setSelection((Spannable) text, result.mStart, result.mEnd); + mTextClassificationResult = result.mResult; + } else { + mTextClassificationResult = null; + } + if (mEditor.startSelectionActionModeInternal()) { + final SelectionModifierCursorController controller = mEditor.getSelectionController(); + if (controller != null) { + controller.show(); + } + } + mEditor.setRestartActionModeOnNextRefresh(false); + mTextClassificationAsyncTask = null; + } + + private void invalidateActionMode(@Nullable SelectionResult result) { + mTextClassificationResult = result != null ? result.mResult : null; + final ActionMode actionMode = mEditor.getTextActionMode(); + if (actionMode != null) { + actionMode.invalidate(); + } + mTextClassificationAsyncTask = null; + } + + private void resetTextClassificationHelper() { + final TextView textView = mEditor.getTextView(); + mTextClassificationHelper.reset(textView.getTextClassifier(), textView.getText(), + textView.getSelectionStart(), textView.getSelectionEnd()); + } + + /** + * AsyncTask for running a query on a background thread and returning the result on the + * UiThread. The AsyncTask times out after a specified time, returning a null result if the + * query has not yet returned. + */ + private static final class TextClassificationAsyncTask + extends AsyncTask<Void, Void, SelectionResult> { + + private final int mTimeOutDuration; + private final Supplier<SelectionResult> mSelectionResultSupplier; + private final Consumer<SelectionResult> mSelectionResultCallback; + private final TextView mTextView; + private final String mOriginalText; + + /** + * @param textView the TextView + * @param timeOut time in milliseconds to timeout the query if it has not completed + * @param selectionResultSupplier fetches the selection results. Runs on a background thread + * @param selectionResultCallback receives the selection results. Runs on the UiThread + */ + TextClassificationAsyncTask( + @NonNull TextView textView, int timeOut, + @NonNull Supplier<SelectionResult> selectionResultSupplier, + @NonNull Consumer<SelectionResult> selectionResultCallback) { + mTextView = Preconditions.checkNotNull(textView); + mTimeOutDuration = timeOut; + mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier); + mSelectionResultCallback = Preconditions.checkNotNull(selectionResultCallback); + // Make a copy of the original text. + mOriginalText = mTextView.getText().toString(); + } + + @Override + @WorkerThread + protected SelectionResult doInBackground(Void... params) { + final Runnable onTimeOut = this::onTimeOut; + mTextView.postDelayed(onTimeOut, mTimeOutDuration); + final SelectionResult result = mSelectionResultSupplier.get(); + mTextView.removeCallbacks(onTimeOut); + return result; + } + + @Override + @UiThread + protected void onPostExecute(SelectionResult result) { + result = TextUtils.equals(mOriginalText, mTextView.getText()) ? result : null; + mSelectionResultCallback.accept(result); + } + + private void onTimeOut() { + if (getStatus() == Status.RUNNING) { + onPostExecute(null); + } + cancel(true); + } + } + + /** + * Helper class for querying the TextClassifier. + * It trims text so that only text necessary to provide context of the selected text is + * sent to the TextClassifier. + */ + private static final class TextClassificationHelper { + + private static final int TRIM_DELTA = 50; // characters + + private TextClassifier mTextClassifier; + + /** The original TextView text. **/ + private String mText; + /** Start index relative to mText. */ + private int mSelectionStart; + /** End index relative to mText. */ + private int mSelectionEnd; + + /** Trimmed text starting from mTrimStart in mText. */ + private CharSequence mTrimmedText; + /** Index indicating the start of mTrimmedText in mText. */ + private int mTrimStart; + /** Start index relative to mTrimmedText */ + private int mRelativeStart; + /** End index relative to mTrimmedText */ + private int mRelativeEnd; + + TextClassificationHelper(TextClassifier textClassifier, + CharSequence text, int selectionStart, int selectionEnd) { + reset(textClassifier, text, selectionStart, selectionEnd); + } + + @UiThread + public void reset(TextClassifier textClassifier, + CharSequence text, int selectionStart, int selectionEnd) { + mTextClassifier = Preconditions.checkNotNull(textClassifier); + mText = Preconditions.checkNotNull(text).toString(); + mSelectionStart = selectionStart; + mSelectionEnd = selectionEnd; + } + + @WorkerThread + public SelectionResult classifyText() { + trimText(); + return new SelectionResult( + mSelectionStart, + mSelectionEnd, + mTextClassifier.getTextClassificationResult( + mTrimmedText, mRelativeStart, mRelativeEnd)); + } + + @WorkerThread + public SelectionResult suggestSelection() { + trimText(); + final TextSelection sel = mTextClassifier.suggestSelection( + mTrimmedText, mRelativeStart, mRelativeEnd); + mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart); + mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart); + return classifyText(); + } + + private void trimText() { + mTrimStart = Math.max(0, mSelectionStart - TRIM_DELTA); + final int referenceEnd = Math.min(mText.length(), mSelectionEnd + TRIM_DELTA); + mTrimmedText = mText.subSequence(mTrimStart, referenceEnd); + mRelativeStart = mSelectionStart - mTrimStart; + mRelativeEnd = mSelectionEnd - mTrimStart; + } + } + + /** + * Selection result. + */ + private static final class SelectionResult { + private final int mStart; + private final int mEnd; + private final TextClassificationResult mResult; + + SelectionResult(int start, int end, TextClassificationResult result) { + mStart = start; + mEnd = end; + mResult = Preconditions.checkNotNull(result); + } + } +} diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index a5ff29119dc9..28c5c60686ed 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -17,6 +17,10 @@ package android.widget; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; +import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH; +import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX; +import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; import android.R; import android.annotation.ColorInt; @@ -142,6 +146,7 @@ import android.view.autofill.AutoFillValue; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; +import android.view.inputmethod.CursorAnchorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -166,6 +171,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; import java.util.Locale; /** @@ -268,6 +274,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener static final String LOG_TAG = "TextView"; static final boolean DEBUG_EXTRACT = false; static final boolean DEBUG_AUTOFILL = false; + private static final float[] TEMP_POSITION = new float[2]; // Enum for the "typeface" XML parameter. // TODO: How can we get this from the XML instead of hardcoding it here? @@ -6635,7 +6642,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ public boolean handleBackInTextActionModeIfNeeded(KeyEvent event) { // Do nothing unless mEditor is in text action mode. - if (mEditor == null || mEditor.mTextActionMode == null) { + if (mEditor == null || mEditor.getTextActionMode() == null) { return false; } @@ -6819,7 +6826,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Has to be done on key down (and not on key up) to correctly be intercepted. case KeyEvent.KEYCODE_BACK: - if (mEditor != null && mEditor.mTextActionMode != null) { + if (mEditor != null && mEditor.getTextActionMode() != null) { stopTextActionMode(); return KEY_EVENT_HANDLED; } @@ -9012,7 +9019,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEditor != null) { mEditor.refreshTextActionMode(); - if (!hasSelection() && mEditor.mTextActionMode == null && hasTransientState()) { + if (!hasSelection() + && mEditor.getTextActionMode() == null && hasTransientState()) { // User generated selection has been removed. setHasTransientState(false); } @@ -9736,9 +9744,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Simple case: this is a single line. final CharSequence text = getText(); structure.setText(text, getSelectionStart(), getSelectionEnd()); - if (forAutoFill && isTextEditable()) { - structure.setAutoFillValue(AutoFillValue.forText(text)); - } } else { // Complex case: multi-line, could be scrolled or within a scroll container // so some lines are not visible. @@ -9795,9 +9800,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener text = text.subSequence(expandedTopChar, expandedBottomChar); } structure.setText(text, selStart - expandedTopChar, selEnd - expandedTopChar); - if (forAutoFill && isTextEditable()) { - structure.setAutoFillValue(AutoFillValue.forText(text)); - } final int[] lineOffsets = new int[bottomLine - topLine + 1]; final int[] lineBaselines = new int[bottomLine - topLine + 1]; final int baselineOffset = getBaselineOffset(); @@ -9845,17 +9847,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final CharSequence text = value.getTextValue(); if (text != null && isTextEditable()) { - if (mAutoFillChangeWatcher == null || mAutoFillChangeWatcher.mOnAutoFill) { - setText(text, mBufferType, true, 0); - } else { - // Must disable listener first so it's not triggered. - mAutoFillChangeWatcher.mOnAutoFill = true; - try { - setText(text, mBufferType, true, 0); - } finally { - mAutoFillChangeWatcher.mOnAutoFill = false; - } - } + setText(text, mBufferType, true, 0); } } @@ -9865,6 +9857,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return isTextEditable() ? AutoFillType.forText(getInputType()) : null; } + @Override + @Nullable + public AutoFillValue getAutoFillValue() { + return isTextEditable() ? AutoFillValue.forText(getText()) : null; + } + /** @hide */ @Override public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { @@ -9916,6 +9914,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE); info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); + info.setAvailableExtraData( + Arrays.asList(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)); } if (isFocused()) { @@ -9952,6 +9952,164 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } + @Override + public void addExtraDataToAccessibilityNodeInfo( + AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) { + if (extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) { + int positionInfoStartIndex = arguments.getInt( + EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, -1); + int positionInfoLength = arguments.getInt( + EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH, -1); + if ((positionInfoLength <= 0) || (positionInfoStartIndex < 0) + || (positionInfoStartIndex >= mText.length())) { + Log.e(LOG_TAG, "Invalid arguments for accessibility character locations"); + return; + } + RectF[] boundingRects = new RectF[positionInfoLength]; + final CursorAnchorInfo.Builder builder = new CursorAnchorInfo.Builder(); + populateCharacterBounds(builder, positionInfoStartIndex, + positionInfoStartIndex + positionInfoLength, + viewportToContentHorizontalOffset(), viewportToContentVerticalOffset()); + CursorAnchorInfo cursorAnchorInfo = builder.setMatrix(null).build(); + if (mTempRect == null) mTempRect = new Rect(); + Rect viewBoundsInScreen = mTempRect; + info.getBoundsInScreen(viewBoundsInScreen); + for (int i = 0; i < positionInfoLength; i++) { + int flags = cursorAnchorInfo.getCharacterBoundsFlags(positionInfoStartIndex + i); + if ((flags & FLAG_HAS_VISIBLE_REGION) == FLAG_HAS_VISIBLE_REGION) { + RectF bounds = cursorAnchorInfo + .getCharacterBounds(positionInfoStartIndex + i); + if (bounds != null) { + bounds.offset(viewBoundsInScreen.left, viewBoundsInScreen.top); + boundingRects[i] = bounds; + } + } + } + info.getExtras().putParcelableArray(extraDataKey, boundingRects); + } + } + + /** + * Populate requested character bounds in a {@link CursorAnchorInfo.Builder} + * + * @param builder The builder to populate + * @param startIndex The starting character index to populate + * @param endIndex The ending character index to populate + * @param viewportToContentHorizontalOffset The horizontal offset from the viewport to the + * content + * @param viewportToContentVerticalOffset The vertical offset from the viewport to the content + * @hide + */ + public void populateCharacterBounds(CursorAnchorInfo.Builder builder, + int startIndex, int endIndex, float viewportToContentHorizontalOffset, + float viewportToContentVerticalOffset) { + final int minLine = mLayout.getLineForOffset(startIndex); + final int maxLine = mLayout.getLineForOffset(endIndex - 1); + for (int line = minLine; line <= maxLine; ++line) { + final int lineStart = mLayout.getLineStart(line); + final int lineEnd = mLayout.getLineEnd(line); + final int offsetStart = Math.max(lineStart, startIndex); + final int offsetEnd = Math.min(lineEnd, endIndex); + final boolean ltrLine = + mLayout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT; + final float[] widths = new float[offsetEnd - offsetStart]; + mLayout.getPaint().getTextWidths(mText, offsetStart, offsetEnd, widths); + final float top = mLayout.getLineTop(line); + final float bottom = mLayout.getLineBottom(line); + for (int offset = offsetStart; offset < offsetEnd; ++offset) { + final float charWidth = widths[offset - offsetStart]; + final boolean isRtl = mLayout.isRtlCharAt(offset); + final float primary = mLayout.getPrimaryHorizontal(offset); + final float secondary = mLayout.getSecondaryHorizontal(offset); + // TODO: This doesn't work perfectly for text with custom styles and + // TAB chars. + final float left; + final float right; + if (ltrLine) { + if (isRtl) { + left = secondary - charWidth; + right = secondary; + } else { + left = primary; + right = primary + charWidth; + } + } else { + if (!isRtl) { + left = secondary; + right = secondary + charWidth; + } else { + left = primary - charWidth; + right = primary; + } + } + // TODO: Check top-right and bottom-left as well. + final float localLeft = left + viewportToContentHorizontalOffset; + final float localRight = right + viewportToContentHorizontalOffset; + final float localTop = top + viewportToContentVerticalOffset; + final float localBottom = bottom + viewportToContentVerticalOffset; + final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop); + final boolean isBottomRightVisible = + isPositionVisible(localRight, localBottom); + int characterBoundsFlags = 0; + if (isTopLeftVisible || isBottomRightVisible) { + characterBoundsFlags |= FLAG_HAS_VISIBLE_REGION; + } + if (!isTopLeftVisible || !isBottomRightVisible) { + characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; + } + if (isRtl) { + characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL; + } + // Here offset is the index in Java chars. + builder.addCharacterBounds(offset, localLeft, localTop, localRight, + localBottom, characterBoundsFlags); + } + } + } + + /** + * @hide + */ + public boolean isPositionVisible(final float positionX, final float positionY) { + synchronized (TEMP_POSITION) { + final float[] position = TEMP_POSITION; + position[0] = positionX; + position[1] = positionY; + View view = this; + + while (view != null) { + if (view != this) { + // Local scroll is already taken into account in positionX/Y + position[0] -= view.getScrollX(); + position[1] -= view.getScrollY(); + } + + if (position[0] < 0 || position[1] < 0 || position[0] > view.getWidth() + || position[1] > view.getHeight()) { + return false; + } + + if (!view.getMatrix().isIdentity()) { + view.getMatrix().mapPoints(position); + } + + position[0] += view.getLeft(); + position[1] += view.getTop(); + + final ViewParent parent = view.getParent(); + if (parent instanceof View) { + view = (View) parent; + } else { + // We've reached the ViewRoot, stop iterating + view = null; + } + } + } + + // We've been able to walk up the view hierarchy and the position was never clipped + return true; + } + /** * Performs an accessibility action after it has been offered to the * delegate. @@ -10009,7 +10167,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Selection.setSelection((Spannable) text, start, end); // Make sure selection mode is engaged. if (mEditor != null) { - mEditor.startSelectionActionMode(null); + mEditor.startSelectionActionModeAsync(); } return true; } @@ -10724,14 +10882,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ protected void viewClicked(InputMethodManager imm) { - final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class); - if (afm != null) { - if (DEBUG_AUTOFILL) Log.v(LOG_TAG, "viewClicked(): id=" + getAccessibilityViewId()); - - // TODO(b/33197203): integrate with onFocus and/or move to view? - afm.updateAutoFillInput(this, AutoFillManager.FLAG_UPDATE_UI_SHOW); - } - if (imm != null) { imm.viewClicked(this); } @@ -11213,7 +11363,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // TODO(b/33197203): implements SpanWatcher too? private final class AutoFillChangeWatcher implements TextWatcher { - private boolean mOnAutoFill; private final AutoFillManager mAfm = mContext.getSystemService(AutoFillManager.class); @Override @@ -11226,18 +11375,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void afterTextChanged(Editable s) { - if (mOnAutoFill) { - if (DEBUG_AUTOFILL) { - Log.v(LOG_TAG, "AutoFillChangeWatcher.afterTextChanged() skipped during " - + "autoFill(): s=" + s); - } - return; - } if (mAfm != null) { if (DEBUG_AUTOFILL) { Log.v(LOG_TAG, "AutoFillChangeWatcher.afterTextChanged(): s=" + s); } - mAfm.onValueChanged(TextView.this, AutoFillValue.forText(s)); + mAfm.valueChanged(TextView.this); } } } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index ab1d9b9c6f6e..40142173ece3 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -36,7 +36,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; import android.app.ActivityManager; -import android.app.AppGlobals; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -115,6 +114,7 @@ public class ResolverActivity extends Activity { private static final String TAG = "ResolverActivity"; private static final boolean DEBUG = false; + private Runnable mPostListBuildRunnable; private boolean mRegistered; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @@ -419,7 +419,9 @@ public class ResolverActivity extends Activity { protected CharSequence getTitleForAction(String action, int defaultTitleRes) { final ActionTitle title = mResolvingHome ? ActionTitle.HOME : ActionTitle.forAction(action); - final boolean named = mAdapter.hasFilteredItem(); + // While there may already be a filtered item, we can only use it in the title if the list + // is already sorted and all information relevant to it is already in the list. + final boolean named = mAdapter.getFilteredPosition() > 0; if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) { return getString(defaultTitleRes); } else { @@ -510,6 +512,9 @@ public class ResolverActivity extends Activity { if (!isChangingConfigurations() && mPickOptionRequest != null) { mPickOptionRequest.cancel(); } + if (mPostListBuildRunnable != null) { + getMainThreadHandler().removeCallbacks(mPostListBuildRunnable); + } } @Override @@ -590,6 +595,9 @@ public class ResolverActivity extends Activity { } TargetInfo target = mAdapter.targetInfoForPosition(which, filtered); + if (target == null) { + return; + } if (onTargetSelected(target, always)) { if (always && filtered) { MetricsLogger.action( @@ -880,15 +888,15 @@ public class ResolverActivity extends Activity { } setContentView(mLayoutId); - if (count > 0 || !rebuildCompleted) { - mAdapterView = (AbsListView) findViewById(R.id.resolver_list); - onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption); - } else { + mAdapterView = (AbsListView) findViewById(R.id.resolver_list); + + if (count == 0 && mAdapter.mPlaceholderCount == 0) { final TextView empty = (TextView) findViewById(R.id.empty); empty.setVisibility(View.VISIBLE); - - mAdapterView = (AbsListView) findViewById(R.id.resolver_list); mAdapterView.setVisibility(View.GONE); + } else { + mAdapterView.setVisibility(View.VISIBLE); + onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption); } return false; } @@ -917,16 +925,23 @@ public class ResolverActivity extends Activity { } public void setTitleAndIcon() { - if (mTitle == null) { - mTitle = getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId); + if (mAdapter.getCount() == 0 && mAdapter.mPlaceholderCount == 0) { + final TextView titleView = (TextView) findViewById(R.id.title); + if (titleView != null) { + titleView.setVisibility(View.GONE); + } } - if (!TextUtils.isEmpty(mTitle)) { + CharSequence title = mTitle != null + ? mTitle + : getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId); + + if (!TextUtils.isEmpty(title)) { final TextView titleView = (TextView) findViewById(R.id.title); if (titleView != null) { - titleView.setText(mTitle); + titleView.setText(title); } - setTitle(mTitle); + setTitle(title); // Try to initialize the title icon if we have a view for it and a title to match final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon); @@ -963,9 +978,17 @@ public class ResolverActivity extends Activity { } } - if (mAdapter.hasFilteredItem()) { + if (mAdapter.getFilteredPosition() >= 0) { setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false); mOnceButton.setEnabled(true); + return; + } + + // When the items load in, if an item was already selected, enable the buttons + if (mAdapterView != null + && mAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) { + setAlwaysButtonEnabled(true, mAdapterView.getCheckedItemPosition(), true); + mOnceButton.setEnabled(true); } } @@ -1234,6 +1257,7 @@ public class ResolverActivity extends Activity { private DisplayResolveInfo mOtherProfile; private boolean mHasExtendedInfo; private ResolverListController mResolverListController; + private int mPlaceholderCount; protected final LayoutInflater mInflater; @@ -1265,6 +1289,10 @@ public class ResolverActivity extends Activity { } } + public void setPlaceholderCount(int count) { + mPlaceholderCount = count; + } + public DisplayResolveInfo getFilteredItem() { if (mFilterLastUsed && mLastChosenPosition >= 0) { // Not using getItem since it offsets to dodge this position for the list @@ -1350,6 +1378,7 @@ public class ResolverActivity extends Activity { } if (N > 1) { + setPlaceholderCount(currentResolveList.size()); AsyncTask<List<ResolvedComponentInfo>, Void, List<ResolvedComponentInfo>> sortingTask = @@ -1366,13 +1395,26 @@ public class ResolverActivity extends Activity { @Override protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) { processSortedList(sortedComponents); - onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption); if (mProfileView != null) { bindProfileView(); } + notifyDataSetChanged(); } }; sortingTask.execute(currentResolveList); + if (mPostListBuildRunnable == null) { + mPostListBuildRunnable = new Runnable() { + @Override + public void run() { + setTitleAndIcon(); + resetAlwaysOrOnceButtonBar(); + onListRebuilt(); + disableLastChosenIfNeeded(); + mPostListBuildRunnable = null; + } + }; + getMainThreadHandler().post(mPostListBuildRunnable); + } return false; } else { processSortedList(currentResolveList); @@ -1563,21 +1605,33 @@ public class ResolverActivity extends Activity { } } + @Nullable public ResolveInfo resolveInfoForPosition(int position, boolean filtered) { - return (filtered ? getItem(position) : mDisplayList.get(position)) - .getResolveInfo(); + TargetInfo target = targetInfoForPosition(position, filtered); + if (target != null) { + return target.getResolveInfo(); + } + return null; } + @Nullable public TargetInfo targetInfoForPosition(int position, boolean filtered) { - return filtered ? getItem(position) : mDisplayList.get(position); + if (filtered) { + return getItem(position); + } + if (mDisplayList.size() > position) { + return mDisplayList.get(position); + } + return null; } public int getCount() { - int result = mDisplayList.size(); + int totalSize = mDisplayList == null || mDisplayList.isEmpty() ? mPlaceholderCount : + mDisplayList.size(); if (mFilterLastUsed && mLastChosenPosition >= 0) { - result--; + totalSize--; } - return result; + return totalSize; } public int getUnfilteredCount() { @@ -1592,11 +1646,16 @@ public class ResolverActivity extends Activity { return mDisplayList.get(index); } + @Nullable public TargetInfo getItem(int position) { if (mFilterLastUsed && mLastChosenPosition >= 0 && position >= mLastChosenPosition) { position++; } - return mDisplayList.get(position); + if (mDisplayList.size() > position) { + return mDisplayList.get(position); + } else { + return null; + } } public long getItemId(int position) { @@ -1660,6 +1719,11 @@ public class ResolverActivity extends Activity { private void onBindView(View view, TargetInfo info) { final ViewHolder holder = (ViewHolder) view.getTag(); + if (info == null) { + holder.icon.setImageDrawable( + getDrawable(R.drawable.resolver_icon_placeholder)); + return; + } final CharSequence label = info.getDisplayLabel(); if (!TextUtils.equals(holder.text.getText(), label)) { holder.text.setText(info.getDisplayLabel()); @@ -1770,6 +1834,11 @@ public class ResolverActivity extends Activity { // Header views don't count. return; } + // If we're still loading, we can't yet enable the buttons. + if (mAdapter.resolveInfoForPosition(position, true) == null) { + return; + } + final int checkedPos = mAdapterView.getCheckedItemPosition(); final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION; if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) { diff --git a/core/java/com/android/internal/app/procstats/PssTable.java b/core/java/com/android/internal/app/procstats/PssTable.java index b6df983d2ac8..de5f67330423 100644 --- a/core/java/com/android/internal/app/procstats/PssTable.java +++ b/core/java/com/android/internal/app/procstats/PssTable.java @@ -96,7 +96,7 @@ public class PssTable extends SparseMappingTable.Table { } val = getValue(key, PSS_USS_AVERAGE); - setValue(key, PSS_AVERAGE, + setValue(key, PSS_USS_AVERAGE, (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount))); val = getValue(key, PSS_USS_MAXIMUM); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 63622f15e4c1..9dca5ea6eaa6 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -9562,7 +9562,8 @@ public class BatteryStatsImpl extends BatteryStats { } }); - if (DEBUG_ENERGY_CPU) { + // TODO: STOPSHIP, remove the "true" below after b/34961340 is fixed + if (DEBUG_ENERGY_CPU || true) { Slog.d(TAG, "Reading cpu stats took " + (mClocks.elapsedRealtime() - startTimeMs) + " ms"); } @@ -10390,10 +10391,9 @@ public class BatteryStatsImpl extends BatteryStats { if (next == null) { return; } - - mWriteLock.lock(); } + mWriteLock.lock(); try { FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite()); stream.write(next.marshall()); diff --git a/core/java/com/android/internal/policy/PipMotionHelper.java b/core/java/com/android/internal/policy/PipMotionHelper.java deleted file mode 100644 index 944cd323b295..000000000000 --- a/core/java/com/android/internal/policy/PipMotionHelper.java +++ /dev/null @@ -1,91 +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 com.android.internal.policy; - -import android.animation.RectEvaluator; -import android.animation.ValueAnimator; -import android.app.ActivityManager; -import android.app.IActivityManager; -import android.graphics.Rect; -import android.os.Handler; -import android.os.RemoteException; -import android.util.Log; -import android.view.animation.Interpolator; -import android.view.animation.PathInterpolator; - -/** - * A helper to animate the PIP. - */ -public class PipMotionHelper { - - private static final String TAG = "PipMotionHelper"; - - private static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect()); - private static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); - private static final int DEFAULT_DURATION = 225; - - private IActivityManager mActivityManager; - private Handler mHandler; - - public PipMotionHelper(Handler handler) { - mHandler = handler; - } - - /** - * Moves the PIP to give given {@param bounds}. - */ - public void resizeToBounds(Rect toBounds) { - mHandler.post(() -> { - if (mActivityManager == null) { - mActivityManager = ActivityManager.getService(); - } - try { - mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */); - } catch (RemoteException e) { - Log.e(TAG, "Could not move pinned stack to bounds: " + toBounds, e); - } - }); - } - - /** - * Creates an animation to move the PIP to give given {@param toBounds} with the default - * animation properties. - */ - public ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds) { - return createAnimationToBounds(fromBounds, toBounds, DEFAULT_DURATION, FAST_OUT_SLOW_IN, - null); - } - - /** - * Creates an animation to move the PIP to give given {@param toBounds}. - */ - public ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds, int duration, - Interpolator interpolator, ValueAnimator.AnimatorUpdateListener updateListener) { - ValueAnimator anim = ValueAnimator.ofObject(RECT_EVALUATOR, fromBounds, toBounds); - anim.setDuration(duration); - anim.setInterpolator(interpolator); - anim.addUpdateListener((ValueAnimator animation) -> { - resizeToBounds((Rect) animation.getAnimatedValue()); - }); - if (updateListener != null) { - anim.addUpdateListener(updateListener); - } - return anim; - } - - -} diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java index ec92aa9d36a4..bf047c1538dc 100644 --- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java @@ -84,13 +84,6 @@ public class PipSnapAlgorithm { } /** - * Enables snapping to the closest edge. - */ - public void setSnapToEdge(boolean snapToEdge) { - mSnapMode = snapToEdge ? SNAP_MODE_EDGE : mDefaultSnapMode; - } - - /** * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at * the given {@param velocityX} and {@param velocityY}. The {@param movementBounds} should be * those for the given {@param stackBounds}. @@ -233,6 +226,21 @@ public class PipSnapAlgorithm { } /** + * Adjusts {@param movementBoundsOut} so that it is the movement bounds for the given + * {@param stackBounds}. + */ + public void getMovementBounds(Rect stackBounds, Rect insetBounds, Rect movementBoundsOut, + int imeHeight) { + // Adjust the right/bottom to ensure the stack bounds never goes offscreen + movementBoundsOut.set(insetBounds); + movementBoundsOut.right = Math.max(insetBounds.left, insetBounds.right - + stackBounds.width()); + movementBoundsOut.bottom = Math.max(insetBounds.top, insetBounds.bottom - + stackBounds.height()); + movementBoundsOut.bottom -= imeHeight; + } + + /** * @return the closest point in {@param points} to the given {@param x} and {@param y}. */ private Point findClosestPoint(int x, int y, Point[] points) { diff --git a/core/java/com/android/internal/util/MessageUtils.java b/core/java/com/android/internal/util/MessageUtils.java index 184245ef538d..e733c30ae84a 100644 --- a/core/java/com/android/internal/util/MessageUtils.java +++ b/core/java/com/android/internal/util/MessageUtils.java @@ -42,10 +42,11 @@ public class MessageUtils { /** * Finds the names of integer constants. Searches the specified {@code classes}, looking for - * accessible static integer fields whose names begin with one of the specified {@prefixes}. + * accessible static integer fields whose names begin with one of the specified + * {@code prefixes}. * * @param classes the classes to examine. - * @prefixes only consider fields names starting with one of these prefixes. + * @param prefixes only consider fields names starting with one of these prefixes. * @return a {@link SparseArray} mapping integer constants to their names. */ public static SparseArray<String> findMessageNames(Class[] classes, String[] prefixes) { @@ -122,7 +123,6 @@ public class MessageUtils { * accessible static integer values whose names begin with {@link #DEFAULT_PREFIXES}. * * @param classNames the classes to examine. - * @prefixes only consider fields names starting with one of these prefixes. * @return a {@link SparseArray} mapping integer constants to their names. */ public static SparseArray<String> findMessageNames(Class[] classNames) { diff --git a/core/java/com/android/internal/view/InputMethodClient.java b/core/java/com/android/internal/view/InputMethodClient.java index c27e9aa3f2bb..802ce3e734d7 100644 --- a/core/java/com/android/internal/view/InputMethodClient.java +++ b/core/java/com/android/internal/view/InputMethodClient.java @@ -32,13 +32,14 @@ public final class InputMethodClient { public static final int START_INPUT_REASON_UNBOUND_FROM_IMMS = 6; public static final int START_INPUT_REASON_ACTIVATED_BY_IMMS = 7; public static final int START_INPUT_REASON_DEACTIVATED_BY_IMMS = 8; + public static final int START_INPUT_REASON_SESSION_CREATED_BY_IME = 9; @Retention(SOURCE) @IntDef({START_INPUT_REASON_UNSPECIFIED, START_INPUT_REASON_WINDOW_FOCUS_GAIN, START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY, START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API, START_INPUT_REASON_CHECK_FOCUS, START_INPUT_REASON_BOUND_TO_IMMS, START_INPUT_REASON_ACTIVATED_BY_IMMS, - START_INPUT_REASON_DEACTIVATED_BY_IMMS}) + START_INPUT_REASON_DEACTIVATED_BY_IMMS, START_INPUT_REASON_SESSION_CREATED_BY_IME}) public @interface StartInputReason {} public static String getStartInputReason(@StartInputReason final int reason) { @@ -61,6 +62,8 @@ public final class InputMethodClient { return "ACTIVATED_BY_IMMS"; case START_INPUT_REASON_DEACTIVATED_BY_IMMS: return "DEACTIVATED_BY_IMMS"; + case START_INPUT_REASON_SESSION_CREATED_BY_IME: + return "SESSION_CREATED_BY_IME"; default: return "Unknown=" + reason; } diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp index fadf8a47f714..6cf5ccfa2d15 100644 --- a/core/jni/android_hardware_HardwareBuffer.cpp +++ b/core/jni/android_hardware_HardwareBuffer.cpp @@ -30,6 +30,7 @@ #include <binder/Parcel.h> #include <gui/IGraphicBufferAlloc.h> #include <gui/ISurfaceComposer.h> +#include <hardware/gralloc1.h> #include <ui/GraphicBuffer.h> #include <private/gui/ComposerService.h> @@ -96,10 +97,15 @@ static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz, } return NULL; } - uint32_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0); + uint64_t producerUsage = 0; + uint64_t consumerUsage = 0; + android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0, &producerUsage, + &consumerUsage); status_t error; sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat, - layers, grallocUsage, &error)); + layers, producerUsage, consumerUsage, + std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]", + &error)); if (buffer == NULL) { if (kDebugGraphicBuffer) { ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()"); @@ -158,7 +164,7 @@ static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env, jobject clazz, jlong nativeObject) { GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject); return android_hardware_HardwareBuffer_convertFromGrallocUsageBits( - buffer->getUsage()); + buffer->getUsage(), buffer->getUsage()); } // ---------------------------------------------------------------------------- @@ -261,52 +267,58 @@ uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format) { } } -uint32_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0, - uint64_t usage1) { - uint32_t bits = 0; +void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0, + uint64_t usage1, uint64_t* outProducerUsage, + uint64_t* outConsumerUsage) { + *outProducerUsage = 0; + *outConsumerUsage = 0; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ)) - bits |= GRALLOC_USAGE_SW_READ_RARELY; + *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN)) - bits |= GRALLOC_USAGE_SW_READ_OFTEN; + *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE)) - bits |= GRALLOC_USAGE_SW_WRITE_RARELY; + *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN)) - bits |= GRALLOC_USAGE_SW_WRITE_OFTEN; + *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE)) - bits |= GRALLOC_USAGE_HW_TEXTURE; + *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT)) - bits |= GRALLOC_USAGE_HW_RENDER; + *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET; // Not sure what this should be. - if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0; - //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER) bits |= 0; + //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0; + if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER)) + *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE)) - bits |= GRALLOC_USAGE_HW_VIDEO_ENCODER; + *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER; if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT)) - bits |= GRALLOC_USAGE_PROTECTED; - - (void)usage1; - - return bits; + *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_PROTECTED; + if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA)) + *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA; } -uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t usage0) { +uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits( + uint64_t producerUsage, uint64_t consumerUsage) { uint64_t bits = 0; - if (containsBits(usage0, GRALLOC_USAGE_SW_READ_RARELY)) + if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ)) bits |= AHARDWAREBUFFER_USAGE0_CPU_READ; - if (containsBits(usage0, GRALLOC_USAGE_SW_READ_OFTEN)) + if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN)) bits |= AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN; - if (containsBits(usage0, GRALLOC_USAGE_SW_WRITE_RARELY)) + if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE)) bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE; - if (containsBits(usage0, GRALLOC_USAGE_SW_WRITE_OFTEN)) + if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN)) bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN; - if (containsBits(usage0, GRALLOC_USAGE_HW_TEXTURE)) + if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE)) bits |= AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE; - if (containsBits(usage0, GRALLOC_USAGE_HW_RENDER)) + if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET)) bits |= AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT; - if (containsBits(usage0, GRALLOC_USAGE_HW_VIDEO_ENCODER)) + if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER)) + bits |= AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER; + if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER)) bits |= AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE; - if (containsBits(usage0, GRALLOC_USAGE_PROTECTED)) + if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_PROTECTED)) bits |= AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT; + if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA)) + bits |= AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA; return bits; } diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp index b2dee0689ee0..8590ecf3bb19 100644 --- a/core/jni/android_os_HwBlob.cpp +++ b/core/jni/android_os_HwBlob.cpp @@ -382,7 +382,7 @@ static void JHwBlob_native_putString( s = nullptr; hidl_string tmp; - tmp.setToExternal(static_cast<const char *>(subBlob->data()), size); + tmp.setToExternal(static_cast<const char *>(subBlob->data()), size - 1); sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); blob->write(offset, &tmp, sizeof(tmp)); diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp index 3f7bab2ee511..02c0c625d469 100644 --- a/core/jni/android_os_seccomp.cpp +++ b/core/jni/android_os_seccomp.cpp @@ -212,6 +212,10 @@ bool set_seccomp_filter() { // b/34908783 AllowSyscall(f, 250); // __NR_epoll_create + // b/34979910 + AllowSyscall(f, 8); // __NR_creat + AllowSyscall(f, 10); // __NR_unlink + Trap(f); return install_filter(f); diff --git a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h index 60e065cbd0e3..a5d0596dd98b 100644 --- a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h +++ b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h @@ -40,12 +40,13 @@ extern uint32_t android_hardware_HardwareBuffer_convertToPixelFormat( uint32_t format); /* Convert from AHARDWAREBUFFER_USAGE* flags to to gralloc usage flags. */ -extern uint32_t android_hardware_HardwareBuffer_convertToGrallocUsageBits( - uint64_t usage0, uint64_t usage1); +extern void android_hardware_HardwareBuffer_convertToGrallocUsageBits( + uint64_t usage0, uint64_t usage1, uint64_t* outProducerUsage, + uint64_t* outConsumerUsage); /* Convert from gralloc usage flags to to AHARDWAREBUFFER_USAGE0* flags. */ extern uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits( - uint64_t usage0); + uint64_t producerUsage, uint64_t consumerUsage); } // namespace android diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a6e43ffe0d0c..7b800b363e65 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3220,6 +3220,11 @@ <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE" android:protectionLevel="signature" /> + <!-- Must be required by system apps when accessing restricted VR APIs. + <p>Protection level: signature --> + <permission android:name="android.permission.RESTRICTED_VR_ACCESS" + android:protectionLevel="signature|preinstalled" /> + <!-- Required to make calls to {@link android.service.vr.IVrManager}. @hide --> <permission android:name="android.permission.ACCESS_VR_MANAGER" diff --git a/core/res/res/drawable/resolver_icon_placeholder.xml b/core/res/res/drawable/resolver_icon_placeholder.xml new file mode 100644 index 000000000000..049cfeecc4c6 --- /dev/null +++ b/core/res/res/drawable/resolver_icon_placeholder.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> + <solid android:color="#10000000"/> + <size android:width="36dp" android:height="36dp"/> +</shape>
\ No newline at end of file diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml index d8dd447e6a74..7dee2af3abbd 100644 --- a/core/res/res/layout/chooser_grid.xml +++ b/core/res/res/layout/chooser_grid.xml @@ -53,8 +53,7 @@ android:visibility="gone" android:scaleType="fitCenter" android:layout_below="@id/profile_button" - android:layout_alignParentLeft="true" - /> + android:layout_alignParentLeft="true"/> <TextView android:id="@+id/title" android:layout_height="wrap_content" android:layout_width="wrap_content" diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml index 02cd8cdd9b8e..bed80edf0ee7 100644 --- a/core/res/res/layout/preference_list_content.xml +++ b/core/res/res/layout/preference_list_content.xml @@ -24,6 +24,7 @@ android:layout_width="match_parent"> <LinearLayout + android:id="@+id/prefs_container" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="0px" @@ -61,8 +62,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="@integer/preferences_right_pane_weight" - android:orientation="vertical" - android:visibility="gone" > + android:orientation="vertical"> <!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an empty layout or just padding, and PreferenceActivity will put the breadcrumbs in diff --git a/core/res/res/layout/preference_list_content_material.xml b/core/res/res/layout/preference_list_content_material.xml index 1bc527e26b48..37b411918ef6 100644 --- a/core/res/res/layout/preference_list_content_material.xml +++ b/core/res/res/layout/preference_list_content_material.xml @@ -24,6 +24,7 @@ android:layout_width="match_parent"> <LinearLayout + android:id="@+id/prefs_container" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="0px" @@ -64,8 +65,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="@integer/preferences_right_pane_weight" - android:orientation="vertical" - android:visibility="gone" > + android:orientation="vertical"> <!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an empty layout or just padding, and PreferenceActivity will put the breadcrumbs in diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml index 02dc2ede430d..8101183d4e24 100644 --- a/core/res/res/layout/resolver_list_with_default.xml +++ b/core/res/res/layout/resolver_list_with_default.xml @@ -45,6 +45,7 @@ android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_marginTop="20dp" + android:src="@drawable/resolver_icon_placeholder" android:scaleType="fitCenter" /> <TextView diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 982405168523..de5fc9511010 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -517,6 +517,7 @@ <dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen> <!-- The elevation of AutoFill fill window--> - <dimen name="autofill_fill_elevation">2dp</dimen> + <dimen name="autofill_fill_elevation">4dp</dimen> <dimen name="autofill_fill_item_height">64dp</dimen> + <dimen name="autofill_fill_min_margin">16dp</dimen> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a420055884da..89269aad8277 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -120,6 +120,7 @@ <java-symbol type="id" name="permission_list" /> <java-symbol type="id" name="pickers" /> <java-symbol type="id" name="prefs" /> + <java-symbol type="id" name="prefs_container" /> <java-symbol type="id" name="prefs_frame" /> <java-symbol type="id" name="prev" /> <java-symbol type="id" name="progress" /> @@ -2834,6 +2835,7 @@ <!-- com.android.server.autofill --> <java-symbol type="dimen" name="autofill_fill_elevation" /> <java-symbol type="dimen" name="autofill_fill_item_height" /> + <java-symbol type="dimen" name="autofill_fill_min_margin" /> <java-symbol type="layout" name="autofill_save"/> <java-symbol type="id" name="autofill_save_title" /> <java-symbol type="id" name="autofill_save_no" /> @@ -2859,4 +2861,7 @@ <java-symbol type="drawable" name="btn_event_material"/> <java-symbol type="string" name="time_picker_text_input_mode_description"/> <java-symbol type="string" name="time_picker_radial_mode_description"/> + + <!-- resolver activity --> + <java-symbol type="drawable" name="resolver_icon_placeholder" /> </resources> diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java index f5cedfa26083..b49054550956 100644 --- a/graphics/java/android/graphics/RectF.java +++ b/graphics/java/android/graphics/RectF.java @@ -583,4 +583,17 @@ public class RectF implements Parcelable { right = in.readFloat(); bottom = in.readFloat(); } + + /** + * Scales up the rect by the given scale. + * @hide + */ + public void scale(float scale) { + if (scale != 1.0f) { + left = left * scale; + top = top * scale ; + right = right * scale; + bottom = bottom * scale; + } + } } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 5531871827a2..750ef3fa05f6 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -198,9 +198,10 @@ public class Typeface { } /** + * Used by resources for cached loading if the font is available. * @hide */ - public static Typeface createFromCache(AssetManager mgr, String path) { + public static Typeface findFromCache(AssetManager mgr, String path) { synchronized (sDynamicTypefaceCache) { final String key = createAssetUid(mgr, path); Typeface typeface = sDynamicTypefaceCache.get(key); @@ -221,6 +222,15 @@ public class Typeface { * @param callback A callback that will be triggered when results are obtained. May not be null. */ public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) { + // Check the cache first + // TODO: would the developer want to avoid a cache hit and always ask for the freshest + // result? + Typeface cachedTypeface = findFromCache( + request.getProviderAuthority(), request.getQuery()); + if (cachedTypeface != null) { + mHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface)); + return; + } synchronized (sLock) { if (sFontsContract == null) { sFontsContract = new FontsContract(); @@ -229,20 +239,34 @@ public class Typeface { final ResultReceiver receiver = new ResultReceiver(null) { @Override public void onReceiveResult(int resultCode, Bundle resultData) { - mHandler.post(new Runnable() { - @Override - public void run() { - receiveResult(request, callback, resultCode, resultData); - } - }); + mHandler.post(() -> receiveResult(request, callback, resultCode, resultData)); } }; sFontsContract.getFont(request, receiver); } } + private static Typeface findFromCache(String providerAuthority, String query) { + synchronized (sDynamicTypefaceCache) { + final String key = createProviderUid(providerAuthority, query); + Typeface typeface = sDynamicTypefaceCache.get(key); + if (typeface != null) { + return typeface; + } + } + return null; + } + private static void receiveResult(FontRequest request, FontRequestCallback callback, int resultCode, Bundle resultData) { + Typeface cachedTypeface = findFromCache( + request.getProviderAuthority(), request.getQuery()); + if (cachedTypeface != null) { + // We already know the result. + // Probably the requester requests the same font again in a short interval. + callback.onTypefaceRetrieved(cachedTypeface); + return; + } if (resultCode == FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND) { callback.onTypefaceRequestFailed( FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND); @@ -296,8 +320,12 @@ public class Typeface { } } fontFamily.freeze(); - callback.onTypefaceRetrieved(Typeface.createFromFamiliesWithDefault( - new FontFamily[] {fontFamily})); + Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily }); + synchronized (sDynamicTypefaceCache) { + String key = createProviderUid(request.getProviderAuthority(), request.getQuery()); + sDynamicTypefaceCache.put(key, typeface); + } + callback.onTypefaceRetrieved(typeface); } /** @@ -464,6 +492,7 @@ public class Typeface { private static String createAssetUid(final AssetManager mgr, String path) { final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers(); final StringBuilder builder = new StringBuilder(); + builder.append("asset:"); final int size = pkgs.size(); for (int i = 0; i < size; i++) { builder.append(pkgs.valueAt(i)); @@ -474,6 +503,18 @@ public class Typeface { } /** + * Creates a unique id for a given font provider and query. + */ + private static String createProviderUid(String authority, String query) { + final StringBuilder builder = new StringBuilder(); + builder.append("provider:"); + builder.append(authority); + builder.append("-"); + builder.append(query); + return builder.toString(); + } + + /** * Create a new typeface from the specified font file. * * @param path The path to the font data. diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 8a6e038d8e0d..5cf52c69f0fd 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -605,6 +605,7 @@ void GlopBuilder::build() { } else { mDescription.hasExternalTexture = true; } + mDescription.hasLinearTexture = mOutGlop->fill.texture.texture->isLinear(); } mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color; diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 1dad58fd64b9..71bee93fc4c7 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -205,6 +205,10 @@ void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end, *d++ = a * (start.g * oppAmount + end.g * amount); *d++ = a * (start.b * oppAmount + end.b * amount); #else + // What we're doing to the alpha channel here is technically incorrect + // but reproduces Android's old behavior when the alpha was pre-multiplied + // with gamma-encoded colors + a = EOCF_sRGB(a); *d++ = a * OECF_sRGB(start.r * oppAmount + end.r * amount); *d++ = a * OECF_sRGB(start.g * oppAmount + end.g * amount); *d++ = a * OECF_sRGB(start.b * oppAmount + end.b * amount); diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index e70982f5444a..5c8f8e93fa3d 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -87,6 +87,7 @@ namespace uirenderer { #define PROGRAM_HAS_ROUND_RECT_CLIP 43 #define PROGRAM_HAS_GAMMA_CORRECTION 44 +#define PROGRAM_HAS_LINEAR_TEXTURE 45 /////////////////////////////////////////////////////////////////////////////// // Types @@ -162,7 +163,10 @@ struct ProgramDescription { bool hasDebugHighlight; bool hasRoundRectClip; + // Extra gamma correction used for text bool hasGammaCorrection; + // Set when sampling an image in linear space + bool hasLinearTexture; /** * Resets this description. All fields are reset back to the default @@ -205,6 +209,7 @@ struct ProgramDescription { hasRoundRectClip = false; hasGammaCorrection = false; + hasLinearTexture = false; } /** @@ -275,6 +280,7 @@ struct ProgramDescription { if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT; if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP; if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION; + if (hasLinearTexture) key |= programid(0x1) << PROGRAM_HAS_LINEAR_TEXTURE; return key; } diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 71076791cf7f..00de9924ace1 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -161,27 +161,54 @@ const char* gFS_Uniforms_HasRoundRectClip = "uniform vec4 roundRectInnerRectLTRB;\n" "uniform float roundRectRadius;\n"; +const char* gFS_OETF[2] = { + "\nvec4 OETF(const vec4 linear) {\n" + " return linear;\n" + "}\n", + // We expect linear data to be scRGB so we mirror the gamma function + "\nvec4 OETF(const vec4 linear) {" + " return vec4(sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)), linear.a);\n" + "}\n", +}; + +const char* gFS_Transfer_Functions = R"__SHADER__( + float OETF_sRGB(const float linear) { + // IEC 61966-2-1:1999 + return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055; + } + + vec3 OETF_sRGB(const vec3 linear) { + return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b)); + } + + float EOTF_sRGB(float srgb) { + // IEC 61966-2-1:1999 + return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4); + } +)__SHADER__"; + // Dithering must be done in the quantization space // When we are writing to an sRGB framebuffer, we must do the following: -// EOCF(OECF(color) + dither) -// We approximate the transfer functions with gamma 2.0 to avoid branches and pow() +// EOTF(OETF(color) + dither) // The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0] // TODO: Handle linear fp16 render targets -const char* gFS_Gradient_Functions = - "\nfloat triangleNoise(const highp vec2 n) {\n" - " highp vec2 p = fract(n * vec2(5.3987, 5.4421));\n" - " p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));\n" - " highp float xy = p.x * p.y;\n" - " return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;\n" - "}\n"; +const char* gFS_Gradient_Functions = R"__SHADER__( + float triangleNoise(const highp vec2 n) { + highp vec2 p = fract(n * vec2(5.3987, 5.4421)); + p += dot(p.yx, p.xy + vec2(21.5351, 14.3137)); + highp float xy = p.x * p.y; + return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0; + } +)__SHADER__"; const char* gFS_Gradient_Preamble[2] = { // Linear framebuffer "\nvec4 dither(const vec4 color) {\n" " return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n" "}\n" "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n" - " vec4 c = pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));\n" - " return vec4(c.rgb * c.a, c.a);\n" + " vec4 c = mix(a, b, v);\n" + " c.a = EOTF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility + " return vec4(OETF_sRGB(c.rgb) * c.a, c.a);\n" "}\n", // sRGB framebuffer "\nvec4 dither(const vec4 color) {\n" @@ -200,13 +227,15 @@ const char* gFS_Gradient_Preamble[2] = { // The gamma coefficient is chosen to thicken or thin the text accordingly // The dot product used to compute the luminance could be approximated with // a simple max(color.r, color.g, color.b) -const char* gFS_Gamma_Preamble = - "\n#define GAMMA (%.2f)\n" - "#define GAMMA_INV (%.2f)\n" - "\nfloat gamma(float a, const vec3 color) {\n" - " float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));\n" - " return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);\n" - "}\n"; +const char* gFS_Gamma_Preamble = R"__SHADER__( + #define GAMMA (%.2f) + #define GAMMA_INV (%.2f) + + float gamma(float a, const vec3 color) { + float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722)); + return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA); + } +)__SHADER__"; const char* gFS_Main = "\nvoid main(void) {\n" @@ -215,52 +244,6 @@ const char* gFS_Main = const char* gFS_Main_AddDither = " fragColor = dither(fragColor);\n"; -// Fast cases -const char* gFS_Fast_SingleColor = - "\nvoid main(void) {\n" - " gl_FragColor = color;\n" - "}\n\n"; -const char* gFS_Fast_SingleTexture = - "\nvoid main(void) {\n" - " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" - "}\n\n"; -const char* gFS_Fast_SingleModulateTexture = - "\nvoid main(void) {\n" - " gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n" - "}\n\n"; -const char* gFS_Fast_SingleA8Texture = - "\nvoid main(void) {\n" - " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" - "}\n\n"; -const char* gFS_Fast_SingleA8Texture_ApplyGamma = - "\nvoid main(void) {\n" - " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, GAMMA));\n" - "}\n\n"; -const char* gFS_Fast_SingleModulateA8Texture = - "\nvoid main(void) {\n" - " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n" - "}\n\n"; -const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma = - "\nvoid main(void) {\n" - " gl_FragColor = color * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n" - "}\n\n"; -const char* gFS_Fast_SingleGradient[2] = { - "\nvoid main(void) {\n" - " gl_FragColor = dither(texture2D(gradientSampler, linear));\n" - "}\n\n", - "\nvoid main(void) {\n" - " gl_FragColor = dither(gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n" - "}\n\n", -}; -const char* gFS_Fast_SingleModulateGradient[2] = { - "\nvoid main(void) {\n" - " gl_FragColor = dither(color.a * texture2D(gradientSampler, linear));\n" - "}\n\n", - "\nvoid main(void) {\n" - " gl_FragColor = dither(color.a * gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n" - "}\n\n" -}; - // General case const char* gFS_Main_FetchColor = " fragColor = color;\n"; @@ -273,7 +256,7 @@ const char* gFS_Main_ApplyVertexAlphaShadowInterp = " fragColor *= texture2D(baseSampler, vec2(alpha, 0.5)).a;\n"; const char* gFS_Main_FetchTexture[2] = { // Don't modulate - " fragColor = texture2D(baseSampler, outTexCoords);\n", + " fragColor = OETF(texture2D(baseSampler, outTexCoords));\n", // Modulate " fragColor = color * texture2D(baseSampler, outTexCoords);\n" }; @@ -304,9 +287,9 @@ const char* gFS_Main_FetchGradient[6] = { " vec4 gradientColor = gammaMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n" }; const char* gFS_Main_FetchBitmap = - " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; + " vec4 bitmapColor = OETF(texture2D(bitmapSampler, outBitmapTexCoords));\n"; const char* gFS_Main_FetchBitmapNpot = - " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n"; + " vec4 bitmapColor = OETF(texture2D(bitmapSampler, wrap(outBitmapTexCoords)));\n"; const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)"; const char* gFS_Main_BlendShadersGB = @@ -632,71 +615,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma, 1.0f / Properties::textGamma); } - // Optimization for common cases - if (!description.hasVertexAlpha - && !blendFramebuffer - && !description.hasColors - && description.colorOp == ProgramDescription::ColorFilterMode::None - && !description.hasDebugHighlight - && !description.hasRoundRectClip) { - bool fast = false; - - const bool noShader = !description.hasGradient && !description.hasBitmap; - const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && - !description.hasAlpha8Texture && noShader; - const bool singleA8Texture = description.hasTexture && - description.hasAlpha8Texture && noShader; - const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && - description.hasGradient && !description.hasBitmap && - description.gradientType == ProgramDescription::kGradientLinear; - - if (singleColor) { - shader.append(gFS_Fast_SingleColor); - fast = true; - } else if (singleTexture) { - if (!description.modulate) { - shader.append(gFS_Fast_SingleTexture); - } else { - shader.append(gFS_Fast_SingleModulateTexture); - } - fast = true; - } else if (singleA8Texture) { - if (!description.modulate) { - if (description.hasGammaCorrection) { - shader.append(gFS_Fast_SingleA8Texture_ApplyGamma); - } else { - shader.append(gFS_Fast_SingleA8Texture); - } - } else { - if (description.hasGammaCorrection) { - shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma); - } else { - shader.append(gFS_Fast_SingleModulateA8Texture); - } - } - fast = true; - } else if (singleGradient) { - shader.append(gFS_Gradient_Functions); - shader.append(gFS_Gradient_Preamble[mHasSRGB]); - if (!description.modulate) { - shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]); - } else { - shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]); - } - fast = true; - } - - if (fast) { -#if DEBUG_PROGRAMS - PROGRAM_LOGD("*** Fast case:\n"); - PROGRAM_LOGD("*** Generated fragment shader:\n\n"); - printLongString(shader); -#endif - - return shader; - } - } - if (description.hasBitmap) { if (description.isShaderBitmapExternal) { shader.append(gFS_Uniforms_BitmapExternalSampler); @@ -719,6 +637,13 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.useShaderBasedWrap) { generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); } + if (description.hasGradient || description.hasLinearTexture) { + shader.append(gFS_Transfer_Functions); + } + if (description.hasBitmap || ((description.hasTexture || description.hasExternalTexture) && + !description.hasAlpha8Texture)) { + shader.append(gFS_OETF[description.hasLinearTexture && !mHasSRGB]); + } if (description.hasGradient) { shader.append(gFS_Gradient_Functions); shader.append(gFS_Gradient_Preamble[mHasSRGB]); @@ -810,10 +735,10 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // End the shader shader.append(gFS_Footer); -#if DEBUG_PROGRAMS +//#if DEBUG_PROGRAMS PROGRAM_LOGD("*** Generated fragment shader:\n\n"); printLongString(shader); -#endif +//#endif return shader; } diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp index 705395e1e2b7..50af9c8cd711 100644 --- a/libs/hwui/Texture.cpp +++ b/libs/hwui/Texture.cpp @@ -44,10 +44,14 @@ static int bytesPerPixel(GLint glFormat) { case GL_RGBA16F: return 8; default: - LOG_ALWAYS_FATAL("UNKNOWN FORMAT %d", glFormat); + LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat); } } +bool Texture::isLinear() const { + return mInternalFormat == GL_RGBA16F; +} + void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) { if (force || wrapS != mWrapS || wrapT != mWrapT) { diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index b8397ccade9c..ce9d4dc234a8 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -128,6 +128,11 @@ public: } /** + * Returns true if this texture uses a linear encoding format. + */ + bool isLinear() const; + + /** * Generation of the backing bitmap, */ uint32_t generation = 0; diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp index 5e937f3239ff..c1ca1e7ac28a 100644 --- a/libs/hwui/tests/common/TestContext.cpp +++ b/libs/hwui/tests/common/TestContext.cpp @@ -16,6 +16,8 @@ #include "tests/common/TestContext.h" +#include <cutils/trace.h> + namespace android { namespace uirenderer { namespace test { @@ -98,6 +100,11 @@ void TestContext::createOffscreenSurface() { } void TestContext::waitForVsync() { + // Hacky fix for not getting sysprop change callbacks + // We just poll the sysprop in vsync since it's when the UI thread is + // "idle" and shouldn't burn too much time + atrace_update_tags(); + if (mConsumer.get()) { BufferItem buffer; if (mConsumer->acquireBuffer(&buffer, 0, false) == OK) { diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp new file mode 100644 index 000000000000..a63a5852a9ff --- /dev/null +++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp @@ -0,0 +1,83 @@ +/* + * 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 "TestSceneBase.h" + +#include <SkColorMatrixFilter.h> +#include <SkGradientShader.h> + +class SimpleColorMatrixAnimation; + +static TestScene::Registrar _SimpleColorMatrix(TestScene::Info{ + "simpleColorMatrix", + "A color matrix shader benchmark for the simple scale/translate case, which has R, G, and B " + "all scaled and translated the same amount.", + TestScene::simpleCreateScene<SimpleColorMatrixAnimation> +}); + +class SimpleColorMatrixAnimation : public TestScene { +public: + std::vector< sp<RenderNode> > cards; + void createContent(int width, int height, Canvas& canvas) override { + canvas.drawColor(Color::White, SkBlendMode::kSrcOver); + + sp<RenderNode> card = createCard(0, 0, width, height); + canvas.drawRenderNode(card.get()); + cards.push_back(card); + } + void doFrame(int frameNr) override { + int curFrame = frameNr % 20; + for (size_t ci = 0; ci < cards.size(); ci++) { + cards[ci]->mutateStagingProperties().setTranslationX(curFrame); + cards[ci]->mutateStagingProperties().setTranslationY(curFrame); + cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); + } + } +private: + sp<RenderNode> createCard(int x, int y, int width, int height) { + return TestUtils::createNode(x, y, x + width, y + height, + [width, height](RenderProperties& props, Canvas& canvas) { + SkPaint paint; + float matrix[20] = { 0 }; + + // Simple scale/translate case where R, G, and B are all treated equivalently + matrix[SkColorMatrix::kR_Scale] = 1.1f; + matrix[SkColorMatrix::kG_Scale] = 1.1f; + matrix[SkColorMatrix::kB_Scale] = 1.1f; + matrix[SkColorMatrix::kA_Scale] = 0.5f; + + matrix[SkColorMatrix::kR_Trans] = 5.0f; + matrix[SkColorMatrix::kG_Trans] = 5.0f; + matrix[SkColorMatrix::kB_Trans] = 5.0f; + matrix[SkColorMatrix::kA_Trans] = 10.0f; + + paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix)); + + // set a shader so it's not likely for the matrix to be optimized away (since a clever + // enough renderer might apply it directly to the paint color) + float pos[] = { 0, 1 }; + SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(width, height) }; + SkColor colors[2] = { Color::DeepPurple_500, Color::DeepOrange_500 }; + paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, + SkShader::kClamp_TileMode)); + + // overdraw several times to emphasize shader cost + for (int i = 0; i < 10; i++) { + canvas.drawRect(i, i, width, height, paint); + } + }); + } +}; diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp new file mode 100644 index 000000000000..053eb6dee31c --- /dev/null +++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp @@ -0,0 +1,65 @@ +/* + * 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 "TestSceneBase.h" + +#include <SkGradientShader.h> + +class SimpleGradientAnimation; + +static TestScene::Registrar _SimpleGradient(TestScene::Info{ + "simpleGradient", + "A benchmark of shader performance of linear, 2 color gradients with black in them.", + TestScene::simpleCreateScene<SimpleGradientAnimation> +}); + +class SimpleGradientAnimation : public TestScene { +public: + std::vector< sp<RenderNode> > cards; + void createContent(int width, int height, Canvas& canvas) override { + canvas.drawColor(Color::White, SkBlendMode::kSrcOver); + + sp<RenderNode> card = createCard(0, 0, width, height); + canvas.drawRenderNode(card.get()); + cards.push_back(card); + } + void doFrame(int frameNr) override { + int curFrame = frameNr % 20; + for (size_t ci = 0; ci < cards.size(); ci++) { + cards[ci]->mutateStagingProperties().setTranslationX(curFrame); + cards[ci]->mutateStagingProperties().setTranslationY(curFrame); + cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); + } + } +private: + sp<RenderNode> createCard(int x, int y, int width, int height) { + return TestUtils::createNode(x, y, x + width, y + height, + [width, height](RenderProperties& props, Canvas& canvas) { + float pos[] = { 0, 1 }; + SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(width, height) }; + SkPaint paint; + // overdraw several times to emphasize shader cost + for (int i = 0; i < 10; i++) { + // use i%2 start position to pick 2 color combo with black in it + SkColor colors[3] = { Color::Transparent, Color::Black, Color::Cyan_500 }; + paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2, + SkShader::kClamp_TileMode)); + canvas.drawRect(i, i, width, height, paint); + } + }); + } +}; diff --git a/location/java/android/location/BatchedLocationCallback.java b/location/java/android/location/BatchedLocationCallback.java new file mode 100644 index 000000000000..f1c40ae256b7 --- /dev/null +++ b/location/java/android/location/BatchedLocationCallback.java @@ -0,0 +1,44 @@ +/* + * 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.location; + +import android.annotation.IntDef; +import android.annotation.SystemApi; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Used for receiving notifications from the LocationManager when + * the a batch of location is ready. These methods are called if the + * BatchedLocationCallback has been registered with the location manager service + * using the + * {@link LocationManager#registerGnssBatchedLocationCallback#startGnssBatch(long, + * boolean, BatchedLocationCallback, android.os.Handler)} method. + * @hide + */ +@SystemApi +public abstract class BatchedLocationCallback { + + /** + * Called when a new batch of locations is ready + * + * @param locations A list of all new locations (possibly zero of them.) + */ + public void onLocationBatch(List<Location> locations) {} +} diff --git a/location/java/android/location/BatchedLocationCallbackTransport.java b/location/java/android/location/BatchedLocationCallbackTransport.java new file mode 100644 index 000000000000..e00f855e9302 --- /dev/null +++ b/location/java/android/location/BatchedLocationCallbackTransport.java @@ -0,0 +1,66 @@ +/* + * 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.location; + +import android.content.Context; +import android.os.RemoteException; + +import java.util.List; + +/** + * A handler class to manage transport callbacks for {@link BatchedLocationCallback}. + * + * @hide + */ +class BatchedLocationCallbackTransport + extends LocalListenerHelper<BatchedLocationCallback> { + private final ILocationManager mLocationManager; + + private final IBatchedLocationCallback mCallbackTransport = new CallbackTransport(); + + public BatchedLocationCallbackTransport(Context context, ILocationManager locationManager) { + super(context, "BatchedLocationCallbackTransport"); + mLocationManager = locationManager; + } + + @Override + protected boolean registerWithServer() throws RemoteException { + return mLocationManager.addGnssBatchingCallback( + mCallbackTransport, + getContext().getPackageName()); + } + + @Override + protected void unregisterFromServer() throws RemoteException { + mLocationManager.removeGnssBatchingCallback(); + } + + private class CallbackTransport extends IBatchedLocationCallback.Stub { + @Override + public void onLocationBatch(final List<Location> locations) { + ListenerOperation<BatchedLocationCallback> operation = + new ListenerOperation<BatchedLocationCallback>() { + @Override + public void execute(BatchedLocationCallback callback) + throws RemoteException { + callback.onLocationBatch(locations); + } + }; + foreach(operation); + } + } +} diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java index aa26111a73e7..c7188aa34522 100644 --- a/location/java/android/location/GnssNavigationMessage.java +++ b/location/java/android/location/GnssNavigationMessage.java @@ -89,7 +89,7 @@ public final class GnssNavigationMessage implements Parcelable { */ public static abstract class Callback { /** - * The status of GNSS measurements event. + * The status of GNSS Navigation Message event. * @hide */ @Retention(RetentionPolicy.SOURCE) diff --git a/location/java/android/location/IBatchedLocationCallback.aidl b/location/java/android/location/IBatchedLocationCallback.aidl new file mode 100644 index 000000000000..dce9f964c010 --- /dev/null +++ b/location/java/android/location/IBatchedLocationCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.location.Location; + +import java.util.List; + +/** + * {@hide} + */ +oneway interface IBatchedLocationCallback +{ + void onLocationBatch(in List<Location> locations); +} diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index bc8b026222ed..fc31f326354f 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -21,6 +21,7 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.IBatchedLocationCallback; import android.location.IGnssMeasurementsListener; import android.location.IGnssStatusListener; import android.location.IGnssNavigationMessageListener; @@ -71,6 +72,13 @@ interface ILocationManager int getGnssYearOfHardware(); + int getGnssBatchSize(String packageName); + boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName); + void removeGnssBatchingCallback(); + boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName); + void flushGnssBatch(String packageName); + boolean stopGnssBatch(); + // --- deprecated --- List<String> getAllProviders(); List<String> getProviders(in Criteria criteria, boolean enabledOnly); @@ -99,6 +107,9 @@ interface ILocationManager // it need not be shared with other providers. void reportLocation(in Location location, boolean passive); + // Used when a (initially Gnss) Location batch arrives + void reportLocationBatch(in List<Location> locations); + // for reporting callback completion void locationCallbackFinished(ILocationListener listener); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 4e146268b256..f9385c6d3b7f 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -18,6 +18,7 @@ package android.location; import com.android.internal.location.ProviderProperties; +import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -59,13 +60,15 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION; * return location results, but the update rate will be throttled and the exact * location will be obfuscated to a coarse level of accuracy. */ -public class LocationManager { +public class LocationManager +{ private static final String TAG = "LocationManager"; private final Context mContext; private final ILocationManager mService; private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport; private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport; + private final BatchedLocationCallbackTransport mBatchedLocationCallbackTransport; private final HashMap<GpsStatus.Listener, GnssStatusListenerTransport> mGpsStatusListeners = new HashMap<>(); private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners = @@ -321,9 +324,13 @@ public class LocationManager { public LocationManager(Context context, ILocationManager service) { mService = service; mContext = context; - mGnssMeasurementCallbackTransport = new GnssMeasurementCallbackTransport(mContext, mService); + mGnssMeasurementCallbackTransport = + new GnssMeasurementCallbackTransport(mContext, mService); mGnssNavigationMessageCallbackTransport = new GnssNavigationMessageCallbackTransport(mContext, mService); + mBatchedLocationCallbackTransport = + new BatchedLocationCallbackTransport(mContext, mService); + } private LocationProvider createProvider(String name, ProviderProperties properties) { @@ -1878,7 +1885,8 @@ public class LocationManager { * No-op method to keep backward-compatibility. * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead. * @hide - * @deprecated use {@link #unregisterGnssNavigationMessageCallback(GnssMeasurements.Callback)} + * @deprecated use + * {@link #unregisterGnssNavigationMessageCallback(GnssNavigationMessage.Callback)} * instead */ @Deprecated @@ -1960,6 +1968,96 @@ public class LocationManager { } /** + * Returns the batch size (in number of Location objects) that are supported by the batching + * interface. + * + * @return Maximum number of location objects that can be returned + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) + public int getGnssBatchSize() { + try { + return mService.getGnssBatchSize(mContext.getPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Start hardware-batching of GNSS locations. This API is primarily used when the AP is + * asleep and the device can batch GNSS locations in the hardware. + * + * Note this is designed (as was the fused location interface before it) for a single user + * SystemApi - requests are not consolidated. Care should be taken when the System switches + * users that may have different batching requests, to stop hardware batching for one user, and + * restart it for the next. + * + * @param periodNanos Time interval, in nanoseconds, that the GNSS locations are requested + * within the batch + * @param wakeOnFifoFull True if the hardware batching should flush the locations in a + * a callback to the listener, when it's internal buffer is full. If + * set to false, the oldest location information is, instead, + * dropped when the buffer is full. + * @param callback The listener on which to return the batched locations + * @param handler The handler on which to process the callback + * + * @return True if batching was successfully started + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) + public boolean registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull, + BatchedLocationCallback callback, Handler handler) { + mBatchedLocationCallbackTransport.add(callback, handler); + + try { + return mService.startGnssBatch(periodNanos, wakeOnFifoFull, mContext.getPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Flush the batched GNSS locations. + * All GNSS locations currently ready in the batch are returned via the callback sent in + * startGnssBatch(), and the buffer containing the batched locations is cleared. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) + public void flushGnssBatch() { + try { + mService.flushGnssBatch(mContext.getPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Stop batching locations. This API is primarily used when the AP is + * asleep and the device can batch locations in the hardware. + * + * @param callback the specific callback class to remove from the transport layer + * + * @return True if batching was successfully started + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) + public boolean unregisterGnssBatchedLocationCallback(BatchedLocationCallback callback) { + + mBatchedLocationCallbackTransport.remove(callback); + + try { + return mService.stopGnssBatch(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Sends additional commands to a location provider. * Can be used to support provider specific extensions to the Location Manager API * diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index cd38b506aab9..9083c1630cca 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1956,7 +1956,13 @@ public class AudioTrack extends PlayerBase e.printStackTrace(); } baseSetStartDelayMs(0); - startImpl(); + try { + startImpl(); + } catch (IllegalStateException e) { + // fail silently for a state exception when it is happening after + // a delayed start, as the player state could have changed between the + // call to start() and the execution of startImpl() + } } }.start(); } diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 03dc2eab67a8..1a1d0f350696 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -1258,7 +1258,13 @@ public class MediaPlayer extends PlayerBase e.printStackTrace(); } baseSetStartDelayMs(0); - startImpl(); + try { + startImpl(); + } catch (IllegalStateException e) { + // fail silently for a state exception when it is happening after + // a delayed start, as the player state could have changed between the + // call to start() and the execution of startImpl() + } } }.start(); } diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index b0df0e47eda1..ddbd542ec037 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -362,6 +362,285 @@ public final class TvContract { String COLUMN_PACKAGE_NAME = "package_name"; } + /** + * Common base for the tables of TV programs. + */ + public interface BaseProgramColumns extends BaseTvColumns { + /** + * The ID of the TV channel that provides this TV program. + * + * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}. + * + * <p>This is a required field. + * + * <p>Type: INTEGER (long) + */ + public static final String COLUMN_CHANNEL_ID = "channel_id"; + + /** + * The title of this TV program. + * + * <p>If this program is an episodic TV show, it is recommended that the title is the series + * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or + * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER}, + * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in. + * + * <p>Type: TEXT + */ + public static final String COLUMN_TITLE = "title"; + + /** + * The season display number of this TV program for episodic TV shows. + * + * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value + * does not necessarily be numeric. (e.g. 12B) + * + * <p>Can be empty. + * + * <p>Type: TEXT + */ + public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; + + /** + * The title of the season for this TV program for episodic TV shows. + * + * <p>This is an optional field supplied only when the season has a special title + * (e.g. The Final Season). If provided, the applications should display it instead of + * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations. + * (e.g. for "The Final Season", displayed string should be "The Final Season", not + * "Season The Final Season"). When displaying multiple programs, the order should be based + * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists. + * + * <p>Can be empty. + * + * <p>Type: TEXT + */ + public static final String COLUMN_SEASON_TITLE = "season_title"; + + /** + * The episode display number of this TV program for episodic TV shows. + * + * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value + * does not necessarily be numeric. (e.g. 12B) + * + * <p>Can be empty. + * + * <p>Type: TEXT + */ + public static final String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; + + /** + * The episode title of this TV program for episodic TV shows. + * + * <p>Can be empty. + * + * <p>Type: TEXT + */ + public static final String COLUMN_EPISODE_TITLE = "episode_title"; + + /** + * The comma-separated canonical genre string of this TV program. + * + * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a + * text that can be stored in this column. Use {@link Genres#decode} to get the canonical + * genre strings from the text stored in the column. + * + * <p>Type: TEXT + * @see Genres + * @see Genres#encode + * @see Genres#decode + */ + public static final String COLUMN_CANONICAL_GENRE = "canonical_genre"; + + /** + * The short description of this TV program that is displayed to the user by default. + * + * <p>It is recommended to limit the length of the descriptions to 256 characters. + * + * <p>Type: TEXT + */ + public static final String COLUMN_SHORT_DESCRIPTION = "short_description"; + + /** + * The detailed, lengthy description of this TV program that is displayed only when the user + * wants to see more information. + * + * <p>TV input services should leave this field empty if they have no additional details + * beyond {@link #COLUMN_SHORT_DESCRIPTION}. + * + * <p>Type: TEXT + */ + public static final String COLUMN_LONG_DESCRIPTION = "long_description"; + + /** + * The width of the video for this TV program, in the unit of pixels. + * + * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video + * resolution of the current TV program. Can be empty if it is not known initially or the + * program does not convey any video such as the programs from type + * {@link Channels#SERVICE_TYPE_AUDIO} channels. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_VIDEO_WIDTH = "video_width"; + + /** + * The height of the video for this TV program, in the unit of pixels. + * + * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video + * resolution of the current TV program. Can be empty if it is not known initially or the + * program does not convey any video such as the programs from type + * {@link Channels#SERVICE_TYPE_AUDIO} channels. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_VIDEO_HEIGHT = "video_height"; + + /** + * The comma-separated audio languages of this TV program. + * + * <p>This is used to describe available audio languages included in the program. Use either + * ISO 639-1 or 639-2/T codes. + * + * <p>Type: TEXT + */ + public static final String COLUMN_AUDIO_LANGUAGE = "audio_language"; + + /** + * The comma-separated content ratings of this TV program. + * + * <p>This is used to describe the content rating(s) of this program. Each comma-separated + * content rating sub-string should be generated by calling + * {@link TvContentRating#flattenToString}. Note that in most cases the program content is + * rated by a single rating system, thus resulting in a corresponding single sub-string that + * does not require comma separation and multiple sub-strings appear only when the program + * content is rated by two or more content rating systems. If any of those ratings is + * specified as "blocked rating" in the user's parental control settings, the TV input + * service should block the current content and wait for the signal that it is okay to + * unblock. + * + * <p>Type: TEXT + */ + public static final String COLUMN_CONTENT_RATING = "content_rating"; + + /** + * The URI for the poster art of this TV program. + * + * <p>The data in the column must be a URL, or a URI in one of the following formats: + * + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) + * </li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * + * <p>Can be empty. + * + * <p>Type: TEXT + */ + public static final String COLUMN_POSTER_ART_URI = "poster_art_uri"; + + /** + * The URI for the thumbnail of this TV program. + * + * <p>The system can generate a thumbnail from the poster art if this column is not + * specified. Thus it is not necessary for TV input services to include a thumbnail if it is + * just a scaled image of the poster art. + * + * <p>The data in the column must be a URL, or a URI in one of the following formats: + * + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) + * </li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * + * <p>Can be empty. + * + * <p>Type: TEXT + */ + public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; + + /** + * The flag indicating whether this TV program is searchable or not. + * + * <p>The columns of searchable programs can be read by other applications that have proper + * permission. Care must be taken not to open sensitive data. + * + * <p>A value of 1 indicates that the program is searchable and its columns can be read by + * other applications, a value of 0 indicates that the program is hidden and its columns can + * be read only by the package that owns the program and the system. If not specified, this + * value is set to 1 (searchable) by default. + * + * <p>Type: INTEGER (boolean) + */ + public static final String COLUMN_SEARCHABLE = "searchable"; + + /** + * Internal data used by individual TV input services. + * + * <p>This is internal to the provider that inserted it, and should not be decoded by other + * apps. + * + * <p>Type: BLOB + */ + public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; + + /** + * Internal integer flag used by individual TV input services. + * + * <p>This is internal to the provider that inserted it, and should not be decoded by other + * apps. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; + + /** + * Internal integer flag used by individual TV input services. + * + * <p>This is internal to the provider that inserted it, and should not be decoded by other + * apps. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; + + /** + * Internal integer flag used by individual TV input services. + * + * <p>This is internal to the provider that inserted it, and should not be decoded by other + * apps. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; + + /** + * Internal integer flag used by individual TV input services. + * + * <p>This is internal to the provider that inserted it, and should not be decoded by other + * apps. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; + + /** + * The version number of this row entry used by TV input services. + * + * <p>This is best used by sync adapters to identify the rows to update. The number can be + * defined by individual TV input services. One may assign the same value as + * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV + * broadcast. + * + * <p>Type: INTEGER + */ + public static final String COLUMN_VERSION_NUMBER = "version_number"; + } + /** Column definitions for the TV channels table. */ public static final class Channels implements BaseTvColumns { @@ -1158,7 +1437,7 @@ public final class TvContract { * <p>By default, the query results will be sorted by * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} in ascending order. */ - public static final class Programs implements BaseTvColumns { + public static final class Programs implements BaseProgramColumns { /** The content:// style URI for this table. */ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" @@ -1471,17 +1750,6 @@ public final class TvContract { "REVIEW_RATING_STYLE_PERCENTAGE"; /** - * The ID of the TV channel that provides this TV program. - * - * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}. - * - * <p>This is a required field. - * - * <p>Type: INTEGER (long) - */ - public static final String COLUMN_CHANNEL_ID = "channel_id"; - - /** * The type of this program content. * * <p>The value should match one of the followings: @@ -1520,18 +1788,6 @@ public final class TvContract { public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type"; /** - * The title of this TV program. - * - * <p>If this program is an episodic TV show, it is recommended that the title is the series - * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or - * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER}, - * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in. - * - * <p>Type: TEXT - */ - public static final String COLUMN_TITLE = "title"; - - /** * The season number of this TV program for episodic TV shows. * * <p>Can be empty. @@ -1544,34 +1800,6 @@ public final class TvContract { public static final String COLUMN_SEASON_NUMBER = "season_number"; /** - * The season display number of this TV program for episodic TV shows. - * - * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value - * does not necessarily be numeric. (e.g. 12B) - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number"; - - /** - * The title of the season for this TV program for episodic TV shows. - * - * <p>This is an optional field supplied only when the season has a special title - * (e.g. The Final Season). If provided, the applications should display it instead of - * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations. - * (e.g. for "The Final Season", displayed string should be "The Final Season", not - * "Season The Final Season"). When displaying multiple programs, the order should be based - * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists. - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_SEASON_TITLE = "season_title"; - - /** * The episode number of this TV program for episodic TV shows. * * <p>Can be empty. @@ -1583,28 +1811,7 @@ public final class TvContract { @Deprecated public static final String COLUMN_EPISODE_NUMBER = "episode_number"; - /** - * The episode display number of this TV program for episodic TV shows. - * - * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value - * does not necessarily be numeric. (e.g. 12B) - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number"; - - /** - * The episode title of this TV program for episodic TV shows. - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_EPISODE_TITLE = "episode_title"; - - /** + /** * The start time of this TV program, in milliseconds since the epoch. * * <p>The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the @@ -1647,109 +1854,6 @@ public final class TvContract { public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre"; /** - * The comma-separated canonical genre string of this TV program. - * - * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a - * text that can be stored in this column. Use {@link Genres#decode} to get the canonical - * genre strings from the text stored in the column. - * - * <p>Type: TEXT - * @see Genres - * @see Genres#encode - * @see Genres#decode - */ - public static final String COLUMN_CANONICAL_GENRE = "canonical_genre"; - - /** - * The short description of this TV program that is displayed to the user by default. - * - * <p>It is recommended to limit the length of the descriptions to 256 characters. - * - * <p>Type: TEXT - */ - public static final String COLUMN_SHORT_DESCRIPTION = "short_description"; - - /** - * The detailed, lengthy description of this TV program that is displayed only when the user - * wants to see more information. - * - * <p>TV input services should leave this field empty if they have no additional details - * beyond {@link #COLUMN_SHORT_DESCRIPTION}. - * - * <p>Type: TEXT - */ - public static final String COLUMN_LONG_DESCRIPTION = "long_description"; - - /** - * The width of the video for this TV program, in the unit of pixels. - * - * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video - * resolution of the current TV program. Can be empty if it is not known initially or the - * program does not convey any video such as the programs from type - * {@link Channels#SERVICE_TYPE_AUDIO} channels. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_VIDEO_WIDTH = "video_width"; - - /** - * The height of the video for this TV program, in the unit of pixels. - * - * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video - * resolution of the current TV program. Can be empty if it is not known initially or the - * program does not convey any video such as the programs from type - * {@link Channels#SERVICE_TYPE_AUDIO} channels. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_VIDEO_HEIGHT = "video_height"; - - /** - * The comma-separated audio languages of this TV program. - * - * <p>This is used to describe available audio languages included in the program. Use either - * ISO 639-1 or 639-2/T codes. - * - * <p>Type: TEXT - */ - public static final String COLUMN_AUDIO_LANGUAGE = "audio_language"; - - /** - * The comma-separated content ratings of this TV program. - * - * <p>This is used to describe the content rating(s) of this program. Each comma-separated - * content rating sub-string should be generated by calling - * {@link TvContentRating#flattenToString}. Note that in most cases the program content is - * rated by a single rating system, thus resulting in a corresponding single sub-string that - * does not require comma separation and multiple sub-strings appear only when the program - * content is rated by two or more content rating systems. If any of those ratings is - * specified as "blocked rating" in the user's parental control settings, the TV input - * service should block the current content and wait for the signal that it is okay to - * unblock. - * - * <p>Type: TEXT - */ - public static final String COLUMN_CONTENT_RATING = "content_rating"; - - /** - * The URI for the poster art of this TV program. - * - * <p>The data in the column must be a URL, or a URI in one of the following formats: - * - * <ul> - * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> - * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) - * </li> - * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> - * </ul> - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_POSTER_ART_URI = "poster_art_uri"; - - /** * The aspect ratio of the poster art for this TV program. * * <p>The value should match one of the followings: @@ -1763,28 +1867,6 @@ public final class TvContract { public static final String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio"; /** - * The URI for the thumbnail of this TV program. - * - * <p>The system can generate a thumbnail from the poster art if this column is not - * specified. Thus it is not necessary for TV input services to include a thumbnail if it is - * just a scaled image of the poster art. - * - * <p>The data in the column must be a URL, or a URI in one of the following formats: - * - * <ul> - * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> - * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) - * </li> - * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> - * </ul> - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri"; - - /** * The aspect ratio of the thumbnail for this TV program. * * <p>The value should match one of the followings: @@ -1883,21 +1965,6 @@ public final class TvContract { public static final String COLUMN_LIVE = "live"; /** - * The flag indicating whether this TV program is searchable or not. - * - * <p>The columns of searchable programs can be read by other applications that have proper - * permission. Care must be taken not to open sensitive data. - * - * <p>A value of 1 indicates that the program is searchable and its columns can be read by - * other applications, a value of 0 indicates that the program is hidden and its columns can - * be read only by the package that owns the program and the system. If not specified, this - * value is set to 1 (searchable) by default. - * - * <p>Type: INTEGER (boolean) - */ - public static final String COLUMN_SEARCHABLE = "searchable"; - - /** * The flag indicating whether recording of this program is prohibited. * * <p>A value of 1 indicates that recording of this program is prohibited and application @@ -1910,68 +1977,6 @@ public final class TvContract { public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited"; /** - * Internal data used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: BLOB - */ - public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data"; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1"; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2"; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3"; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4"; - - /** - * The version number of this row entry used by TV input services. - * - * <p>This is best used by sync adapters to identify the rows to update. The number can be - * defined by individual TV input services. One may assign the same value as - * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV - * broadcast. - * - * <p>Type: INTEGER - */ - public static final String COLUMN_VERSION_NUMBER = "version_number"; - - /** * The internal ID used by individual TV input services. * * <p>This is internal to the provider that inserted it, and should not be decoded by other @@ -2341,7 +2346,7 @@ public final class TvContract { * <p>By default, the query results will be sorted by {@link #COLUMN_START_TIME_UTC_MILLIS} in * ascending order. */ - public static final class RecordedPrograms implements BaseTvColumns { + public static final class RecordedPrograms implements BaseProgramColumns { /** The content:// style URI for this table. */ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" @@ -2365,83 +2370,6 @@ public final class TvContract { public static final String COLUMN_INPUT_ID = "input_id"; /** - * The ID of the TV channel that provided this recorded TV program. - * - * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}. - * - * <p>This is a required field. - * - * <p>Type: INTEGER (long) - * @see Programs#COLUMN_CHANNEL_ID - */ - public static final String COLUMN_CHANNEL_ID = Programs.COLUMN_CHANNEL_ID; - - /** - * The title of this recorded TV program. - * - * <p>If this recorded program is an episodic TV show, it is recommended that the title is - * the series title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or - * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, - * and {@link #COLUMN_EPISODE_TITLE}) are filled in. - * - * <p>Type: TEXT - * @see Programs#COLUMN_TITLE - */ - public static final String COLUMN_TITLE = Programs.COLUMN_TITLE; - - /** - * The season display number of this recorded TV program for episodic TV shows. - * - * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value - * does not necessarily be numeric. (e.g. 12B) - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_SEASON_DISPLAY_NUMBER = - Programs.COLUMN_SEASON_DISPLAY_NUMBER; - - /** - * The title of the season for this recorded TV program for episodic TV shows. - * - * <p>This is an optional field supplied only when the season has a special title - * (e.g. The Final Season). If provided, the applications should display it instead of - * {@link #COLUMN_SEASON_DISPLAY_NUMBER} without alterations. - * (e.g. for "The Final Season", displayed string should be "The Final Season", not - * "Season The Final Season"). When displaying multiple programs, the order should be based - * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists. - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_SEASON_TITLE = Programs.COLUMN_SEASON_TITLE; - - /** - * The episode display number of this recorded TV program for episodic TV shows. - * - * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value - * does not necessarily be numeric. (e.g. 12B) - * - * <p>Can be empty. - * - * <p>Type: TEXT - */ - public static final String COLUMN_EPISODE_DISPLAY_NUMBER = - Programs.COLUMN_EPISODE_DISPLAY_NUMBER; - - /** - * The episode title of this recorded TV program for episodic TV shows. - * - * <p>Can be empty. - * - * <p>Type: TEXT - * @see Programs#COLUMN_EPISODE_TITLE - */ - public static final String COLUMN_EPISODE_TITLE = Programs.COLUMN_EPISODE_TITLE; - - /** * The start time of the original TV program, in milliseconds since the epoch. * * <p>Type: INTEGER (long) @@ -2474,154 +2402,6 @@ public final class TvContract { public static final String COLUMN_BROADCAST_GENRE = Programs.COLUMN_BROADCAST_GENRE; /** - * The comma-separated canonical genre string of this recorded TV program. - * - * <p>Canonical genres are defined in {@link Programs.Genres}. Use - * {@link Programs.Genres#encode Genres.encode()} to create a text that can be stored in - * this column. Use {@link Programs.Genres#decode Genres.decode()} to get the canonical - * genre strings from the text stored in the column. - * - * <p>Type: TEXT - * @see Programs#COLUMN_CANONICAL_GENRE - * @see Programs.Genres - */ - public static final String COLUMN_CANONICAL_GENRE = Programs.COLUMN_CANONICAL_GENRE; - - /** - * The short description of this recorded TV program that is displayed to the user by - * default. - * - * <p>It is recommended to limit the length of the descriptions to 256 characters. - * - * <p>Type: TEXT - * @see Programs#COLUMN_SHORT_DESCRIPTION - */ - public static final String COLUMN_SHORT_DESCRIPTION = Programs.COLUMN_SHORT_DESCRIPTION; - - /** - * The detailed, lengthy description of this recorded TV program that is displayed only when - * the user wants to see more information. - * - * <p>TV input services should leave this field empty if they have no additional details - * beyond {@link #COLUMN_SHORT_DESCRIPTION}. - * - * <p>Type: TEXT - * @see Programs#COLUMN_LONG_DESCRIPTION - */ - public static final String COLUMN_LONG_DESCRIPTION = Programs.COLUMN_LONG_DESCRIPTION; - - /** - * The width of the video for this recorded TV program, in the unit of pixels. - * - * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video - * resolution of the current recorded TV program. Can be empty if it is not known or the - * recorded program does not convey any video. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_VIDEO_WIDTH - */ - public static final String COLUMN_VIDEO_WIDTH = Programs.COLUMN_VIDEO_WIDTH; - - /** - * The height of the video for this recorded TV program, in the unit of pixels. - * - * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video - * resolution of the current recorded TV program. Can be empty if it is not known or the - * recorded program does not convey any video. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_VIDEO_HEIGHT - */ - public static final String COLUMN_VIDEO_HEIGHT = Programs.COLUMN_VIDEO_HEIGHT; - - /** - * The comma-separated audio languages of this recorded TV program. - * - * <p>This is used to describe available audio languages included in the recorded program. - * Use either ISO 639-1 or 639-2/T codes. - * - * <p>Type: TEXT - * @see Programs#COLUMN_AUDIO_LANGUAGE - */ - public static final String COLUMN_AUDIO_LANGUAGE = Programs.COLUMN_AUDIO_LANGUAGE; - - /** - * The comma-separated content ratings of this recorded TV program. - * - * <p>This is used to describe the content rating(s) of this recorded program. Each - * comma-separated content rating sub-string should be generated by calling - * {@link TvContentRating#flattenToString}. Note that in most cases the recorded program - * content is rated by a single rating system, thus resulting in a corresponding single - * sub-string that does not require comma separation and multiple sub-strings appear only - * when the recorded program content is rated by two or more content rating systems. If any - * of those ratings is specified as "blocked rating" in the user's parental control - * settings, the TV input service should block the current content and wait for the signal - * that it is okay to unblock. - * - * <p>Type: TEXT - * @see Programs#COLUMN_CONTENT_RATING - */ - public static final String COLUMN_CONTENT_RATING = Programs.COLUMN_CONTENT_RATING; - - /** - * The URI for the poster art of this recorded TV program. - * - * <p>The data in the column must be a URL, or a URI in one of the following formats: - * - * <ul> - * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> - * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) - * </li> - * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> - * </ul> - * - * <p>Can be empty. - * - * <p>Type: TEXT - * @see Programs#COLUMN_POSTER_ART_URI - */ - public static final String COLUMN_POSTER_ART_URI = Programs.COLUMN_POSTER_ART_URI; - - /** - * The URI for the thumbnail of this recorded TV program. - * - * <p>The system can generate a thumbnail from the poster art if this column is not - * specified. Thus it is not necessary for TV input services to include a thumbnail if it is - * just a scaled image of the poster art. - * - * <p>The data in the column must be a URL, or a URI in one of the following formats: - * - * <ul> - * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> - * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) - * </li> - * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> - * </ul> - * - * <p>Can be empty. - * - * <p>Type: TEXT - * @see Programs#COLUMN_THUMBNAIL_URI - */ - public static final String COLUMN_THUMBNAIL_URI = Programs.COLUMN_THUMBNAIL_URI; - - /** - * The flag indicating whether this recorded TV program is searchable or not. - * - * <p>The columns of searchable recorded programs can be read by other applications that - * have proper permission. Care must be taken not to open sensitive data. - * - * <p>A value of 1 indicates that the recorded program is searchable and its columns can be - * read by other applications, a value of 0 indicates that the recorded program is hidden - * and its columns can be read only by the package that owns the recorded program and the - * system. If not specified, this value is set to 1 (searchable) by default. - * - * <p>Type: INTEGER (boolean) - * @see Programs#COLUMN_SEARCHABLE - */ - public static final String COLUMN_SEARCHABLE = Programs.COLUMN_SEARCHABLE; - - /** * The URI of the recording data for this recorded program. * * <p>Together with {@link #COLUMN_RECORDING_DATA_BYTES}, applications can use this @@ -2671,80 +2451,6 @@ public final class TvContract { public static final String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis"; - - /** - * Internal data used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: BLOB - * @see Programs#COLUMN_INTERNAL_PROVIDER_DATA - */ - public static final String COLUMN_INTERNAL_PROVIDER_DATA = - Programs.COLUMN_INTERNAL_PROVIDER_DATA; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG1 - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = - Programs.COLUMN_INTERNAL_PROVIDER_FLAG1; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG2 - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = - Programs.COLUMN_INTERNAL_PROVIDER_FLAG2; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG3 - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = - Programs.COLUMN_INTERNAL_PROVIDER_FLAG3; - - /** - * Internal integer flag used by individual TV input services. - * - * <p>This is internal to the provider that inserted it, and should not be decoded by other - * apps. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG4 - */ - public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = - Programs.COLUMN_INTERNAL_PROVIDER_FLAG4; - - /** - * The version number of this row entry used by TV input services. - * - * <p>This is best used by sync adapters to identify the rows to update. The number can be - * defined by individual TV input services. One may assign the same value as - * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV - * broadcast. - * - * <p>Type: INTEGER - * @see Programs#COLUMN_VERSION_NUMBER - */ - public static final String COLUMN_VERSION_NUMBER = Programs.COLUMN_VERSION_NUMBER; - private RecordedPrograms() {} } diff --git a/native/android/hardware_buffer.cpp b/native/android/hardware_buffer.cpp index 2f75c10d6764..e5e928dee2a7 100644 --- a/native/android/hardware_buffer.cpp +++ b/native/android/hardware_buffer.cpp @@ -26,10 +26,11 @@ #include <android_runtime/android_hardware_HardwareBuffer.h> #include <binder/Binder.h> #include <binder/Parcel.h> -#include <cutils/native_handle.h> #include <binder/IServiceManager.h> +#include <cutils/native_handle.h> #include <gui/ISurfaceComposer.h> #include <gui/IGraphicBufferAlloc.h> +#include <hardware/gralloc1.h> #include <ui/GraphicBuffer.h> #include <utils/Flattenable.h> #include <utils/Log.h> @@ -96,10 +97,14 @@ int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, } status_t err; - uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits( - desc->usage0, desc->usage1); + uint64_t producerUsage = 0; + uint64_t consumerUsage = 0; + android_hardware_HardwareBuffer_convertToGrallocUsageBits(desc->usage0, + desc->usage1, &producerUsage, &consumerUsage); sp<GraphicBuffer> gbuffer = allocator->createGraphicBuffer(desc->width, - desc->height, format, desc->layers, usage, &err); + desc->height, format, desc->layers, producerUsage, consumerUsage, + std::string("AHardwareBuffer pid [") + std::to_string(getpid()) + + "]", &err); if (err != NO_ERROR) { return err; } @@ -131,7 +136,7 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, outDesc->layers = gbuffer->getLayerCount(); outDesc->usage0 = android_hardware_HardwareBuffer_convertFromGrallocUsageBits( - gbuffer->getUsage()); + gbuffer->getUsage(), gbuffer->getUsage()); outDesc->usage1 = 0; outDesc->format = android_hardware_HardwareBuffer_convertFromPixelFormat( static_cast<uint32_t>(gbuffer->getPixelFormat())); @@ -148,15 +153,19 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage0, return BAD_VALUE; } - uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits( - usage0, 0); + uint64_t producerUsage = 0; + uint64_t consumerUsage = 0; + android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage0, 0, + &producerUsage, &consumerUsage); GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer); + Rect bounds; if (!rect) { - return gBuffer->lockAsync(usage, outVirtualAddress, fence); + bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); } else { - Rect bounds(rect->left, rect->top, rect->right, rect->bottom); - return gBuffer->lockAsync(usage, bounds, outVirtualAddress, fence); + bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); } + return gBuffer->lockAsync(producerUsage, consumerUsage, bounds, + outVirtualAddress, fence); } int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { diff --git a/packages/SettingsLib/res/color/batterymeter_bolt_color.xml b/packages/SettingsLib/res/color/batterymeter_bolt_color.xml new file mode 100644 index 000000000000..34de5489a28b --- /dev/null +++ b/packages/SettingsLib/res/color/batterymeter_bolt_color.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="0.3" android:color="?android:attr/colorForeground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/color/batterymeter_charge_color.xml b/packages/SettingsLib/res/color/batterymeter_charge_color.xml new file mode 100644 index 000000000000..15944c3a2a07 --- /dev/null +++ b/packages/SettingsLib/res/color/batterymeter_charge_color.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="?android:attr/colorForeground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/color/batterymeter_frame_color.xml b/packages/SettingsLib/res/color/batterymeter_frame_color.xml new file mode 100644 index 000000000000..34de5489a28b --- /dev/null +++ b/packages/SettingsLib/res/color/batterymeter_frame_color.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="0.3" android:color="?android:attr/colorForeground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml new file mode 100644 index 000000000000..c8a80ac57c00 --- /dev/null +++ b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="0.24" android:color="?android:attr/colorBackground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml new file mode 100644 index 000000000000..8dcfdbb8cf1e --- /dev/null +++ b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="0.47" android:color="?android:attr/colorBackground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml new file mode 100644 index 000000000000..34de5489a28b --- /dev/null +++ b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="0.3" android:color="?android:attr/colorForeground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml new file mode 100644 index 000000000000..15944c3a2a07 --- /dev/null +++ b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="?android:attr/colorForeground" /> +</selector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml index 01ba2cdf9a01..b40bfd4662ba 100644 --- a/packages/SettingsLib/res/values-bn/arrays.xml +++ b/packages/SettingsLib/res/values-bn/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"শুধুমাত্র DRM সামগ্রীর জন্য HDCP চেক করা ব্যবহার করুন"</item> <item msgid="45075631231212732">"সর্বদা HDCP পরীক্ষণ ব্যবহার করুন"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> <item msgid="8895532488906185219">"৪৪.১ kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"মোনো"</item> <item msgid="8883739882299884241">"স্টিরিও"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"অডিও গুণমানের জন্য অপ্টিমাইজ করা হয়েছে (৯৯০kbps/৯০৯kbps)"</item> + <item msgid="2921767058740704969">"সন্তুলিত গুণমানের অডিও এবং সংযোগ (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"সংযোগের গুণমানের জন্য অপটিমাইজ করা হয়েছে (৩৩০kbps/৩০৩kbps)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"অডিও গুণমানের জন্য অপ্টিমাইজ করা হয়েছে"</item> + <item msgid="4327143584633311908">"সন্তুলিত গুণমানের অডিও এবং সংযোগ"</item> + <item msgid="4681409244565426925">"সংযোগের গুণমানের জন্য অপটিমাইজ করা হয়েছে"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"বন্ধ আছে"</item> <item msgid="1593289376502312923">"৬৪K"</item> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 8350bb761636..08f72276ef61 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -53,7 +53,7 @@ <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"পরিচিতি শেয়ার করার কাজে ব্যবহার করুন"</string> <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"ইন্টারনেট সংযোগ শেয়ার করা হচ্ছে"</string> <string name="bluetooth_profile_map" msgid="5465271250454324383">"বার্তা অ্যাক্সেস"</string> - <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM -এর অ্যাক্সেস"</string> + <string name="bluetooth_profile_sap" msgid="5764222021851283125">"সিম -এর অ্যাক্সেস"</string> <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"মিডিয়া অডিওতে সংযুক্ত রয়েছে"</string> <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ফোন অডিওতে সংযুক্ত"</string> <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ফাইল স্থানান্তর সার্ভারের সঙ্গে সংযুক্ত"</string> @@ -65,7 +65,7 @@ <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"ডিভাইসের সাথে স্থানীয় ইন্টারনেট সংযোগ ভাগ করছে"</string> <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"ইন্টারনেট অ্যাক্সেসের জন্য ব্যবহার করুন"</string> <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"মানচিত্রের জন্য ব্যবহার করুন"</string> - <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM -এর অ্যাক্সেসের জন্য ব্যবহার করুন"</string> + <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"সিম -এর অ্যাক্সেসের জন্য ব্যবহার করুন"</string> <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"মিডিয়া অডিওয়ের জন্য ব্যবহার করুন"</string> <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফোন অডিওয়ের জন্য ব্যবহার করুন"</string> <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string> diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml index f27f2650cb05..1c3d3bf75ff3 100644 --- a/packages/SettingsLib/res/values-bs/arrays.xml +++ b/packages/SettingsLib/res/values-bs/arrays.xml @@ -111,9 +111,9 @@ <item msgid="8883739882299884241">"Stereo"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> - <item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990kbps/909kbps)"</item> + <item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990 kbps/909 kbps)"</item> <item msgid="2921767058740704969">"Uravnotežen kvalitet zvuka i veze (660kbps/606kbps)"</item> - <item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330kbps/303kbps)"</item> + <item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330 kbps/303 kbps)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> <item msgid="6398189564246596868">"Optimizirano za kvalitet zvuka"</item> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 2d3639769985..8071c83203ae 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -202,7 +202,7 @@ <string name="adb_keys_warning_message" msgid="5659849457135841625">"Vil du ophæve adgangen til USB-fejlfinding for alle computere, du tidligere har godkendt?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Vil du tillade udviklingsindstillinger?"</string> <string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse indstillinger er kun beregnet til brug i forbindelse med udvikling. De kan forårsage, at din enhed og dens applikationer går ned eller ikke fungerer korrekt."</string> - <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Kontrollér apps via USB"</string> + <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificer apps via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollér apps, der er installeret via ADB/ADT, for skadelig adfærd."</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string> diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml index 3493c086115a..d5155c9e4a33 100644 --- a/packages/SettingsLib/res/values-es/arrays.xml +++ b/packages/SettingsLib/res/values-es/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"Utilizar comprobación de HDCP solo para contenido DRM"</item> <item msgid="45075631231212732">"Utilizar siempre comprobación de HDCP"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"Usar preferencia del sistema (predeter.)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"Usar preferencia del sistema (predeter.)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Usar preferencia del sistema (predeter.)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"Mono"</item> <item msgid="8883739882299884241">"Estéreo"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"Optimizado para la calidad del audio (990 kbps/909 kbps)"</item> + <item msgid="2921767058740704969">"Equilibrar la calidad del audio y de la conexión (660/606&nbsp;kbps)"</item> + <item msgid="8860982705384396512">"Optimizado para la calidad de la conexión (330 kbps/303 kbps)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"Se ha optimizado para la calidad del audio"</item> + <item msgid="4327143584633311908">"Equilibrar la calidad del audio y la de la conexión"</item> + <item msgid="4681409244565426925">"Se ha optimizado para la calidad de la conexión"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"No"</item> <item msgid="1593289376502312923">"64 K"</item> diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml index 4148a4e8b69e..e4bcf4824432 100644 --- a/packages/SettingsLib/res/values-eu/arrays.xml +++ b/packages/SettingsLib/res/values-eu/arrays.xml @@ -111,9 +111,9 @@ <item msgid="8883739882299884241">"Estereoa"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> - <item msgid="7158319962230727476">"Audioaren kalitatea areagotzeko optimizatua (990 kb/s / 909 kb/s)"</item> - <item msgid="2921767058740704969">"Orekatu audioaren eta konexioaren kalitateak (660 kbps / 606 kbps)"</item> - <item msgid="8860982705384396512">"Konexioaren kalitatea areagotzeko optimizatua (330 kb/s / 303 kb/s)"</item> + <item msgid="7158319962230727476">"Audioaren kalitatea areagotzeko optimizatua (990 Kb/s / 909 Kb/s)"</item> + <item msgid="2921767058740704969">"Audioaren eta konexioaren kalitate orekatua (660 Kb/s / 606 Kb/s)"</item> + <item msgid="8860982705384396512">"Konexioaren kalitatea areagotzeko optimizatua (330 Kb/s / 303 Kb/s)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> <item msgid="6398189564246596868">"Audioaren kalitatea areagotzeko optimizatua"</item> diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml index e8711985ffe6..6eb4321653b6 100644 --- a/packages/SettingsLib/res/values-gu/arrays.xml +++ b/packages/SettingsLib/res/values-gu/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"ફક્ત DRM સામગ્રી માટે HDCP તપાસનો ઉપયોગ કરો"</item> <item msgid="45075631231212732">"હંમેશા HDCP તપાસનો ઉપયોગ કરો"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"મૉનો"</item> <item msgid="8883739882299884241">"સ્ટીરિઓ"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"ઑડિઓની ગુણવત્તા (990 kbps/909 kbps) માટે ઓપ્ટિમાઇઝ કર્યું"</item> + <item msgid="2921767058740704969">"સંતુલિત ઑડિઓ અને કનેક્શનની ગુણવત્તા (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"કનેક્શનની ગુણવત્તા (330 kbps/303 kbps) માટે ઓપ્ટિમાઇઝ કર્યું"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"ઑડિઓની ગુણવત્તા માટે ઓપ્ટિમાઇઝ કર્યું"</item> + <item msgid="4327143584633311908">"સંતુલિત ઑડિઓ અને કનેક્શનની ગુણવત્તા"</item> + <item msgid="4681409244565426925">"કનેક્શનની ગુણવત્તા માટે ઓપ્ટિમાઇઝ કર્યું"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"બંધ"</item> <item msgid="1593289376502312923">"64K"</item> diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml index 88f6e7886b30..8925f32ea728 100644 --- a/packages/SettingsLib/res/values-hy/arrays.xml +++ b/packages/SettingsLib/res/values-hy/arrays.xml @@ -111,12 +111,12 @@ <item msgid="8883739882299884241">"Ստերեո"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> - <item msgid="7158319962230727476">"Օպտիմալացված ձայնի որակ համար (990 կբ/վ / 909 կբ/վ)"</item> + <item msgid="7158319962230727476">"Օպտիմալացված ձայնի որակի համար (990 կբ/վ / 909 կբ/վ)"</item> <item msgid="2921767058740704969">"Ձայնի և կապի հավասարակշռված որակ (660 կբ/վ / 606 կբ/վ)"</item> <item msgid="8860982705384396512">"Օպտիմալացված կապի որակի համար (330 կբ/վ / 303 կբ/վ)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> - <item msgid="6398189564246596868">"Օպտիմալացված ձայնի որակ համար"</item> + <item msgid="6398189564246596868">"Օպտիմալացված ձայնի որակի համար"</item> <item msgid="4327143584633311908">"Ձայնի և կապի հավասարակշռված որակ"</item> <item msgid="4681409244565426925">"Օպտիմալացված կապի որակի համար"</item> </string-array> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 12d61fe4c930..186b79c0f2de 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -140,10 +140,10 @@ <string name="choose_profile" msgid="8229363046053568878">"Pilih Profil"</string> <string name="category_personal" msgid="1299663247844969448">"Pribadi"</string> <string name="category_work" msgid="8699184680584175622">"Kantor"</string> - <string name="development_settings_title" msgid="215179176067683667">"Opsi pengembang"</string> - <string name="development_settings_enable" msgid="542530994778109538">"Aktifkan opsi pengembang"</string> + <string name="development_settings_title" msgid="215179176067683667">"Opsi developer"</string> + <string name="development_settings_enable" msgid="542530994778109538">"Aktifkan opsi developer"</string> <string name="development_settings_summary" msgid="1815795401632854041">"Menyetel opsi untuk pengembangan apl"</string> - <string name="development_settings_not_available" msgid="4308569041701535607">"Opsi pengembang tidak tersedia untuk pengguna ini"</string> + <string name="development_settings_not_available" msgid="4308569041701535607">"Opsi developer tidak tersedia untuk pengguna ini"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"Setelan VPN tidak tersedia untuk pengguna ini"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"Setelan Penambatan tidak tersedia untuk pengguna ini"</string> <string name="apn_settings_not_available" msgid="7873729032165324000">"Setelan Nama Titik Akses tidak tersedia untuk pengguna ini"</string> diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml index 73851a4229fd..c729b42eedcb 100644 --- a/packages/SettingsLib/res/values-kn/arrays.xml +++ b/packages/SettingsLib/res/values-kn/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"DRM ವಿಷಯಗಳಿಗೆ ಮಾತ್ರ HDCP ಪರೀಕ್ಷಿಸುವಿಕೆಯನ್ನು ಬಳಸು"</item> <item msgid="45075631231212732">"HDCP ಪರಿಶೀಲನೆಯನ್ನು ಯಾವಾಗಲೂ ಬಳಸು"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"ಮೊನೊ"</item> <item msgid="8883739882299884241">"ಸ್ಟೀರಿಯೊ"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"ಆಡಿಯೋ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ (990kbps/909kbps) ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item> + <item msgid="2921767058740704969">"ಸಂತುಲಿತ ಆಡಿಯೊ ಮತ್ತು ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟ (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ (330kbps/303kbps) ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"ಆಡಿಯೊ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item> + <item msgid="4327143584633311908">"ಸಂತುಲಿತ ಆಡಿಯೊ ಮತ್ತು ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟ"</item> + <item msgid="4681409244565426925">"ಸಂಪರ್ಕ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"ಆಫ್"</item> <item msgid="1593289376502312923">"64K"</item> diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml index f00ebe50bd5c..4d1a685806ea 100644 --- a/packages/SettingsLib/res/values-ky/arrays.xml +++ b/packages/SettingsLib/res/values-ky/arrays.xml @@ -111,14 +111,14 @@ <item msgid="8883739882299884241">"Стерео"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> - <item msgid="7158319962230727476">"Аудио сапаты үчүн оптималдаштырылды (990кб/сек./909кб/сек.)"</item> + <item msgid="7158319962230727476">"Аудионун сапатын оптималдаштыруу (990кб/сек./909кб/сек.)"</item> <item msgid="2921767058740704969">"Теңделген аудио жана туташуу сапаты (660кб/сек./606кб/сек.)"</item> - <item msgid="8860982705384396512">"Туташуу сапаты үчүн оптималдаштырылды (330кб/сек./303кб/сек.)"</item> + <item msgid="8860982705384396512">"Туташуунун сапатын оптималдаштыруу (330кб/сек./303кб/сек.)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> - <item msgid="6398189564246596868">"Аудио сапаты үчүн оптималдаштырылды"</item> + <item msgid="6398189564246596868">"Аудионун сапатын оптималдаштыруу"</item> <item msgid="4327143584633311908">"Теңделген аудио жана туташуу сапаты"</item> - <item msgid="4681409244565426925">"Туташуу сапаты үчүн оптималдаштырылды"</item> + <item msgid="4681409244565426925">"Туташуунун сапатын оптималдаштыруу"</item> </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"Өчүк"</item> diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml index bb05b8c871c0..e79a567287a2 100644 --- a/packages/SettingsLib/res/values-ml/arrays.xml +++ b/packages/SettingsLib/res/values-ml/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"DRM ഉള്ളടക്കത്തിനുമാത്രമായി HDCP പരിശോധന ഉപയോഗിക്കുക"</item> <item msgid="45075631231212732">"എല്ലായ്പ്പോഴും HDCP പരിശോധന ഉപയോഗിക്കുക"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"മോണോ"</item> <item msgid="8883739882299884241">"സ്റ്റീരിയോ"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"ശബ്ദനിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു (990kbps/909kbps)"</item> + <item msgid="2921767058740704969">"സന്തുലിതമായ ഓഡിയോ/കണക്ഷൻ നിലവാരം (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു (330kbps/303kbps)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"ശബ്ദനിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു"</item> + <item msgid="4327143584633311908">"സന്തുലിതമായ ഓഡിയോ/കണക്ഷൻ നിലവാരം"</item> + <item msgid="4681409244565426925">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"ഓഫ്"</item> <item msgid="1593289376502312923">"64K"</item> diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml index 751b7be59403..e83b1f9c1efd 100644 --- a/packages/SettingsLib/res/values-mr/arrays.xml +++ b/packages/SettingsLib/res/values-mr/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"केवळ DRM सामग्रीसाठी HDCP तपासणी वापरा"</item> <item msgid="45075631231212732">"नेहमी HDCP तपासणी वापरा"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"मोनो"</item> <item msgid="8883739882299884241">"स्टिरिओ"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"ऑडिओ गुणवत्ता (990kbps/909kbps) साठी ऑप्टिमाइझ केली"</item> + <item msgid="2921767058740704969">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"कनेक्शन गुणवत्ता (330kbps/303kbps) साठी ऑप्टिमाइझ केली"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"ऑडिओ गुणवत्तेसाठी ऑप्टिमाइझ केले"</item> + <item msgid="4327143584633311908">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता"</item> + <item msgid="4681409244565426925">"कनेक्शन गुणवत्तेसाठी ऑप्टिमाइझ केले"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"बंद"</item> <item msgid="1593289376502312923">"64K"</item> diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml index 46a758e616eb..cee130b273f4 100644 --- a/packages/SettingsLib/res/values-ne/arrays.xml +++ b/packages/SettingsLib/res/values-ne/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item> <item msgid="45075631231212732">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> <item msgid="8895532488906185219">"४४.१ kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"मोनो"</item> <item msgid="8883739882299884241">"स्टेरियो"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"अडियोको गुणस्तर सुधार्न अनुकूलन गरिएको (990kbps/909kbps)"</item> + <item msgid="2921767058740704969">"सन्तुलित अडियो र जडान गुणस्तर (६६०kbps/६०६kbps)"</item> + <item msgid="8860982705384396512">"जडानको गुणस्तर सुधार्न अनुकूलन गरिएको (330kbps/303kbps)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"अडियोको गुणस्तर सुधार्न अनुकूलन गरिएको"</item> + <item msgid="4327143584633311908">"सन्तुलित अडियो र जडान गुणस्तर"</item> + <item msgid="4681409244565426925">"जडानको गुणस्तर सुधार्न अनुकूलन गरिएको"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"निष्क्रिय गर्नुहोस्"</item> <item msgid="1593289376502312923">"६४के"</item> diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml index 1f943988259b..7ad1d17bd21a 100644 --- a/packages/SettingsLib/res/values-ur/arrays.xml +++ b/packages/SettingsLib/res/values-ur/arrays.xml @@ -58,14 +58,22 @@ <item msgid="3878793616631049349">"HDCP چیکنگ صرف DRM مواد کیلئے استعمال کریں"</item> <item msgid="45075631231212732">"ہمیشہ HDCP چیکنگ استعمال کریں"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) --> - <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) --> - <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="8910200421843557332">"aptX"</item> + <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="6751080638867012696">"LDAC"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="2279916056363477395">"aptX"</item> + <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7950781694447359344">"LDAC"</item> + </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -102,10 +110,16 @@ <item msgid="8900559293912978337">"مونو"</item> <item msgid="8883739882299884241">"اسٹیریو"</item> </string-array> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) --> - <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"آڈیو کے معیار کیلئے بہتر بنایا گيا (990kbps/909kbps)"</item> + <item msgid="2921767058740704969">"متوازن آڈیو اور کنکشن کا معیار (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"کنکشن کے معیار کیلئے بہتر بنایا گيا (330kbps/303kbps)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"آڈیو کے معیار کیلئے بہتر بنایا گيا"</item> + <item msgid="4327143584633311908">"متوازن آڈیو اور کنکشن کا معیار"</item> + <item msgid="4681409244565426925">"کنکشن کے معیار کیلئے بہتر بنایا گيا"</item> + </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"آف"</item> <item msgid="1593289376502312923">"64K"</item> diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index 7bbca5edbc85..eb64b3a9bbd9 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -520,4 +520,37 @@ <item>7</item> </integer-array> + <!-- BatteryMeterView parameters --> + <array name="batterymeter_color_levels"> + <item>15</item> + <item>100</item> + </array> + <array name="batterymeter_color_values"> + <item>@*android:color/battery_saver_mode_color</item> + <item>@android:color/white</item> + </array> + <array name="batterymeter_bolt_points"> + <item>73</item> <item>0</item> + <item>392</item><item>0</item> + <item>201</item><item>259</item> + <item>442</item><item>259</item> + <item>4</item> <item>703</item> + <item>157</item><item>334</item> + <item>0</item> <item>334</item> + </array> + <array name="batterymeter_plus_points"> + <item>3</item><item>0</item> + <item>5</item><item>0</item> + <item>5</item><item>3</item> + <item>8</item><item>3</item> + <item>8</item><item>5</item> + <item>5</item><item>5</item> + <item>5</item><item>8</item> + <item>3</item><item>8</item> + <item>3</item><item>5</item> + <item>0</item><item>5</item> + <item>0</item><item>3</item> + <item>3</item><item>3</item> + </array> + </resources> diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml index 2e8b30fb5abf..b72bcc71f046 100644 --- a/packages/SettingsLib/res/values/dimens.xml +++ b/packages/SettingsLib/res/values/dimens.xml @@ -57,4 +57,15 @@ <dimen name="drawer_width">300dp</dimen> <dimen name="drawer_item_top_bottom_margin">4dp</dimen> <dimen name="drawer_spacer_height">32dp</dimen> + + <dimen name="battery_height">48dp</dimen> + <dimen name="battery_width">38dp</dimen> + + <!-- Margin on the right side of the system icon group on Keyguard. --> + <fraction name="battery_button_height_fraction">10.5%</fraction> + + <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this + fraction of a pixel.--> + <fraction name="battery_subpixel_smoothing_left">0%</fraction> + <fraction name="battery_subpixel_smoothing_right">0%</fraction> </resources> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 01296327f689..5475b325773f 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -900,4 +900,7 @@ <string name="retail_demo_reset_next">Next</string> <!-- Title for carrier demo mode factory reset confirmation dialog. [CHAR LIMIT=40] --> <string name="retail_demo_reset_title">Password required</string> + + <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. --> + <string name="battery_meter_very_low_overlay_symbol">!</string> </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java new file mode 100755 index 000000000000..d25bb2e1b1b7 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.graph; + +import android.animation.ArgbEvaluator; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.provider.Settings; +import com.android.settingslib.R; +import com.android.settingslib.Utils; + +public class BatteryMeterDrawableBase extends Drawable { + + private static final float ASPECT_RATIO = 9.5f / 14.5f; + public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName(); + public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; + + protected final Context mContext; + + protected int mLevel = -1; + protected boolean mPluggedIn; + protected boolean mPowerSaveEnabled; + protected boolean mShowPercent; + + private static final boolean SINGLE_DIGIT_PERCENT = false; + + private static final int FULL = 96; + + private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction + + private final int[] mColors; + private final int mIntrinsicWidth; + private final int mIntrinsicHeight; + + private float mButtonHeightFraction; + private float mSubpixelSmoothingLeft; + private float mSubpixelSmoothingRight; + private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint, + mPlusPaint; + private float mTextHeight, mWarningTextHeight; + private int mIconTint = Color.WHITE; + private float mOldDarkIntensity = 0f; + + private int mHeight; + private int mWidth; + private String mWarningString; + private final int mCriticalLevel; + private int mChargeColor; + private final float[] mBoltPoints; + private final Path mBoltPath = new Path(); + private final float[] mPlusPoints; + private final Path mPlusPath = new Path(); + + private final RectF mFrame = new RectF(); + private final RectF mButtonFrame = new RectF(); + private final RectF mBoltFrame = new RectF(); + private final RectF mPlusFrame = new RectF(); + + private final Path mShapePath = new Path(); + private final Path mClipPath = new Path(); + private final Path mTextPath = new Path(); + + private int mDarkModeBackgroundColor; + private int mDarkModeFillColor; + + private int mLightModeBackgroundColor; + private int mLightModeFillColor; + + public BatteryMeterDrawableBase(Context context, int frameColor) { + mContext = context; + final Resources res = context.getResources(); + TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); + TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); + + final int N = levels.length(); + mColors = new int[2 * N]; + for (int i = 0; i < N; i++) { + mColors[2 * i] = levels.getInt(i, 0); + mColors[2 * i + 1] = colors.getColor(i, 0); + } + levels.recycle(); + colors.recycle(); + updateShowPercent(); + mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); + mCriticalLevel = mContext.getResources().getInteger( + com.android.internal.R.integer.config_criticalBatteryWarningLevel); + mButtonHeightFraction = context.getResources().getFraction( + R.fraction.battery_button_height_fraction, 1, 1); + mSubpixelSmoothingLeft = context.getResources().getFraction( + R.fraction.battery_subpixel_smoothing_left, 1, 1); + mSubpixelSmoothingRight = context.getResources().getFraction( + R.fraction.battery_subpixel_smoothing_right, 1, 1); + + mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mFramePaint.setColor(frameColor); + mFramePaint.setDither(true); + mFramePaint.setStrokeWidth(0); + mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); + + mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBatteryPaint.setDither(true); + mBatteryPaint.setStrokeWidth(0); + mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); + + mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); + mTextPaint.setTypeface(font); + mTextPaint.setTextAlign(Paint.Align.CENTER); + + mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + font = Typeface.create("sans-serif", Typeface.BOLD); + mWarningTextPaint.setTypeface(font); + mWarningTextPaint.setTextAlign(Paint.Align.CENTER); + if (mColors.length > 1) { + mWarningTextPaint.setColor(mColors[1]); + } + + mChargeColor = Utils.getDefaultColor(mContext, R.color.batterymeter_charge_color); + + mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color)); + mBoltPoints = loadBoltPoints(res); + + mPlusPaint = new Paint(mBoltPaint); + mPlusPoints = loadPlusPoints(res); + + mDarkModeBackgroundColor = + Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_background); + mDarkModeFillColor = + Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_fill); + mLightModeBackgroundColor = + Utils.getDefaultColor(mContext, R.color.light_mode_icon_color_dual_tone_background); + mLightModeFillColor = + Utils.getDefaultColor(mContext, R.color.light_mode_icon_color_dual_tone_fill); + + mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width); + mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height); + } + + @Override + public int getIntrinsicHeight() { + return mIntrinsicHeight; + } + + @Override + public int getIntrinsicWidth() { + return mIntrinsicWidth; + } + + public void disableShowPercent() { + mShowPercent = false; + postInvalidate(); + } + + protected void postInvalidate() { + scheduleSelf(this::invalidateSelf, 0); + } + + private static float[] loadBoltPoints(Resources res) { + final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); + int maxX = 0, maxY = 0; + for (int i = 0; i < pts.length; i += 2) { + maxX = Math.max(maxX, pts[i]); + maxY = Math.max(maxY, pts[i + 1]); + } + final float[] ptsF = new float[pts.length]; + for (int i = 0; i < pts.length; i += 2) { + ptsF[i] = (float) pts[i] / maxX; + ptsF[i + 1] = (float) pts[i + 1] / maxY; + } + return ptsF; + } + + private static float[] loadPlusPoints(Resources res) { + final int[] pts = res.getIntArray(R.array.batterymeter_plus_points); + int maxX = 0, maxY = 0; + for (int i = 0; i < pts.length; i += 2) { + maxX = Math.max(maxX, pts[i]); + maxY = Math.max(maxY, pts[i + 1]); + } + final float[] ptsF = new float[pts.length]; + for (int i = 0; i < pts.length; i += 2) { + ptsF[i] = (float) pts[i] / maxX; + ptsF[i + 1] = (float) pts[i + 1] / maxY; + } + return ptsF; + } + + @Override + public void setBounds(int left, int top, int right, int bottom) { + super.setBounds(left, top, right, bottom); + mHeight = bottom - top; + mWidth = right - left; + mWarningTextPaint.setTextSize(mHeight * 0.75f); + mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; + } + + protected void updateShowPercent() { + mShowPercent = true; + } + + private int getColorForLevel(int percent) { + // If we are in power save mode, always use the normal color. + if (mPowerSaveEnabled) { + return mColors[mColors.length - 1]; + } + int thresh, color = 0; + for (int i = 0; i < mColors.length; i += 2) { + thresh = mColors[i]; + color = mColors[i + 1]; + if (percent <= thresh) { + + // Respect tinting for "normal" level + if (i == mColors.length - 2) { + return mIconTint; + } else { + return color; + } + } + } + return color; + } + + public void setDarkIntensity(float darkIntensity) { + if (darkIntensity == mOldDarkIntensity) { + return; + } + int backgroundColor = getBackgroundColor(darkIntensity); + int fillColor = getFillColor(darkIntensity); + setColors(fillColor, backgroundColor); + mOldDarkIntensity = darkIntensity; + } + + public void setColors(int fillColor, int backgroundColor) { + mIconTint = fillColor; + mFramePaint.setColor(backgroundColor); + mBoltPaint.setColor(fillColor); + mChargeColor = fillColor; + invalidateSelf(); + } + + private int getBackgroundColor(float darkIntensity) { + return getColorForDarkIntensity( + darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor); + } + + private int getFillColor(float darkIntensity) { + return getColorForDarkIntensity( + darkIntensity, mLightModeFillColor, mDarkModeFillColor); + } + + private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) { + return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor); + } + + @Override + public void draw(Canvas c) { + final int level = mLevel; + + if (level == -1) return; + + float drawFrac = (float) level / 100f; + final int height = mHeight; + final int width = (int) (ASPECT_RATIO * mHeight); + int px = (mWidth - width) / 2; + + final int buttonHeight = (int) (height * mButtonHeightFraction); + + mFrame.set(0, 0, width, height); + mFrame.offset(px, 0); + + // button-frame: area above the battery body + mButtonFrame.set( + mFrame.left + Math.round(width * 0.25f), + mFrame.top, + mFrame.right - Math.round(width * 0.25f), + mFrame.top + buttonHeight); + + mButtonFrame.top += mSubpixelSmoothingLeft; + mButtonFrame.left += mSubpixelSmoothingLeft; + mButtonFrame.right -= mSubpixelSmoothingRight; + + // frame: battery body area + mFrame.top += buttonHeight; + mFrame.left += mSubpixelSmoothingLeft; + mFrame.top += mSubpixelSmoothingLeft; + mFrame.right -= mSubpixelSmoothingRight; + mFrame.bottom -= mSubpixelSmoothingRight; + + // set the battery charging color + mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level)); + + if (level >= FULL) { + drawFrac = 1f; + } else if (level <= mCriticalLevel) { + drawFrac = 0f; + } + + final float levelTop = drawFrac == 1f ? mButtonFrame.top + : (mFrame.top + (mFrame.height() * (1f - drawFrac))); + + // define the battery shape + mShapePath.reset(); + mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); + mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); + mShapePath.lineTo(mButtonFrame.right, mFrame.top); + mShapePath.lineTo(mFrame.right, mFrame.top); + mShapePath.lineTo(mFrame.right, mFrame.bottom); + mShapePath.lineTo(mFrame.left, mFrame.bottom); + mShapePath.lineTo(mFrame.left, mFrame.top); + mShapePath.lineTo(mButtonFrame.left, mFrame.top); + mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); + + if (mPluggedIn) { + // define the bolt shape + final float bl = mFrame.left + mFrame.width() / 4f; + final float bt = mFrame.top + mFrame.height() / 6f; + final float br = mFrame.right - mFrame.width() / 4f; + final float bb = mFrame.bottom - mFrame.height() / 10f; + if (mBoltFrame.left != bl || mBoltFrame.top != bt + || mBoltFrame.right != br || mBoltFrame.bottom != bb) { + mBoltFrame.set(bl, bt, br, bb); + mBoltPath.reset(); + mBoltPath.moveTo( + mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), + mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); + for (int i = 2; i < mBoltPoints.length; i += 2) { + mBoltPath.lineTo( + mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), + mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); + } + mBoltPath.lineTo( + mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), + mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); + } + + float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); + boltPct = Math.min(Math.max(boltPct, 0), 1); + if (boltPct <= BOLT_LEVEL_THRESHOLD) { + // draw the bolt if opaque + c.drawPath(mBoltPath, mBoltPaint); + } else { + // otherwise cut the bolt out of the overall shape + mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); + } + } else if (mPowerSaveEnabled) { + // define the plus shape + final float pw = mFrame.width() * 2 / 3; + final float pl = mFrame.left + (mFrame.width() - pw) / 2; + final float pt = mFrame.top + (mFrame.height() - pw) / 2; + final float pr = mFrame.right - (mFrame.width() - pw) / 2; + final float pb = mFrame.bottom - (mFrame.height() - pw) / 2; + if (mPlusFrame.left != pl || mPlusFrame.top != pt + || mPlusFrame.right != pr || mPlusFrame.bottom != pb) { + mPlusFrame.set(pl, pt, pr, pb); + mPlusPath.reset(); + mPlusPath.moveTo( + mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), + mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); + for (int i = 2; i < mPlusPoints.length; i += 2) { + mPlusPath.lineTo( + mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(), + mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height()); + } + mPlusPath.lineTo( + mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), + mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); + } + + float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top); + boltPct = Math.min(Math.max(boltPct, 0), 1); + if (boltPct <= BOLT_LEVEL_THRESHOLD) { + // draw the bolt if opaque + c.drawPath(mPlusPath, mPlusPaint); + } else { + // otherwise cut the bolt out of the overall shape + mShapePath.op(mPlusPath, Path.Op.DIFFERENCE); + } + } + + // compute percentage text + boolean pctOpaque = false; + float pctX = 0, pctY = 0; + String pctText = null; + if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) { + mTextPaint.setColor(getColorForLevel(level)); + mTextPaint.setTextSize(height * + (SINGLE_DIGIT_PERCENT ? 0.75f + : (mLevel == 100 ? 0.38f : 0.5f))); + mTextHeight = -mTextPaint.getFontMetrics().ascent; + pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level / 10) : level); + pctX = mWidth * 0.5f; + pctY = (mHeight + mTextHeight) * 0.47f; + pctOpaque = levelTop > pctY; + if (!pctOpaque) { + mTextPath.reset(); + mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); + // cut the percentage text out of the overall shape + mShapePath.op(mTextPath, Path.Op.DIFFERENCE); + } + } + + // draw the battery shape background + c.drawPath(mShapePath, mFramePaint); + + // draw the battery shape, clipped to charging level + mFrame.top = levelTop; + mClipPath.reset(); + mClipPath.addRect(mFrame, Path.Direction.CCW); + mShapePath.op(mClipPath, Path.Op.INTERSECT); + c.drawPath(mShapePath, mBatteryPaint); + + if (!mPluggedIn && !mPowerSaveEnabled) { + if (level <= mCriticalLevel) { + // draw the warning text + final float x = mWidth * 0.5f; + final float y = (mHeight + mWarningTextHeight) * 0.48f; + c.drawText(mWarningString, x, y, mWarningTextPaint); + } else if (pctOpaque) { + // draw the percentage text + c.drawText(pctText, pctX, pctY, mTextPaint); + } + } + } + + // Some stuff required by Drawable. + @Override + public void setAlpha(int alpha) { + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + mFramePaint.setColorFilter(colorFilter); + mBatteryPaint.setColorFilter(colorFilter); + mWarningTextPaint.setColorFilter(colorFilter); + mBoltPaint.setColorFilter(colorFilter); + mPlusPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return 0; + } +} diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java new file mode 100644 index 000000000000..fab00dab5be7 --- /dev/null +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java @@ -0,0 +1,51 @@ +package com.android.settingslib.graph; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import com.android.settingslib.R; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyFloat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class BatteryMeterDrawableBaseTest { + private Context mContext; + private Resources mResources; + private BatteryMeterDrawableBase mBatteryDrawable; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getTargetContext(); + mResources = mContext.getResources(); + mBatteryDrawable = new BatteryMeterDrawableBase(mContext, 0); + } + + @Test + public void testGetIntrinsicSize() { + assertThat(mBatteryDrawable.getIntrinsicWidth()). + isEqualTo(mResources.getDimensionPixelSize(R.dimen.battery_width)); + assertThat(mBatteryDrawable.getIntrinsicHeight()). + isEqualTo(mResources.getDimensionPixelSize(R.dimen.battery_height)); + } + + @Test + public void testDrawNothingBeforeOnBatteryLevelChanged() { + final Canvas canvas = mock(Canvas.class); + mBatteryDrawable.draw(canvas); + verify(canvas, never()).drawPath(any(), any()); + verify(canvas, never()).drawText(anyString(), anyFloat(), anyFloat(), any()); + } +} diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 720612726a8f..136f17e5a77c 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -38,7 +38,7 @@ <bool name="def_bluetooth_on">true</bool> <bool name="def_wifi_display_on">false</bool> - <bool name="def_install_non_market_apps">false</bool> + <bool name="def_install_non_market_apps">true</bool> <bool name="def_package_verifier_enable">true</bool> <!-- Comma-separated list of location providers. Network location is off by default because it requires diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 8be924312740..229979489855 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -2735,7 +2735,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 137; + private static final int SETTINGS_VERSION = 138; private final int mUserId; @@ -3187,6 +3187,18 @@ public class SettingsProvider extends ContentProvider { currentVersion = 137; } + if (currentVersion == 137) { + // Version 138: Settings.Secure#INSTALL_NON_MARKET_APPS is deprecated and its + // default value set to 1. The user can no longer change the value of this + // setting through the UI. + final SettingsState secureSetting = getSecureSettingsLocked(userId); + if (!mUserManager.hasUserRestriction( + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserHandle.of(userId))) { + secureSetting.insertSettingLocked(Settings.Secure.INSTALL_NON_MARKET_APPS, + "1", null, true, SettingsState.SYSTEM_PACKAGE_NAME); + } + currentVersion = 138; + } if (currentVersion != newVersion) { Slog.wtf("SettingsProvider", "warning: upgrading settings database to version " diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java new file mode 100644 index 000000000000..51e43738b537 --- /dev/null +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.providers.settings; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import android.content.Context; +import android.content.pm.UserInfo; +import android.os.SystemClock; +import android.os.UserManager; +import android.provider.Settings; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.util.Log; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; + +@LargeTest +public class InstallNonMarketAppsDeprecationTest extends BaseSettingsProviderTest { + + private static final String TAG = InstallNonMarketAppsDeprecationTest.class.getSimpleName(); + private static final long USER_RESTRICTION_CHANGE_TIMEOUT = 5000; + + private UserManager mUm; + private boolean mHasUserRestriction; + private List<UserInfo> mCurrentUsers; + + private String waitTillValueChanges(String errorMessage, String oldValue) { + boolean interrupted = false; + final long startTime = SystemClock.uptimeMillis(); + String newValue = getSetting(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS); + while (newValue.equals(oldValue) && SystemClock.uptimeMillis() <= (startTime + + USER_RESTRICTION_CHANGE_TIMEOUT)) { + try { + Thread.sleep(1000); + } catch (InterruptedException exc) { + interrupted = true; + } + newValue = getSetting(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS); + } + if (interrupted) { + Thread.currentThread().interrupt(); + } + assertFalse(errorMessage, oldValue.equals(newValue)); + return newValue; + } + + private String getSecureSettingForUserViaShell(int userId) throws IOException { + StringBuilder sb = new StringBuilder("settings get --user "); + sb.append(userId + " secure "); + sb.append(Settings.Secure.INSTALL_NON_MARKET_APPS); + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream( + InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand( + sb.toString()).getFileDescriptor()))); + String line = reader.readLine(); + return line.trim(); + } + + @Before + public void setUp() { + mUm = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + mHasUserRestriction = mUm.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); + mCurrentUsers = mUm.getUsers(); + } + + @Test + public void testValueDefaults() throws Exception { + if (mHasUserRestriction) { + // Default values don't apply when user restriction is set. Pass. + Log.w(TAG, "User restriction for unknown sources set. Skipping testValueDefaults test"); + return; + } + String value = getSetting(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS); + assertEquals("install_non_market_apps should be 1", value, "1"); + + setSettingViaShell(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS, "0", + false); + resetSettingsViaShell(SETTING_TYPE_SECURE, Settings.RESET_MODE_TRUSTED_DEFAULTS); + + value = getSetting(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS); + assertEquals("install_non_market_apps not reset to 1", value, "1"); + } + + @Test + public void testValueForNewUser() throws Exception { + UserInfo newUser = mUm.createUser("TEST_USER", 0); + String value = getSecureSettingForUserViaShell(newUser.id); + assertEquals("install_non_market_apps should be 1 for a new user", value, "1"); + } + + @Test + public void testValueRespectsUserRestriction() { + String value = getSetting(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS); + assertEquals(value, mHasUserRestriction ? "0" : "1"); + + mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, !mHasUserRestriction); + value = waitTillValueChanges( + "Changing user restriction did not change the value of install_non_market_apps", + value); + assertTrue("Invalid value", value.equals("1") || value.equals("0")); + + mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, mHasUserRestriction); + value = waitTillValueChanges( + "Changing user restriction did not change the value of install_non_market_apps", + value); + assertTrue("Invalid value", value.equals("1") || value.equals("0")); + } + + @After + public void tearDown() { + if (mUm.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) + != mHasUserRestriction) { + mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, + mHasUserRestriction); + } + mUm.getUsers().forEach(user -> { + if (!mCurrentUsers.contains(user)) { + mUm.removeUser(user.id); + } + }); + } +} diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index 6d7679830490..8cc2ce260066 100644 --- a/packages/SystemUI/proguard.flags +++ b/packages/SystemUI/proguard.flags @@ -38,5 +38,5 @@ -keep class ** extends android.support.v14.preference.PreferenceFragment -keep class com.android.systemui.tuner.* -keep class com.android.systemui.plugins.** { - public protected **; + public protected *; } diff --git a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml index ea03a50e4460..4987f9bcf610 100644 --- a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml +++ b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml @@ -15,5 +15,5 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#61FFFFFF" /> - <corners android:radius="@dimen/recents_grid_task_view_rounded_corners_radius"/> + <corners android:radius="@dimen/recents_grid_task_view_focused_frame_rounded_corners_radius"/> </shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index e49125764efc..e647adee4412 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Vou uit"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeer"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Maak toe"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Foon raak warm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Sommige kenmerke is beperk terwyl foon afkoel"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Jou foon sal outomaties probeer om af te koel. Jy kan steeds jou foon gebruik, maar dit sal dalk stadiger wees.\n\nJou foon sal normaalweg werk nadat dit afgekoel het."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Aanporboodskap vir wagwoord"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skermkiekies"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sekuriteit"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Gebruikerstatus"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Algemene boodskappe"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Berging"</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index d1aefcf56c2a..392cd0171af7 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ገጽ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ዘርጋ"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"አሳንስ"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"አሰናብት"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ስልኩ እየሞቀ ነው"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ስልኩ እየቀዘቀዘ ሳለ አንዳንድ ባህሪዎች ይገደባሉ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"የእርስዎ ስልክ በራስ-ሰር ለመቀዝቀዝ ይሞክራል። አሁንም ስልክዎን መጠቀም ይችላሉ፣ ነገር ግን ሊንቀራፈፍ ይችላል።\n\nአንዴ ስልክዎ ከቀዘቀዘ በኋላ በመደበኝነት ያሄዳል።"</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"የይለፍ ቃል ጠይቅ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ቅጽበታዊ ገጽ እይታዎች"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"ደህንነት"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"የተጠቃሚ ሁኔታ"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"አጠቃላይ መልዕክቶች"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ማከማቻ"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 77da13c0ae52..f9073f534626 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -679,7 +679,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"توسيع"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"تصغير"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"تجاهل"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"تزداد درجة حرارة الهاتف"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"يتم تقييد عمل بعض الميزات إلى أن تنخفض درجة حرارة الهاتف"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"سيحاول الهاتف تخفيض درجة حرارته تلقائيًا. سيظل بإمكانك استخدام هاتفك، ولكن قد يعمل بشكل أبطأ.\n\nبعد أن تنخفض درجة حرارة الهاتف، سيستعيد سرعته المعتادة."</string> @@ -690,7 +691,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"طلب إدخال كلمة المرور"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"لقطات الشاشة"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"الأمان"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"حالة المستخدمين"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"رسائل عامة"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"سعة التخزين"</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index c55e94caa169..ba67b3a56dc8 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Genişləndirin"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Kiçildin"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Yığışdırın"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon qızmağa başlayır"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon soyuyana kimi bəzi funksiyalar məhdudlaşdırılır"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonunuz avtomatik olaraq soyumağa başlayacaq. Telefon istifadəsinə davam edə bilərsiniz, lakin sürəti yavaşlaya bilər.\n\nTelefonunuz soyuduqdan sonra normal işləyəcək."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Parol üçün bildiriş"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinşotlar"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Təhlükəsizlik"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"İstifadəçi statusu"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Ümumi Mesajlar"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Yaddaş"</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index cc5ab4c4efb2..2e01995b77ad 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odbaci"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon se zagrejao"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon ne ohladi"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon će automatski pokušati da se ohladi. I dalje ćete moći da koristite telefon, ali će sporije reagovati.\n\nKada se telefon ohladi, normalno će raditi."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Upit za lozinku"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Bezbednost"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status korisnika"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Opšte poruke"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index d0841522bb6d..60f042e167ff 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -677,7 +677,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Разгарнуць"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Згарнуць"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Адхіліць"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Тэлефон награваецца"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Некаторыя функцыі абмежаваны, пакуль тэлефон астывае"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш тэлефон аўтаматычна паспрабуе астыць. Вы можаце па-ранейшаму карыстацца сваім тэлефонам, але ён можа працаваць больш павольна.\n\nПасля таго як ваш тэлефон астыне, ён будзе працаваць у звычайным рэжыме."</string> @@ -688,7 +689,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Запыт пароля"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Здымкі экрана"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Бяспека"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус карыстальніка"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Агульныя паведамленні"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 08a814263965..2ebac751eb09 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Разгъване"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Отхвърляне"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефонът загрява"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Някои функции са ограничени, докато телефонът се охлажда"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонът ви автоматично ще направи опит за охлаждане. Пак можете да го използвате, но той може да работи по-бавно.\n\nСлед като се охлади, ще работи нормално."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Подкана за парола"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Екранни снимки"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Сигурност"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Състояние на потребителя"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Общи съобщения"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 90aa1f5fd3d3..ed86d3d9ce40 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -156,7 +156,7 @@ <string name="accessibility_cell_data_off" msgid="8000803571751407635">"সেলুলার ডেটা বন্ধ আছে"</string> <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ব্লুটুথ টিথারিং৷"</string> <string name="accessibility_airplane_mode" msgid="834748999790763092">"বিমান মোড৷"</string> - <string name="accessibility_no_sims" msgid="3957997018324995781">"কোনো SIM কার্ড নেই।"</string> + <string name="accessibility_no_sims" msgid="3957997018324995781">"কোনো সিম কার্ড নেই।"</string> <string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তিত হচ্ছে।"</string> <string name="accessibility_battery_details" msgid="7645516654955025422">"ব্যাটারির বিশদ বিবরণ খুলুন"</string> <string name="accessibility_battery_level" msgid="7451474187113371965">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ ব্যাটারি রয়েছে৷"</string> @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"শব্দ করে ও স্ক্রীনে ভেসে ওঠে"</string> <string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string> <string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"১৫ মিনিট"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"৩০ মিনিট"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"১ ঘণ্টা"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"মনে করানো হবে না"</string> + <string name="snooze_undo" msgid="6074877317002985129">"পূর্বাবস্থায় ফিরুন"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> পরে আবার মনে করানো হবে"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"চার্জ করার সময় ব্যাটারি সেভার উপলব্ধ নয়"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"ব্যাটারি সেভার"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"চালু আছে"</string> <string name="switch_bar_off" msgid="8803270596930432874">"বন্ধ আছে"</string> <string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন দন্ড"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"লেআউট"</string> + <string name="nav_bar_left" msgid="731491280511316123">"বাঁ"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"ডান"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"বোতামের ধরণ"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(ডিফল্ট)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"ক্লিপবোর্ড"</item> + <item msgid="5742013440802239414">"কীকোড"</item> + <item msgid="8748101184830239843">"মেনু / কীবোর্ড স্যুইচার"</item> + <item msgid="8175437057325747277">"কোনো কিছুই নয়"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"ভাগ করা (ডিফল্ট)"</item> + <item msgid="6210279084134579668">"কেন্দ্রস্থ"</item> + <item msgid="89143234390889289">"বাঁ দিকে সারিবদ্ধ"</item> + <item msgid="7715533883382410603">"ডান দিকে সারিবদ্ধ"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"মেনু / কীবোর্ড স্যুইচার"</string> <string name="save" msgid="2311877285724540644">"সংরক্ষণ করুন"</string> <string name="reset" msgid="2448168080964209908">"পুনরায় সেট করুন"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"ক্লিপবোর্ড"</string> <string name="accessibility_key" msgid="5701989859305675896">"কাস্টম নেভিগেশান বোতাম"</string> <string name="keycode" msgid="7335281375728356499">"কীকোড"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"আইকন"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"টাইলগুলি যোগ করার জন্য টেনে আনুন"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"সরানোর জন্য এখানে টেনে আনুন"</string> <string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা করুন"</string> @@ -682,28 +671,18 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"প্রসারিত করুন"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ছোটো করুন"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"খারিজ করুন"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ফোনটি গরম হচ্ছে"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ফোনটি ঠান্ডা হওয়ার সময় কিছু বৈশিষ্ট্য সীমিত হতে পারে"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"আপনার ফোনটি নিজে থেকেই ঠান্ডা হওয়ার চেষ্টা করবে৷ আপনি তবুও আপনার ফোন ব্যবহার করতে পারেন, কিন্তু এটি একটু ধীরে চলতে পারে৷\n\nআপনার ফোনটি পুরোপুরি ঠান্ডা হয়ে গেলে এটি স্বাভাবিকভাবে চলবে৷"</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> - <skip /> + <string name="lockscreen_left" msgid="6806490081187499505">"বাঁ"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"ডান"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"কাস্টমাইজ করার শর্টকাট"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"শর্টকাট"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"পাসওয়ার্ড জানতে চান"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"স্ক্রীনশটস"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"সাধারণ বার্তাগুলি"</string> + <string name="notification_channel_storage" msgid="3077205683020695313">"সঞ্চয়স্থান"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index e44e4bb708b6..d17775cba5af 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -448,7 +448,7 @@ <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skupi"</string> <string name="screen_pinning_title" msgid="3273740381976175811">"Ekran je prikačen"</string> <string name="screen_pinning_description" msgid="8909878447196419623">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string> - <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran ostaje prikzan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Pregled."</string> + <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Pregled."</string> <string name="screen_pinning_positive" msgid="3783985798366751226">"Jasno mi je"</string> <string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, hvala"</string> <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite li sakriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string> @@ -608,7 +608,7 @@ <string-array name="nav_bar_buttons"> <item msgid="1545641631806817203">"Međumemorija"</item> <item msgid="5742013440802239414">"Kôd tipke"</item> - <item msgid="8748101184830239843">"Meni / Prebacivač tastature"</item> + <item msgid="8748101184830239843">"Prebacivač Meni / Tastatura"</item> <item msgid="8175437057325747277">"Nema"</item> </string-array> <string-array name="nav_bar_layouts"> @@ -675,7 +675,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odbaci"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon se pregrijava"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon hladi"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Vaš telefon će se automatski pokušati ohladiti. I dalje možete koristi telefon, ali će možda raditi sporije.\n\nNakon što se ohladi, telefon će normalno raditi."</string> @@ -686,7 +687,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Traži lozinku"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sigurnost"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status korisnika"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index b5cf3e4f3f1c..009942c5119e 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Desplega"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignora"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"El telèfon s\'està escalfant"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Algunes funcions estaran limitades mentre el telèfon es refreda"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"El telèfon provarà de refredar-se automàticament. Podràs continuar utilitzant-lo, però és possible que funcioni més lentament.\n\nUn cop s\'hagi refredat, funcionarà amb normalitat."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Sol·licita la contrasenya"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures de pantalla"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Seguretat"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Estat de l\'usuari"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Missatges generals"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Emmagatzematge"</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f9ec15e06e50..dc3df04fa023 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -677,7 +677,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbalit"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovat"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Zrušit"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon se zahřívá"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Některé funkce jsou při chladnutí omezeny"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon se automaticky pokusí vychladnout. Lze jej nadále používat, ale může být pomalejší.\n\nAž telefon vychladne, bude fungovat normálně."</string> @@ -688,7 +689,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Výzva k zadání hesla"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovek"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Zabezpečení"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status uživatele"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné zprávy"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Úložiště"</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 206478cc3ac7..dda65e2e0c3b 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Udvid"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Afvis"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefonen er ved at blive varm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Nogle funktioner er begrænsede, mens telefonen køler ned"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Din telefon forsøger automatisk at køle ned. Du kan stadig bruge telefonen, men den kører muligvis langsommere.\n\nNår din telefon er kølet ned, fungerer den normalt igen."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Spørg om adgangskode"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sikkerhed"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Brugerstatus"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meddelelser"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Lagerplads"</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index a317fa064afc..5509a5774fec 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Maximieren"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimieren"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Schließen"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Smartphone wird warm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Einige Funktionen sind während der Abkühlphase des Smartphones eingeschränkt"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Dein Smartphone kühlt sich automatisch ab. Du kannst dein Smartphone weiterhin nutzen, aber es reagiert möglicherweise langsamer.\n\nSobald dein Smartphone abgekühlt ist, funktioniert es wieder normal."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Zur Passworteingabe auffordern"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sicherheit"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Nutzerstatus"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Nachrichten"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Speicher"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 08c58223dcd0..1de2dae33f8c 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Ανάπτυξη"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Ελαχιστοποίηση"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Παράβλεψη"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Αύξηση θερμοκρασίας τηλεφώνου"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Ορισμένες λειτουργίες περιορίζονται κατά τη μείωση της θερμοκρασίας"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Το τηλέφωνό σας θα προσπαθήσει να μειώσει αυτόματα τη θερμοκρασία. Μπορείτε να εξακολουθήσετε να το χρησιμοποιείτε, αλλά είναι πιθανό να λειτουργεί πιο αργά.\n\nΜόλις μειωθεί η θερμοκρασία του τηλεφώνου σας, θα λειτουργεί ξανά κανονικά."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Προτροπή για κωδικό πρόσβασης"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Στιγμιότυπα οθόνης"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Ασφάλεια"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Κατάσταση χρήστη"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Γενικά μηνύματα"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Αποθηκευτικός χώρος"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 822c2dfe245b..a79caad47130 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dismiss"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Phone is getting warm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Some features limited while phone cools down"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Prompt for password"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"User status"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 822c2dfe245b..a79caad47130 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dismiss"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Phone is getting warm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Some features limited while phone cools down"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Prompt for password"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"User status"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 822c2dfe245b..a79caad47130 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dismiss"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Phone is getting warm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Some features limited while phone cools down"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Prompt for password"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"User status"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 37019b1ad0cd..1c4d42ad94a5 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Descartar"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"El teléfono se está calentando"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Se limitarán algunas funciones mientras se enfría el teléfono"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Tu teléfono intentará enfriarse automáticamente. Podrás usarlo, pero es posible que funcione más lento.\n\nUna vez que se haya enfriado, volverá a funcionar correctamente."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar contraseña"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Estado del usuario"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 75cd169c42f4..28299b7acf12 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -528,24 +528,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"Emitir sonido y mostrar en pantalla"</string> <string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string> <string name="notification_done" msgid="5279426047273930175">"Listo"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"Controles de las notificaciones"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Opciones para posponer las notificaciones"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"No posponer"</string> + <string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"Volverá a mostrarse en <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no disponible mientras se carga el dispositivo"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string> @@ -607,24 +598,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"Sí"</string> <string name="switch_bar_off" msgid="8803270596930432874">"No"</string> <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"Diseño"</string> + <string name="nav_bar_left" msgid="731491280511316123">"Izquierda"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"Derecha"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"Tipo de botón"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(predeterminada)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"Portapapeles"</item> + <item msgid="5742013440802239414">"Código de teclado"</item> + <item msgid="8748101184830239843">"Menú/Cambio de teclado"</item> + <item msgid="8175437057325747277">"Ninguno"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"Dividida (predeterminada)"</item> + <item msgid="6210279084134579668">"Centrada"</item> + <item msgid="89143234390889289">"Alineada a la izquierda"</item> + <item msgid="7715533883382410603">"Alineada a la derecha"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"Menú/Cambio de teclado"</string> <string name="save" msgid="2311877285724540644">"Guardar"</string> <string name="reset" msgid="2448168080964209908">"Restablecer"</string> @@ -632,8 +622,7 @@ <string name="clipboard" msgid="1313879395099896312">"Portapapeles"</string> <string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizada"</string> <string name="keycode" msgid="7335281375728356499">"Código de teclado"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"Icono"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastra para añadir funciones"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar una función"</string> <string name="qs_edit" msgid="2232596095725105230">"Editar"</string> @@ -684,28 +673,18 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Mostrar"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Rechazar"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"El teléfono se está calentando"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Se limitan algunas funciones mientras el teléfono se enfría"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"El teléfono intentará enfriarse. Puedes seguir utilizándolo, pero es posible que funcione con mayor lentitud.\n\nUna vez que se haya enfriado, funcionará con normalidad."</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> - <skip /> + <string name="lockscreen_left" msgid="6806490081187499505">"Izquierda"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"Derecha"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"Personalizar el acceso directo"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"Acceso directo"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar contraseña"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string> + <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 03613bd97e3d..9a888c55dc20 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Laiendamine"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeeri"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Loobu"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon soojeneb"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Mõned funktsioonid on piiratud, kuni telefon jahtub"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Teie telefon proovib automaatselt maha jahtuda. Saate telefoni ikka kasutada, kuid see võib olla aeglasem.\n\nKui telefon on jahtunud, töötab see tavapäraselt."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Parooli viip"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekraanipildid"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Turvalisus"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Kasutaja olek"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Üldised sõnumid"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Salvestusruum"</string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 115c8488c83d..45ec067e55d9 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Zabaldu"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizatu"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Baztertu"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Berotzen ari da telefonoa"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Eginbide batzuk ezingo dira erabili telefonoa hoztu arte"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonoa automatikoki saiatuko da hozten. Hoztu bitartean, telefonoa erabiltzen jarrai dezakezu, baina mantsoago funtziona lezake.\n\nTelefonoaren tenperatura jaitsi bezain laster, ohi bezala funtzionatzen jarraituko du."</string> @@ -681,10 +682,9 @@ <string name="lockscreen_right" msgid="6093496261656102989">"Eskuinaldea"</string> <string name="lockscreen_customize" msgid="1288691376862981950">"Pertsonalizatu lasterbidea"</string> <string name="lockscreen_shortcut" msgid="3734369277470360642">"Lasterbidea"</string> - <string name="lockscreen_unlock" msgid="4934466194763269051">"Eskatu pasahizta"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"Eskatu pasahitza"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pantaila-argazkiak"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Segurtasuna"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Erabiltzailearen egoera"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mezu orokorrak"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 78af4b855e30..cd125b566284 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"بزرگ کردن"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"کوچک کردن"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"نپذیرفتن"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"تلفن درحال گرم شدن است"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"وقتی تلفن درحال خنک شدن است، بعضی از قابلیتها محدود میشوند"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"تلفنتان بهطور خودکار سعی میکند خنک شود. همچنان میتوانید از تلفنتان استفاده کنید، اما ممکن است کندتر عمل کند.\n\nوقتی تلفن خنک شد، عملکرد عادیاش از سرگرفته میشود."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"درخواست وارد کردن گذرواژه"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"عکسهای صفحهنمایش"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"امنیت"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"وضعیت کاربر"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"پیامهای عمومی"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"فضای ذخیرهسازی"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index bc840a86b2ae..623ee51ebe0c 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Laajenna"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Pienennä"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ohita"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Puhelin lämpenee"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Joidenkin ominaisuuksien käyttöä on rajoitettu puhelimen jäähtymisen aikana."</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Puhelimesi yrittää automaattisesti jäähdyttää itsensä. Voit silti käyttää puhelinta, mutta se voi toimia hitaammin.\n\nKun puhelin on jäähtynyt, se toimii normaalisti."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Kysy salasanaa"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Kuvakaappaukset"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Tietosuoja"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Käyttäjätila"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Yleiset viestit"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Tallennustila"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index f69a85b6917a..5d4867c0d27b 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorer"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Le téléphone commence à chauffer"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Les fonctionnalités sont limitées pendant que le téléphone refroidit"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string> @@ -684,7 +685,7 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Demander le mot de passe"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Saisies d\'écran"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sécurité"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"État de l\'utilisateur"</string> + <!-- no translation found for notification_channel_general (4525309436693914482) --> + <skip /> <string name="notification_channel_storage" msgid="3077205683020695313">"Stockage"</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 4a2f23f6156d..97748a2b6d4a 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorer"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Le téléphone chauffe"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Fonctionnalités limitées pendant le refroidissement du téléphone"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Demander le mot de passe"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures d\'écran"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sécurité"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"État de l\'utilisateur"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Nouveaux messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Espace de stockage"</string> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index e65f3b086517..5821bb96a0c5 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Despregar"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorar"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"O teléfono está quentando"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"O uso dalgunhas funcións é limitado mentres o teléfono arrefría"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"O teléfono tentará arrefriar automaticamente. Podes utilizalo, pero é probable que funcione máis lento.\n\nUnha vez que arrefríe, funcionará con normalidade."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitude de contrasinal"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Seguranza"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Estado do usuario"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mensaxes xerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index b120c7d18c5f..5fedb2dbceba 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"અવાજ કરો અને સ્ક્રીન પર બતાવો"</string> <string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string> <string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"સૂચના નિયંત્રણો"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"15 મિનિટ"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"30 મિનિટ"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 કલાક"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"સ્નૂઝ કરશો નહીં"</string> + <string name="snooze_undo" msgid="6074877317002985129">"પૂર્વવત્ કરો"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> માટે સ્નૂઝ કરો"</string> <string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ચાર્જિંગ દરમિયાન બૅટરી બચતકર્તા ઉપલબ્ધ નથી"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"બૅટરી બચતકર્તા"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"ચાલુ"</string> <string name="switch_bar_off" msgid="8803270596930432874">"બંધ"</string> <string name="nav_bar" msgid="1993221402773877607">"નેવિગેશન બાર"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"લેઆઉટ"</string> + <string name="nav_bar_left" msgid="731491280511316123">"ડાબે"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"જમણે"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"બટનનો પ્રકાર"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(ડિફૉલ્ટ)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"ક્લિપબોર્ડ"</item> + <item msgid="5742013440802239414">"કીકોડ"</item> + <item msgid="8748101184830239843">"મેનૂ / કીબોર્ડ સ્વિચર"</item> + <item msgid="8175437057325747277">"કોઈ નહીં"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"વિભાજીત (ડિફૉલ્ટ)"</item> + <item msgid="6210279084134579668">"કેન્દ્રિત"</item> + <item msgid="89143234390889289">"ડાબે-સંરેખિત"</item> + <item msgid="7715533883382410603">"જમણે-સંરેખિત"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"મેનૂ / કીબોર્ડ સ્વિચર"</string> <string name="save" msgid="2311877285724540644">"સાચવો"</string> <string name="reset" msgid="2448168080964209908">"ફરીથી સેટ કરો"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"ક્લિપબોર્ડ"</string> <string name="accessibility_key" msgid="5701989859305675896">"કસ્ટમ નેવિગેશન બટન"</string> <string name="keycode" msgid="7335281375728356499">"કીકોડ"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"આઇકન"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"ટાઇલ્સ ઉમેરવા માટે ખેંચો"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"દૂર કરવા માટે અહીં ખેંચો"</string> <string name="qs_edit" msgid="2232596095725105230">"સંપાદિત કરો"</string> @@ -682,28 +671,18 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"વિસ્તૃત કરો"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"નાનું કરો"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"છોડી દો"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ફોન ગરમ થઈ રહ્યો છે"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ફોન ઠંડો થાય ત્યાં સુધી કેટલીક સુવિધાઓ મર્યાદિત હોય છે"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"તમારો ફોન આપમેળે ઠંડો થવાનો પ્રયાસ કરશે. તમે હજી પણ તમારા ફોનનો ઉપયોગ કરી શકો છો, પરંતુ તે કદાચ થોડો ધીમો ચાલે.\n\nતમારો ફોન ઠંડો થઈ જવા પર, તે સામાન્ય રીતે ચાલશે."</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> - <skip /> + <string name="lockscreen_left" msgid="6806490081187499505">"ડાબે"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"જમણે"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"શૉર્ટકટ કસ્ટમાઇઝ કરો"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"શૉર્ટકટ"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"પાસવર્ડ માટેનો સંકેત આપો"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"સ્ક્રીનશૉટ"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"સામાન્ય સંદેશા"</string> + <string name="notification_channel_storage" msgid="3077205683020695313">"સ્ટોરેજ"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 767669185116..b6cba3c34784 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -532,7 +532,7 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनट"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनट"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 घंटा"</string> - <string name="snooze_option_dont_snooze" msgid="655446566007801922">"यद नहीं दिलाएं"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"याद नहीं दिलाएं"</string> <string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string> <string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string> @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पेज <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करें"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"छोटा करें"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"खारिज करें"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"फ़ोन गर्म हो रहा है"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"फ़ोन के ठंडा होने के दौरान कुछ सुविधाएं सीमित होती हैं"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"आपका फ़ोन अपने आप ठंडा होने की कोशिश करेगा. आप अभी भी अपने फ़ोन का उपयोग कर सकते हैं, लेकिन हो सकता है कि यह धीमी गति से चले.\n\nठंडा हो जाने पर आपका फ़ोन सामान्य रूप से चलेगा."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"पासवर्ड के लिए संकेत दें"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"सुरक्षा"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"उपयोगकर्ता स्थिति"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"सामान्य संदेश"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"जगह"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 07c725b70838..85a744d9292e 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Proširivanje"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiziraj"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odbaci"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon se zagrijava"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Neke su značajke ograničene dok se telefon hladi"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon će se automatski pokušati ohladiti. Možete ga nastaviti koristiti, no mogao bi raditi sporije.\n\nKad se ohladi, radit će normalno."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Upit za zaporku"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimke zaslona"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sigurnost"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status korisnika"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 029e76bf9a92..81f3d5e158ca 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Kibontás"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Kis méret"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Elvetés"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"A telefon melegszik"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Bizonyos funkciók korlátozottan működnek a telefon hűlése közben"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"A telefon automatikusan megpróbál lehűlni. Továbbra is tudja használni a telefont, de elképzelhető, hogy működése lelassul.\n\nAmint a telefon lehűl, újra a szokásos módon működik majd."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Jelszókérés"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Képernyőképek"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Biztonság"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Felhasználói állapot"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Általános üzenetek"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Tárhely"</string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 761bee1d0454..e5169f255201 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -534,7 +534,7 @@ <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ժամ"</string> <string name="snooze_option_dont_snooze" msgid="655446566007801922">"Չհետաձգել"</string> <string name="snooze_undo" msgid="6074877317002985129">"ՀԵՏԱՐԿԵԼ"</string> - <string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է հետևյալ ժամանակով՝ <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ով"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Մարտկոցի տնտեսումը լիցքավորման ժամանակ հասանելի չէ"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"Մարտկոցի տնտեսում"</string> @@ -608,7 +608,7 @@ <item msgid="8175437057325747277">"Չկան"</item> </string-array> <string-array name="nav_bar_layouts"> - <item msgid="4967898371682516967">"Բաժանվածծ (կանխադրված)"</item> + <item msgid="4967898371682516967">"Բաժանված (կանխադրված)"</item> <item msgid="6210279084134579668">"Կենտրոնում"</item> <item msgid="89143234390889289">"Հավասարեցված ձախ"</item> <item msgid="7715533883382410603">"Հավասարեցված աջ"</item> @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Ընդարձակել"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Ծալել"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Փակել"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Հեռախոսը տաքանում է"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Հովանալու ընթացքում հեռախոսի որոշ գործառույթներ սահմանափակ են"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ձեր հեռախոսն ավտոմատ կերպով կփորձի hովանալ: Կարող եք շարունակել օգտագործել հեռախոսը, սակայն հնարավոր է, որ այն ավելի դանդաղ աշխատի:\n\nՀովանալուց հետո հեռախոսը կաշխատի կանոնավոր կերպով:"</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Պահանջել գաղտնաբառ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Էկրանի պատկերներ"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Անվտանգություն"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Օգտվողի կարգավիճակը"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Ընդհանուր հաղորդագրություններ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Հիշողություն"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 24a7b538136e..a2d38e9faa60 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Luaskan"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Tutup"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Ponsel menjadi hangat"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Beberapa fitur dibatasi saat ponsel mendingin"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ponsel akan otomatis mencoba mendingin. Anda tetap dapat menggunakan ponsel, tetapi mungkin berjalan lebih lambat.\n\nSetelah dingin, ponsel akan berjalan seperti biasa."</string> @@ -680,9 +681,8 @@ <string name="lockscreen_customize" msgid="1288691376862981950">"Sesuaikan pintasan"</string> <string name="lockscreen_shortcut" msgid="3734369277470360642">"Pintasan"</string> <string name="lockscreen_unlock" msgid="4934466194763269051">"Minta sandi"</string> - <string name="notification_channel_alerts" msgid="4496839309318519037">"Lansiran"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Keamanan"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status pengguna"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Pesan Umum"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Penyimpanan"</string> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 5f46b92697c0..b0dacfc4162b 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Stækka"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minnka"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Hunsa"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Síminn er að hitna"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Sumir eiginleikar eru takmarkaðir þegar síminn kælir sig"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Síminn reynir sjálfkrafa að kæla sig. Þú getur enn notað símann en hann gæti verið hægvirkari.\n\nEftir að síminn hefur kælt sig niður virkar hann eðlilega."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Beiðni um aðgangsorð"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjámyndir"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Öryggi"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Staða notanda"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Almenn skilaboð"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Geymslurými"</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 2441b7fd653d..8dacab213eab 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Espandi"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Riduci a icona"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignora"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Il telefono si sta scaldando"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Alcune funzioni limitate durante il raffreddamento del telefono"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Il telefono cercherà automaticamente di raffreddarsi. Puoi comunque usarlo, ma potrebbe essere più lento.\n\nUna volta raffreddato, il telefono funzionerà normalmente."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Richiedi password"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sicurezza"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Stato utente"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Messaggi generali"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Spazio di archiviazione"</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 280b9aa1b1e3..d39a07aec821 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -675,7 +675,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"הרחב"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"מזער"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"סגור"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"הטלפון מתחמם"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"חלק מהתכונות מוגבלות כל עוד הטלפון מתקרר"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"קירור הטלפון ייעשה באופן אוטומטי. תוכל עדיין להשתמש בטלפון, אבל ייתכן שהוא יפעל לאט יותר.\n\nהטלפון יחזור לפעול כרגיל לאחר שיתקרר."</string> @@ -686,7 +687,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"בקש סיסמה"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"צילומי מסך"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"אבטחה"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"סטטוס המשתמש"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"הודעות כלליות"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"אחסון"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 015545ef6bcc..9ea02b97a22d 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ページ <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"閉じる"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"スマートフォンの温度が上昇中"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"スマートフォンのクールダウン中は一部の機能が制限されます"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"スマートフォンは自動的にクールダウンを行います。その間もスマートフォンを使用できますが、動作が遅くなる可能性があります。\n\nクールダウンが完了すると、通常どおり動作します。"</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"パスワードの入力"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"スクリーンショット"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"セキュリティ"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"ユーザー ステータス"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"一般メッセージ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ストレージ"</string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index c75d83dc6c65..30b503e48701 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"გაშლა"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ჩაკეცვა"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"დახურვა"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ტელეფონი ცხელდება"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ზოგიერთი ფუნქცია შეზღუდული იქნება, სანამ ტელეფონი გაგრილდება"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"თქვენი ტელეფონი გაგრილებას ავტომატურად შეეცდება. შეგიძლიათ გააგრძელოთ მისით სარგებლობა, თუმცა ტელეფონმა შეიძლება უფრო ნელა იმუშაოს.\n\nგაგრილების შემდგომ ის ჩვეულებრივად იმუშავებს."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"პაროლის მოთხოვნა"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ეკრანის ანაბეჭდები"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"უსაფრთხოება"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"მომხმარებლის სტატუსი"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"ზოგადი შეტყობინებები"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"მეხსიერება"</string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index d86fcf9533bc..cfcd2ec102fc 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Жаю"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Кішірейту"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Қабылдамау"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефон қызуда"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Телефон толық суығанға дейін, кейбір функциялардың жұмысы шектеледі"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефон автоматты түрде суи бастайды. Оны пайдалана бере аласыз, бірақ ол баяуырақ жұмыс істеуі мүмкін.\n\nТелефон суығаннан кейін, оның жұмысы қалпына келеді."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Құпия сөзді сұрау"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттар"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Қауіпсіздік"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Пайдаланушы күйі"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы хабарлар"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Жад"</string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index cfbba6ed2ed6..a958258e1d5e 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -602,16 +602,16 @@ <string name="nav_bar_button_type" msgid="6947806619897153791">"ប្រភេទប៊ូតុង"</string> <string name="nav_bar_default" msgid="8587114043070993007">"(លំនាំដើម)"</string> <string-array name="nav_bar_buttons"> - <item msgid="1545641631806817203">"ក្ដារតម្បៀតខ្ទាស់"</item> + <item msgid="1545641631806817203">"អង្គចងចាំ"</item> <item msgid="5742013440802239414">"លេខកូដគ្រាប់ចុច"</item> - <item msgid="8748101184830239843">"កម្មវិធីប្តូរក្តារចុច / ម៉ឺនុយ"</item> + <item msgid="8748101184830239843">"ម៉ឺនុយ / កម្មវិធីប្តូរក្តារចុច"</item> <item msgid="8175437057325747277">"គ្មាន"</item> </string-array> <string-array name="nav_bar_layouts"> <item msgid="4967898371682516967">"បំបែក (លំនាំដើម)"</item> <item msgid="6210279084134579668">"ដាក់នៅកណ្តាល"</item> - <item msgid="89143234390889289">"តម្រឹមខាងឆ្វេង"</item> - <item msgid="7715533883382410603">"តម្រឹមខាងស្ដាំ"</item> + <item msgid="89143234390889289">"តម្រឹមឆ្វេង"</item> + <item msgid="7715533883382410603">"តម្រឹមស្ដាំ"</item> </string-array> <string name="menu_ime" msgid="4943221416525250684">"កម្មវិធីប្តូរក្តារចុច / ម៉ឺនុយ"</string> <string name="save" msgid="2311877285724540644">"រក្សាទុក"</string> @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ពង្រីក"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"បដិសេធ"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ទូរសព្ទនេះកំពុងកើនកម្តៅ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"មុខងារមួយចំនួននឹងមិនអាចប្រើបានពេញលេញនោះទេ ខណៈពេលដែលទូរសព្ទកំពុងបញ្ចុះកម្តៅ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"ទូរសព្ទរបស់អ្នកនឹងព្យាយាមបញ្ចុះកម្តៅដោយស្វ័យប្រវត្តិ។ អ្នកនៅតែអាចប្រើទូរសព្ទរបស់អ្នកបានដដែល ប៉ុន្តែវានឹងដំណើរការយឺតជាងមុន។\n\nបន្ទាប់ពីទូរសព្ទរបស់អ្នកត្រជាក់ជាងមុនហើយ វានឹងដំណើរការដូចធម្មតា។"</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"ជំរុញឲ្យបញ្ចូលពាក្យសម្ងាត់"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ការជូនដំណឹង"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"រូបថតអេក្រង់"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"សុវត្ថិភាព"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"ស្ថានភាពអ្នកប្រើ"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"សារទូទៅ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ទំហំផ្ទុក"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 70a880911955..ba681db62f6c 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"ಪರದೆಯ ಮೇಲೆ ಧ್ವನಿಮಾಡಿ ಮತ್ತು ಪಾಪ್ ಮಾಡಿ"</string> <string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ನಿಮಿಷಗಳು"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"30 ನಿಮಿಷಗಳು"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ಗಂಟೆ"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"ಸ್ನೂಜ್ ಮಾಡಬೇಡಿ"</string> + <string name="snooze_undo" msgid="6074877317002985129">"ರದ್ದುಮಾಡಿ"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ಗೆ ಸ್ನೂಜ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ಬ್ಯಾಟರಿ ಬಳಕೆ"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ಚಾರ್ಜಿಂಗ್ ಸಮಯದಲ್ಲಿ ಬ್ಯಾಟರಿ ಸೇವರ್ ಲಭ್ಯವಿರುವುದಿಲ್ಲ"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"ಆನ್"</string> <string name="switch_bar_off" msgid="8803270596930432874">"ಆಫ್"</string> <string name="nav_bar" msgid="1993221402773877607">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"ಲೇಔಟ್"</string> + <string name="nav_bar_left" msgid="731491280511316123">"ಎಡ"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"ಬಲ"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"ಬಟನ್ ವಿಧ"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(ಡಿಫಾಲ್ಟ್)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"ಕ್ಲಿಪ್ಬೋರ್ಡ್"</item> + <item msgid="5742013440802239414">"ಕೀಕೋಡ್"</item> + <item msgid="8748101184830239843">"ಮೆನು / ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</item> + <item msgid="8175437057325747277">"ಯಾವುದೂ ಅಲ್ಲ"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"ವಿಭಜಿಸಲಾಗಿದೆ (ಡಿಫಾಲ್ಟ್)"</item> + <item msgid="6210279084134579668">"ಕೇಂದ್ರೀಕೃತ"</item> + <item msgid="89143234390889289">"ಎಡಕ್ಕೆ ಹೊಂದಿಸಿರುವುದು"</item> + <item msgid="7715533883382410603">"ಬಲಕ್ಕೆ ಹೊಂದಿಸಿರುವುದು"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"ಮೆನು / ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</string> <string name="save" msgid="2311877285724540644">"ಉಳಿಸು"</string> <string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"ಕ್ಲಿಪ್ಬೋರ್ಡ್"</string> <string name="accessibility_key" msgid="5701989859305675896">"ಕಸ್ಟಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಟನ್"</string> <string name="keycode" msgid="7335281375728356499">"ಕೀಕೋಡ್"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"ಐಕಾನ್"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"ಟೈಲ್ಗಳನ್ನು ಸೇರಿಸಲು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ತೆಗೆದುಹಾಕಲು ಇಲ್ಲಿ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string> <string name="qs_edit" msgid="2232596095725105230">"ಎಡಿಟ್"</string> @@ -682,28 +671,18 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ವಿಸ್ತೃತಗೊಳಿಸು"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ಕುಗ್ಗಿಸಿ"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"ವಜಾಗೊಳಿಸಿ"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ಫೋನ್ ಬಿಸಿಯಾಗುತ್ತಿದೆ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ಫೋನ್ ತಣ್ಣಗಾಗುವವರೆಗೂ ಕೆಲವು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸೀಮಿತಗೊಳಿಸುತ್ತದೆ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"ನಿಮ್ಮ ಫೋನ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಣ್ಣಗಾಗಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಈಗಲೂ ಬಳಸಬಹುದಾಗಿರುತ್ತದೆ, ಆದರೆ ಇದು ನಿಧಾನವಾಗಿರಬಹುದು.\n\nಒಮ್ಮೆ ನಿಮ್ಮ ಫೋನ್ ತಣ್ಣಗಾದ ನಂತರ ಇದು ಸಾಮಾನ್ಯ ರೀತಿಯಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ."</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> - <skip /> + <string name="lockscreen_left" msgid="6806490081187499505">"ಎಡ"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"ಬಲ"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"ಶಾರ್ಟ್ಕಟ್ ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"ಶಾರ್ಟ್ಕಟ್"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"ಪಾಸ್ವರ್ಡ್ ಕೇಳಿ"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳು"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string> + <string name="notification_channel_storage" msgid="3077205683020695313">"ಸಂಗ್ರಹಣೆ"</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 4b59ad2d2de1..c5faa18ed85c 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"펼치기"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"최소화"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"닫기"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"휴대전화 온도가 높음"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"휴대전화 온도를 낮추는 동안 일부 기능이 제한됩니다."</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"휴대전화 온도를 자동으로 낮추려고 시도합니다. 휴대전화를 계속 사용할 수는 있지만 작동이 느려질 수도 있습니다.\n\n휴대전화 온도가 낮아지면 정상적으로 작동됩니다."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"비밀번호 요청"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"보안"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"사용자 상태"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 53b109832451..6f57a7355421 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -620,7 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"Алмашуу буфери"</string> <string name="accessibility_key" msgid="5701989859305675896">"Ыңгайлаштырылган чабыттоо баскычы"</string> <string name="keycode" msgid="7335281375728356499">"Баскыч коду"</string> - <string name="icon" msgid="8732339849035837289">"Сөлөкөт"</string> + <string name="icon" msgid="8732339849035837289">"Сүрөтчө"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"Керектүү нерселерди сүйрөп кошуңуз"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Алып салуу үчүн бул жерге сүйрөңүз"</string> <string name="qs_edit" msgid="2232596095725105230">"Түзөтүү"</string> @@ -671,18 +671,18 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Жайып көрсөтүү"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Кичирейтүү"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Этибарга албоо"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефонуңуз ысып баратат"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Телефон сууганча айрым элементтердин иши чектелген"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонуңуз автоматтык түрдө сууйт. Аны колдоно берсеңиз болот, бирок ал жайыраак иштеп калат.\n\nТелефонуңуз суугандан кийин адаттагыдай эле иштеп баштайт."</string> <string name="lockscreen_left" msgid="6806490081187499505">"Сол жакта"</string> <string name="lockscreen_right" msgid="6093496261656102989">"Оң жакта"</string> - <string name="lockscreen_customize" msgid="1288691376862981950">"Кыска жолду ыңгайлаштыруу"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"Кыска жолду тууралоо"</string> <string name="lockscreen_shortcut" msgid="3734369277470360642">"Кыска жол"</string> - <string name="lockscreen_unlock" msgid="4934466194763269051">"Сырсөз үчүн ишарат"</string> - <string name="notification_channel_alerts" msgid="4496839309318519037">"Айгай кабарлар"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"Сырсөздү суроо"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттор"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Коопсуздук"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Колдонуучунун абалы"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы билдирүүлөр"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Сактагыч"</string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index aea7812aedc7..c7475bc61264 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ຂະຫຍາຍ"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ຫຍໍ້"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"ປິດໄວ້"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ໂທລະສັບກຳລັງຮ້ອນຂຶ້ນ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ຄຸນສົມບັດບາງຢ່າງຖືກຈຳກັດໄວ້ເນື່ອງໃນເວລາຫຼຸດອຸນຫະພູມຂອງໂທລະສັບ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"ໂທລະສັບຂອງທ່ານຈະພະຍາຍາມລົດອຸນຫະພູມລົງ. ທ່ານຍັງຄົງສາມາດໃຊ້ໂທລະສັບຂອງທ່ານໄດ້ຢູ່, ແຕ່ມັນຈະເຮັດວຽກຊ້າລົງ.\n\nເມື່ອໂທລະສັບຂອງທ່ານບໍ່ຮ້ອນຫຼາຍແລ້ວ, ມັນຈະກັບມາເຮັດວຽກຕາມປົກກະຕິ."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"ຖາມຫາລະຫັດຜ່ານ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ຮູບຖ່າຍໜ້າຈໍ"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"ຄວາມປອດໄພ"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"ສະຖານະຜູ້ໃຊ້"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"ຂໍ້ຄວາມທົ່ວໄປ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ບ່ອນເກັບຂໍ້ມູນ"</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 83f4d1537147..e6713f2ba207 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -675,7 +675,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Išskleisti"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Sumažinti"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Atsisakyti"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefonas kaista"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Kai kurios funkcijos gali neveikti, kol telefonas vėsta"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonas automatiškai bandys atvėsti. Telefoną vis tiek galėsite naudoti, tačiau jis gali veikti lėčiau.\n\nKai telefonas atvės, jis veiks įprastai."</string> @@ -686,7 +687,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Paraginti įvesti slaptažodį"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrano kopijos"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sauga"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Naudotojų būsena"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Bendrieji pranešimai"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 09581e8324d6..ba6ce3c040f0 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Izvērst"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizēt"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Noraidīt"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Tālrunis kļūst silts"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Dažas funkcijas ir ierobežotas, kamēr tālrunis mēģina atdzist"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Jūsu tālrunis automātiski mēģinās atdzist. Jūs joprojām varat izmantot tālruni, taču tas, iespējams, darbosies lēnāk.\n\nTiklīdz tālrunis būs atdzisis, tas darbosies normāli."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Pieprasīt paroli"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrānuzņēmumi"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Drošība"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Lietotāju statuss"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Vispārīgi ziņojumi"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Krātuve"</string> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 6db8e586fc17..5308d657dc17 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Проширете"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Минимизирај"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Отфрли"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефонот се загрева"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Некои функции се ограничени додека телефонот се лади"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонот автоматски ќе се обиде да се олади. Вие сепак ќе може да го користите, но тој може да работи побавно.\n\nОткако ќе се олади, ќе работи нормално."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Побарај лозинка"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Слики од екранот"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Безбедност"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Кориснички статус"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Општи пораки"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Меморија"</string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 0cdd3513268d..cf32631a1d35 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"ശബ്ദമുണ്ടാക്കുക, സ്ക്രീനിൽ കാണിക്കുക"</string> <string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string> <string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"അറിയിപ്പ് സ്നൂസ് ഓപ്ഷനുകൾ"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"15 മിനിറ്റ്"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"30 മിനിറ്റ്"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"ഒരു മണിക്കൂർ"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"സ്നൂസ് ചെയ്യരുത്"</string> + <string name="snooze_undo" msgid="6074877317002985129">"പഴയപടിയാക്കുക"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> സമയത്തേക്ക് സ്നൂസ് ചെയ്തു"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ബാറ്ററി ഉപയോഗം"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ചാർജുചെയ്യുന്ന സമയത്ത് ബാറ്ററി സേവർ ലഭ്യമല്ല"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"ബാറ്ററി സേവർ"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"ഓൺ"</string> <string name="switch_bar_off" msgid="8803270596930432874">"ഓഫ്"</string> <string name="nav_bar" msgid="1993221402773877607">"നാവിഗേഷൻ ബാർ"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"ലേഔട്ട്"</string> + <string name="nav_bar_left" msgid="731491280511316123">"ഇടത്"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"വലത്"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"ബട്ടൺ തരം"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(ഡിഫോൾട്ട്)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"ക്ലിപ്പ്ബോർഡ്"</item> + <item msgid="5742013440802239414">"കീകോഡ്"</item> + <item msgid="8748101184830239843">"മെനു / കീബോർഡ് സ്വിച്ചർ"</item> + <item msgid="8175437057325747277">"ഒന്നുമില്ല"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"വിഭജിച്ചത് (ഡിഫോൾട്ട്)"</item> + <item msgid="6210279084134579668">"മധ്യഭാഗത്ത് വിന്യസിച്ചത്"</item> + <item msgid="89143234390889289">"ഇടതുവശത്ത് വിന്യസിച്ചത്"</item> + <item msgid="7715533883382410603">"വലതുവശത്ത് വിന്യസിച്ചത്"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"മെനു / കീബോർഡ് സ്വിച്ചർ"</string> <string name="save" msgid="2311877285724540644">"സംരക്ഷിക്കുക"</string> <string name="reset" msgid="2448168080964209908">"പുനഃസജ്ജമാക്കുക"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"ക്ലിപ്പ്ബോർഡ്"</string> <string name="accessibility_key" msgid="5701989859305675896">"ഇഷ്ടാനുസൃത നാവിഗേഷൻ ബട്ടൺ"</string> <string name="keycode" msgid="7335281375728356499">"കീകോഡ്"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"ഐക്കൺ"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"ടൈലുകൾ ചേർക്കുന്നതിന് വലിച്ചിടുക"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"നീക്കംചെയ്യുന്നതിന് ഇവിടെ വലിച്ചിടുക"</string> <string name="qs_edit" msgid="2232596095725105230">"എഡിറ്റുചെയ്യുക"</string> @@ -682,28 +671,19 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"പേജ് <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"വികസിപ്പിക്കുക"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ചെറുതാക്കുക"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"നിരസിക്കുക"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ഫോൺ ചൂടായിക്കൊണ്ടിരിക്കുന്നു"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ഫോൺ തണുത്തുകൊണ്ടിരിക്കുമ്പോൾ ചില ഫീച്ചറുകൾ പരിമിതപ്പെടുത്തപ്പെടും"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"നിങ്ങളുടെ ഫോൺ സ്വയമേവ തണുക്കാൻ ശ്രമിക്കും. നിങ്ങൾക്ക് അപ്പോഴും ഫോൺ ഉപയോഗിക്കാമെങ്കിലും പ്രവർത്തനം മന്ദഗതിയിലായിരിക്കും.\n\nതണുത്തുകഴിഞ്ഞാൽ, ഫോൺ സാധാരണ ഗതിയിൽ പ്രവർത്തിക്കും."</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> + <string name="lockscreen_left" msgid="6806490081187499505">"ഇടത്"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"വലത്"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"കുറുക്കുവഴി ഇഷ്ടാനുസൃതമാക്കുക"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"കുറുക്കുവഴി"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"പാസ്വേഡ് ആവശ്യപ്പെടുക"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"സ്ക്രീൻഷോട്ടുകൾ"</string> + <!-- no translation found for notification_channel_general (4525309436693914482) --> <skip /> + <string name="notification_channel_storage" msgid="3077205683020695313">"സ്റ്റോറേജ്"</string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index d184f84606eb..336429f159e5 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Дэлгэх"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Хаах"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Утас халж эхэлж байна"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Таны утас хөрж байх зуур зарим онцлогийг хязгаарласан"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Таны утас автоматаар хөрөх болно. Та утсаа ашиглаж болох хэдий ч удаан ажиллаж болзошгүй.\n\nТаны утас хөрсний дараагаар хэвийн ажиллана."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Нууц үг шаардах"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Дэлгэцийн зураг дарах"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Аюулгүй байдал"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Хэрэглэгчийн төлөв"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Энгийн зурвас"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Хадгалах сан"</string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index f26f1e5277eb..7b09c9d44241 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"ध्वनी करा आणि स्क्रीनवर पॉप करा"</string> <string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string> <string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रणे"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नूझ पर्याय"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनिटे"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनिटे"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 तास"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"स्नूझ करू नका"</string> + <string name="snooze_undo" msgid="6074877317002985129">"पूर्ववत करा"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> साठी स्नूझ करा"</string> <string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज करताना बॅटरी बचतकर्ता उपलब्ध नाही"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"बॅटरी बचतकर्ता"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string> <string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string> <string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string> + <string name="nav_bar_left" msgid="731491280511316123">"डावा"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"उजवा"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"बटणाचा प्रकार"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(डीफॉल्ट)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"क्लिपबोर्ड"</item> + <item msgid="5742013440802239414">"कीकोड"</item> + <item msgid="8748101184830239843">"मेनू / कीबोर्ड स्विचर"</item> + <item msgid="8175437057325747277">"काहीही नाही"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"विभाजित (डीफॉल्ट)"</item> + <item msgid="6210279084134579668">"मध्यवर्ती"</item> + <item msgid="89143234390889289">"डावे-संरेखित"</item> + <item msgid="7715533883382410603">"उजवे-संरेखित"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"मेनू / कीबोर्ड स्विचर"</string> <string name="save" msgid="2311877285724540644">"जतन करा"</string> <string name="reset" msgid="2448168080964209908">"रीसेट करा"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string> <string name="accessibility_key" msgid="5701989859305675896">"सानुकूल नेव्हिगेशन बटण"</string> <string name="keycode" msgid="7335281375728356499">"कीकोड"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"चिन्ह"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइल जोडण्यासाठी ड्रॅग करा"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"काढण्यासाठी येथे ड्रॅग करा"</string> <string name="qs_edit" msgid="2232596095725105230">"संपादित करा"</string> @@ -682,28 +671,19 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करा"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"लहान करा"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"डिसमिस करा"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"फोन ऊष्ण होत आहे"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"फोन थंड होत असताना काही वैशिष्ट्ये मर्यादित असतात"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"आपला फोन स्वयंचलितपणे थंड होईल. आपण अद्यापही आपला फोन वापरू शकता परंतु तो कदाचित धीमेपणे कार्य करेल.\n\nआपला फोन एकदा थंड झाला की, तो सामान्यपणे कार्य करेल."</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> + <string name="lockscreen_left" msgid="6806490081187499505">"डावा"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"उजवा"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"शॉर्टकट सानुकूल करा"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"शॉर्टकट"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"संकेतशब्दासाठी संकेत"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string> + <!-- no translation found for notification_channel_general (4525309436693914482) --> <skip /> + <string name="notification_channel_storage" msgid="3077205683020695313">"संचय"</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 18fa6d072637..9ba75b224b4f 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Kembangkan"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimumkan"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ketepikan"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon semakin panas"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Sesetengah ciri adalah terhad semasa telefon menyejuk"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon anda akan cuba menyejuk secara automatik. Anda masih dapat menggunakan telefon itu tetapi telefon tersebut mungkin berjalan lebih perlahan.\n\nSetelah telefon anda sejuk, telefon itu akan berjalan seperti biasa."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Gesa untuk kata laluan"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Tangkapan skrin"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Keselamatan"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status pengguna"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mesej Am"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storan"</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 1c4a83e1262c..32ff25dcbdfa 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ချဲ့ရန်"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ချုံ့ရန်"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"ပယ်ရန်"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ဖုန်း ပူနွေးလာပါပြီ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ဖုန်းကို အေးအောင်ပြုလုပ်နေစဉ်တွင် အချို့ဝန်ဆောင်မှုများကို ကန့်သတ်ထားပါသည်"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"သင့်ဖုန်းသည် အလိုအလျောက် ပြန်အေးသွားပါလိမ့်မည်။ ဖုန်းကို အသုံးပြုနိုင်ပါသေးသည် သို့သော် ပိုနှေးနိုင်ပါသည်။\n\nသင့်ဖုန်း အေးသွားသည်နှင့် ပုံမှန်အတိုင်း ပြန်အလုပ်လုပ်ပါလိမ့်မည်။"</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"စကားဝှက်ကို မေးရန်"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"မျက်နှာပြင်ဓာတ်ပုံများ"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"လုံခြုံရေး"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"အသုံးပြုသူ အခြေအနေ"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"အထွေထွေ မက်ဆေ့ဂျ်များ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"သိုလှောင်မှုများ"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index d546e929e0c1..66245833a2fa 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -528,7 +528,7 @@ <string name="notification_done" msgid="5279426047273930175">"Ferdig"</string> <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> <string name="notification_menu_gear_description" msgid="2204480013726775108">"varselinnstillinger"</string> - <string name="notification_menu_snooze_description" msgid="3653669438131034525">"utsettelsesalternativer for varsler"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"slumrealternativer for varsler"</string> <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string> @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Vis"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Avvis"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefonen begynner å bli varm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Enkelte funksjoner er begrenset mens telefonen kjøles ned"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonen din kommer til å prøve å kjøle seg ned automatisk. Du kan fremdeles bruke telefonen, men den kjører muligens saktere.\n\nTelefonen kommer til å kjøre som normalt, når den har kjølt seg ned."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Påminnelse for passord"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjermdumper"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Sikkerhet"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Brukerstatus"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meldinger"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 4f65f63b3e56..ee0499280c5a 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"आवाज निकाल्ने र स्क्रिनमा पपअप देखाउने"</string> <string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string> <string name="notification_done" msgid="5279426047273930175">"सम्पन्न भयो"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना सम्बन्धी नियन्त्रणहरू"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नुज गर्ने विकल्पहरू"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"१५ मिनेट"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"३० मिनेट"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"१ घण्टा"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"स्नुज नगर्नुहोस्"</string> + <string name="snooze_undo" msgid="6074877317002985129">"अनडू गर्नुहोस्"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> का लागि स्नुज गरियो"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज गर्ने समयमा ब्याट्री सेभर उपलब्ध छैन"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"ब्याट्री सेभर"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"सक्रिय गर्नुहोस्"</string> <string name="switch_bar_off" msgid="8803270596930432874">"निष्क्रिय"</string> <string name="nav_bar" msgid="1993221402773877607">"नेभिगेशन पट्टी"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string> + <string name="nav_bar_left" msgid="731491280511316123">"बायाँ"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"दायाँ"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"बटनको प्रकार"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(पूर्वनिर्धारित)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"क्लिपबोर्ड"</item> + <item msgid="5742013440802239414">"किकोड"</item> + <item msgid="8748101184830239843">"मेनु / किबोर्ड परिवर्तक"</item> + <item msgid="8175437057325747277">"कुनै पनि होइन"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"विभाजित (पूर्वनिर्धारित)"</item> + <item msgid="6210279084134579668">"मध्य भागमा"</item> + <item msgid="89143234390889289">"बायाँतिर पङ्क्तिबद्ध"</item> + <item msgid="7715533883382410603">"दायाँतिर पङ्क्तिबद्ध"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"मेनु / किबोर्ड स्विचर"</string> <string name="save" msgid="2311877285724540644">"सुरक्षित गर्नुहोस्"</string> <string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string> <string name="accessibility_key" msgid="5701989859305675896">"अनुकूलनको नेभिगेशन बटन"</string> <string name="keycode" msgid="7335281375728356499">"Keycode"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"आइकन"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइलहरू थप्न तान्नुहोस्"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"हटाउनका लागि यहाँ तान्नुहोस्"</string> <string name="qs_edit" msgid="2232596095725105230">"सम्पादन गर्नुहोस्"</string> @@ -682,28 +671,19 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत गर्नुहोस्"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"सानो बनाउनुहोस्"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"खारेज गर्नुहोस्"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"फोन तातो भइरहेको छ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"फोन चिसो हुँदै गर्दा केही विशेषताहरूलाई सीमित गरिन्छ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"तपाईंको फोन स्वतः चिसो हुने प्रयास गर्नेछ। तपाईं अझै पनि आफ्नो फोनको प्रयोग गर्न सक्नुहुन्छ तर त्यो अझ ढिलो चल्न सक्छ।\n\nचिसो भएपछि तपाईंको फोन सामान्य गतिमा चल्नेछ।"</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> + <string name="lockscreen_left" msgid="6806490081187499505">"बायाँ"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"दायाँ"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"सर्टकट आफू अनुकूल पार्नुहोस्"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"सर्टकट"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"पासवर्ड माग्ने"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रिनशटहरू"</string> + <!-- no translation found for notification_channel_general (4525309436693914482) --> <skip /> + <string name="notification_channel_storage" msgid="3077205683020695313">"भण्डारण"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index dbb777133b20..f4c306a55854 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Uitvouwen"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Sluiten"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"De telefoon wordt warm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Bepaalde functies zijn beperkt terwijl de telefoon afkoelt"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Je telefoon probeert automatisch af te koelen. Je kunt je telefoon nog steeds gebruiken, maar deze kan langzamer werken.\n\nZodra de telefoon is afgekoeld, werkt deze weer normaal."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Wachtwoordprompt"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Beveiliging"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Gebruikersstatus"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Algemene berichten"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Opslag"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 008f55aa0297..97ec2f165f19 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -533,7 +533,7 @@ <string name="snooze_option_30_min" msgid="867081342535195788">"30 ਮਿੰਟ"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ਘੰਟਾ"</string> <string name="snooze_option_dont_snooze" msgid="655446566007801922">"ਸਨੂਜ਼ ਨਾ ਕਰੋ"</string> - <string name="snooze_undo" msgid="6074877317002985129">"ਪਹਿਲਾਂ ਵਰਗਾ ਕਰੋ"</string> + <string name="snooze_undo" msgid="6074877317002985129">"ਅਣਕੀਤਾ ਕਰੋ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ਲਈ ਸਨੂਜ਼ ਕੀਤਾ ਗਿਆ"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> @@ -603,7 +603,7 @@ <string name="nav_bar_default" msgid="8587114043070993007">"(ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</string> <string-array name="nav_bar_buttons"> <item msgid="1545641631806817203">"ਕਲਿੱਪਬੋਰਡ"</item> - <item msgid="5742013440802239414">"ਕੀਕੋਡ"</item> + <item msgid="5742013440802239414">"ਕੀ-ਕੋਡ"</item> <item msgid="8748101184830239843">"ਮੀਨੂ/ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</item> <item msgid="8175437057325747277">"ਕੋਈ ਨਹੀਂ"</item> </string-array> @@ -620,7 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"ਕਲਿੱਪਬੋਰਡ"</string> <string name="accessibility_key" msgid="5701989859305675896">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਆਵਾਗੌਣ ਬਟਨ"</string> <string name="keycode" msgid="7335281375728356499">"ਕੀਕੋਡ"</string> - <string name="icon" msgid="8732339849035837289">"ਚਿੰਨ੍ਹ"</string> + <string name="icon" msgid="8732339849035837289">"ਪ੍ਰਤੀਕ"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"ਟਾਇਲਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਘਸੀਟੋ"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ਹਟਾਉਣ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string> <string name="qs_edit" msgid="2232596095725105230">"ਸੰਪਾਦਨ ਕਰੋ"</string> @@ -671,18 +671,18 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"ਖਾਰਜ ਕਰੋ"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ਫ਼ੋਨ ਗਰਮ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ਫ਼ੋਨ ਦੇ ਠੰਡਾ ਹੋਣ ਦੇ ਦੌਰਾਨ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸੀਮਿਤ ਹੁੰਦੀਆਂ ਹਨ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਵੈਚਲਿਤ ਰੂਪ ਵਿੱਚ ਠੰਡਾ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਵਰਤ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਵਧੇਰੇ ਹੌਲੀ ਚੱਲੇ।\n\nਇੱਕ ਵਾਰ ਠੰਡਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਧਾਰਨ ਤੌਰ \'ਤੇ ਚੱਲੇਗਾ।"</string> <string name="lockscreen_left" msgid="6806490081187499505">"ਖੱਬੇ"</string> <string name="lockscreen_right" msgid="6093496261656102989">"ਸੱਜੇ"</string> - <string name="lockscreen_customize" msgid="1288691376862981950">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਸ਼ਾਰਟਕੱਟ"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ"</string> <string name="lockscreen_shortcut" msgid="3734369277470360642">"ਸ਼ਾਰਟਕੱਟ"</string> - <string name="lockscreen_unlock" msgid="4934466194763269051">"ਪਾਸਵਰਡ ਲਈ ਉਤਪ੍ਰੇਰਕ"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"ਪਾਸਵਰਡ ਲਈ ਪੁੱਛੋ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"ਸੁਰੱਖਿਆ"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"ਵਰਤੋਂਕਾਰ ਸਥਿਤੀ"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"ਆਮ ਸੁਨੇਹੇ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ਸਟੋਰੇਜ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 6e2d00114b09..04efcd4a9fb2 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -675,7 +675,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strona <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Rozwiń"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizuj"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Zamknij"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon się nagrzewa"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Podczas obniżania temperatury telefonu niektóre funkcje są ograniczone"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon automatycznie podejmie próbę obniżenia temperatury. Możesz go wciąż używać, ale telefon może działać wolniej.\n\nGdy temperatura się obniży, telefon będzie działał normalnie."</string> @@ -686,7 +687,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Pytaj o hasło"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Zrzuty ekranu"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Bezpieczeństwo"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Stan użytkownika"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Wiadomości"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Miejsce"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 4ab349c22601..e5a875474f1f 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dispensar"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"O smartphone está esquentando"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Alguns recursos ficam limitados enquanto o smartphone é resfriado"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Seu smartphone tentará se resfriar automaticamente. Você ainda poderá usá-lo, mas talvez ele fique mais lento.\n\nQuando o smartphone estiver resfriado, ele voltará ao normal."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar senha"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status do usuário"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index fa1f70e47a94..4304d9992a0b 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorar"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"O telemóvel está a aquecer"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Algumas funcionalidades são limitadas enquanto o telemóvel arrefece"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"O telemóvel tenta arrefecer automaticamente. Pode continuar a utilizá-lo, mas este poderá funcionar mais lentamente.\n\nAssim que o telemóvel tiver arrefecido, funcionará normalmente."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar palavra-passe"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de ecrã"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Estado do utilizador"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 4ab349c22601..e5a875474f1f 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dispensar"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"O smartphone está esquentando"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Alguns recursos ficam limitados enquanto o smartphone é resfriado"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Seu smartphone tentará se resfriar automaticamente. Você ainda poderá usá-lo, mas talvez ele fique mais lento.\n\nQuando o smartphone estiver resfriado, ele voltará ao normal."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar senha"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status do usuário"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 7dc39d5a6f76..535b5c3ea22e 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -675,7 +675,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Extindeți"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizați"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Respingeți"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefonul se încălzește"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Anumite funcții sunt limitate în timp ce telefonul se răcește"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonul va încerca automat să se răcească. Puteți folosi telefonul în continuare, dar este posibil să funcționeze mai lent.\n\nDupă ce se răcește, telefonul va funcționa normal."</string> @@ -686,7 +687,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitați parola"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturi de ecran"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Securitate"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Stare utilizator"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mesaje generale"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Stocare"</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 5806e23e7b3f..68d499d1cc2e 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -677,7 +677,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Развернуть"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Свернуть"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Закрыть"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефон нагревается"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Пока телефон не остынет, некоторые функции могут быть недоступны."</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш телефон остынет автоматически.\n\nОбратите внимание, что до тех пор он может работать медленнее, чем обычно."</string> @@ -688,7 +689,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Подсказка для пароля"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоты"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Безопасность"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус пользователя"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Сообщения"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 8870fad47a93..9c58ba1e3d7a 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"දිග හරින්න"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"කුඩා කරන්න"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"අස් කරන්න"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"දුරකථනය උණුසුම් වෙමින්"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"දුරකථනය සිසිල් වන අතරතුර සමහර විශේෂාංග සීමිත විය හැකිය"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"ඔබගේ දුරකථනය ස්වයංක්රියව සිසිල් වීමට උත්සාහ කරනු ඇත. ඔබට තවම ඔබේ දුරකථනය භාවිත කළ හැකිය, නමුත් එය සෙමින් ධාවනය විය හැකිය.\n\nඔබේ දුරකථනය සිසිල් වූ පසු, එය සාමාන්ය ලෙස ධාවනය වනු ඇත."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"මුරපදය සඳහා ප්රේරණය කරන්න"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"තිර රු"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"ආරක්ෂාව"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"පරිශීලක තත්ත්වය"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"පොදු පණිවිඩ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ගබඩාව"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 8afa43235e85..cddcaf0a5855 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -677,7 +677,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbaliť"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odmietnuť"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Teplota telefónu stúpa"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Niektoré funkcie budú obmedzené, dokým neklesne teplota telefónu"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Váš telefón sa automaticky pokúsi schladiť. Môžete ho naďalej používať, ale môže fungovať pomalšie.\n\nPo poklese teploty bude telefón fungovať ako normálne."</string> @@ -688,7 +689,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Požadovať heslo"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovky"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Zabezpečenie"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Stav používateľa"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné správy"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Úložisko"</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index f45784788804..da993b4eb9ef 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -677,7 +677,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Razširi"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiraj"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Opusti"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon se segreva"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Nekatere funkcije bodo med ohlajanjem omejene."</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon se bo samodejno poskusil ohladiti. Še naprej ga lahko uporabljate, vendar bo morda deloval počasneje.\n\nKo se telefon ohladi, bo zopet deloval kot običajno."</string> @@ -688,7 +689,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Poziv za geslo"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Posnetki zaslona"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Varnost"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Stanje uporabnika"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Splošna sporočila"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index b7409a021bab..6b8bb9725757 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Zgjero"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizo"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Hiqe"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefoni po bëhet i ngrohtë"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Disa funksione janë të kufizuara kur telefoni është duke u ftohur"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefoni yt do të përpiqet automatikisht që të ftohet. Mund ta përdorësh përsëri telefonin, por ai mund të punojë më ngadalë.\n\nPasi telefoni të jetë ftohur, ai do të punojë si normalisht."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Kërko fjalëkalimin"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamjet e ekranit"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Siguria"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Statusi i përdoruesit"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mesazhe të përgjithshme"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 4b0a5778d469..0af49e4e68f0 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Прошири"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Умањи"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Одбаци"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефон се загрејао"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Неке функције су ограничене док се телефон не охлади"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефон ће аутоматски покушати да се охлади. И даље ћете моћи да користите телефон, али ће спорије реаговати.\n\nКада се телефон охлади, нормално ће радити."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Упит за лозинку"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Снимци екрана"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Безбедност"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус корисника"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Опште поруке"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Меморијски простор"</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index c119da7d751e..9700f0a331d5 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sida <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Utöka"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimera"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorera"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Mobilen börjar bli varm"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Vissa funktioner är begränsade medan mobilen svalnar"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Mobilen försöker svalna automatiskt. Du kan fortfarande använda mobilen, men den kan vara långsammare än vanligt.\n\nMobilen fungerar som vanligt när den har svalnat."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Kräv lösenord"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skärmdumpar"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Säkerhet"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Användarstatus"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Allmänna meddelanden"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 54fc44313ce5..fc9439c94433 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -467,13 +467,13 @@ <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Gonga ili ukomeshe. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string> <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Inaonyesha %s ya vidhibiti vya sauti. Telezesha kidole juu ili uondoe."</string> <string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Imeficha vidhibiti vya sauti"</string> - <string name="system_ui_tuner" msgid="708224127392452018">"Kipokea Ishara cha SystemUI"</string> + <string name="system_ui_tuner" msgid="708224127392452018">"Kirekebishi cha kiolesura cha mfumo"</string> <string name="show_battery_percentage" msgid="5444136600512968798">"Onyesha asilimia ya betri iliyopachikwa"</string> <string name="show_battery_percentage_summary" msgid="3215025775576786037">"Onyesha asilimia ya kiwango cha betri ndani ya aikoni ya sehemu ya arifa inapokuwa haichaji"</string> <string name="quick_settings" msgid="10042998191725428">"Mipangilio ya Haraka"</string> <string name="status_bar" msgid="4877645476959324760">"Sehemu ya kuonyesha hali"</string> <string name="overview" msgid="4018602013895926956">"Muhtasari"</string> - <string name="demo_mode" msgid="2532177350215638026">"Hali ya onyesho la UI ya mfumo"</string> + <string name="demo_mode" msgid="2532177350215638026">"Hali ya onyesho la kirekebishi cha kiolesura cha mfumo"</string> <string name="enable_demo_mode" msgid="4844205668718636518">"Washa hali ya onyesho"</string> <string name="show_demo_mode" msgid="2018336697782464029">"Onyesha hali ya onyesho"</string> <string name="status_bar_ethernet" msgid="5044290963549500128">"Ethaneti"</string> @@ -490,12 +490,12 @@ <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Mtandao-hewa"</string> <string name="accessibility_managed_profile" msgid="6613641363112584120">"Wasifu wa kazini"</string> <string name="tuner_warning_title" msgid="7094689930793031682">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string> - <string name="tuner_warning" msgid="8730648121973575701">"Kipokea Ishara cha System UI kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika, au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string> + <string name="tuner_warning" msgid="8730648121973575701">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string> <string name="tuner_persistent_warning" msgid="8597333795565621795">"Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika, au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string> <string name="got_it" msgid="2239653834387972602">"Nimeelewa"</string> - <string name="tuner_toast" msgid="603429811084428439">"Hongera! Kipokea Ishara cha System UI kimeongezwa kwenye Mipangilio"</string> + <string name="tuner_toast" msgid="603429811084428439">"Hongera! Kirekebishi cha kiolesura cha mfumo kimeongezwa kwenye mipangilio"</string> <string name="remove_from_settings" msgid="8389591916603406378">"Ondoa kwenye Mipangilio"</string> - <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Je, ungependa kuondoa Kipokea ishara cha SystemUI kwenye Mipangilio na uache kutumia vipengele vyake vyote?"</string> + <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Je, ungependa kuondoa Kirekebishi cha kiolesura cha mfumo kwenye mipangilio na uache kutumia vipengele vyake vyote?"</string> <string name="activity_not_found" msgid="348423244327799974">"Programu haijasakinishwa kwenye kifaa chako"</string> <string name="clock_seconds" msgid="7689554147579179507">"Onyesha sekunde za saa"</string> <string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string> @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Panua"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Punguza"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ondoa"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Joto la simu linaongezeka"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Baadhi ya vipengele havitatumika kwenye simu wakati inapoa"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Simu yako itajaribu kupoa kiotomatiki. Bado unaweza kutumia simu yako, lakini huenda ikafanya kazi polepole. \n\nPindi simu yako itakapopoa, itaendelea kufanya kazi kama kawaida."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Omba nenosiri"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Picha za skrini"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Usalama"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Hali ya mtumiaji"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Ujumbe wa Jumla"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Hifadhi"</string> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 68b99bf832b9..b79e8a9ed3cb 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"விரி"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"சிறிதாக்கு"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"நிராகரி"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"மொபைல் சூடாகிறது"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"மொபைலின் வெப்ப அளவு குறையும் போது, சில அம்சங்களைப் பயன்படுத்த முடியாது"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"உங்கள் மொபைலின் வெப்ப அளவு தானாகவே குறையும். தொடர்ந்து நீங்கள் மொபைலைப் பயன்படுத்தலாம், ஆனால் அதன் வேகம் குறைவாக இருக்கக்கூடும்.\n\nமொபைலின் வெப்ப அளவு குறைந்தவுடன், அது இயல்பு நிலையில் இயங்கும்."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"கடவுச்சொல்லைக் கேள்"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ஸ்கிரீன் ஷாட்டுகள்"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"பாதுகாப்பு"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"பயனர் நிலை"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"பொதுச் செய்திகள்"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"சேமிப்பிடம்"</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 69619bd027db..2175c5a49d25 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -600,7 +600,7 @@ <string name="nav_bar_left" msgid="731491280511316123">"ఎడమ"</string> <string name="nav_bar_right" msgid="2523774879720231974">"కుడి"</string> <string name="nav_bar_button_type" msgid="6947806619897153791">"బటన్ రకం"</string> - <string name="nav_bar_default" msgid="8587114043070993007">"(yadha prakaram)"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(డిఫాల్ట్)"</string> <string-array name="nav_bar_buttons"> <item msgid="1545641631806817203">"క్లిప్బోర్డ్"</item> <item msgid="5742013440802239414">"కీకోడ్"</item> @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"విస్తరింపజేయి"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"కనిష్టీకరించు"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"తీసివేయి"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"ఫోన్ వేడెక్కుతోంది"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ఫోన్ను చల్లబరిచే క్రమంలో కొన్ని లక్షణాలు పరిమితం చేయబడ్డాయి"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"మీ ఫోన్ స్వయంచాలకంగా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"పాస్వర్డ్ కోసం ప్రాంప్ట్ చేయి"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"స్క్రీన్షాట్లు"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"భద్రత"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"వినియోగదారు స్థితి"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"సాధారణ సందేశాలు"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"నిల్వ"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index ce7af3ca5421..e4d489d2c7c0 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ขยาย"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ย่อเล็กสุด"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"ปิด"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"โทรศัพท์เริ่มเครื่องร้อน"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"คุณลักษณะบางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"โทรศัพท์จะพยายามลดอุณหภูมิลงโดยอัตโนมัติ คุณยังสามารถใช้โทรศัพท์ได้ แต่โทรศัพท์อาจทำงานช้าลง\n\nโทรศัพท์จะทำงานตามปกติเมื่อเย็นลงแล้ว"</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"แจ้งให้ป้อนรหัสผ่าน"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ภาพหน้าจอ"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"ความปลอดภัย"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"สถานะของผู้ใช้"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"ข้อความทั่วไป"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"พื้นที่เก็บข้อมูล"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 3e632c41bc6c..ac5aa927d9a7 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Palawakin"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"I-minimize"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"I-dismiss"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Umiinit ang telepono"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Limitado ang ilang feature habang nagku-cool down ang telepono"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Awtomatikong susubukan ng iyong telepono na mag-cool down. Magagamit mo pa rin ang iyong telepono, ngunit maaaring mas mabagal ang paggana nito.\n\nKapag nakapag-cool down na ang iyong telepono, gagana na ito nang normal."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Mag-prompt para sa password"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Mga Screenshot"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Status ng user"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Mga Pangkalahatang Mensahe"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 3d00f1d29026..8cf0633f073d 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Genişlet"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Kapat"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon ısınıyor"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon soğurken bazı özellikler sınırlı olarak kullanılabilir"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonunuz otomatik olarak soğumaya çalışacak. Bu sırada telefonunuzu kullanmaya devam edebilirsiniz ancak uygulamalar daha yavaş çalışabilir.\n\nTelefonunuz soğuduktan sonra normal şekilde çalışacaktır."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Şifre sor"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekran görüntüleri"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Güvenlik"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Kullanıcı durumu"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Genel Mesajlar"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Depolama alanı"</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 4d928d9a102e..62c0c8c0968f 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -677,7 +677,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Розгорнути"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Згорнути"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Вимкнути"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Телефон нагрівається"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Під час охолодження деякі функції обмежуються"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш телефон охолоджуватиметься автоматично. Ви можете далі користуватися телефоном, але він може працювати повільніше.\n\nКоли телефон охолоне, він працюватиме належним чином."</string> @@ -688,7 +689,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Запит пароля"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Знімки екрана"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Безпека"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус користувача"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Загальні повідомлення"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Пам’ять"</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index d8ab5f8efac4..9a7629b47fbe 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -526,24 +526,15 @@ <string name="notification_importance_high" msgid="3316555356062640222">"آواز نکالیں اور اسکرین پر پاپ کریں"</string> <string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string> <string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string> - <!-- no translation found for notification_menu_accessibility (2046162834248888553) --> - <skip /> - <!-- no translation found for notification_menu_gear_description (2204480013726775108) --> - <skip /> - <!-- no translation found for notification_menu_snooze_description (3653669438131034525) --> - <skip /> - <!-- no translation found for snooze_option_15_min (1068727451405610715) --> - <skip /> - <!-- no translation found for snooze_option_30_min (867081342535195788) --> - <skip /> - <!-- no translation found for snooze_option_1_hour (1098086401880077154) --> - <skip /> - <!-- no translation found for snooze_option_dont_snooze (655446566007801922) --> - <skip /> - <!-- no translation found for snooze_undo (6074877317002985129) --> - <skip /> - <!-- no translation found for snoozed_for_time (2390718332980204462) --> - <skip /> + <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"اطلاع کے کنٹرولز"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"اطلاع اسنوز کرنے کے اختیارات"</string> + <string name="snooze_option_15_min" msgid="1068727451405610715">"15 منٹ"</string> + <string name="snooze_option_30_min" msgid="867081342535195788">"30 منٹ"</string> + <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 گھنٹہ"</string> + <string name="snooze_option_dont_snooze" msgid="655446566007801922">"اسنوز نہ کريں"</string> + <string name="snooze_undo" msgid="6074877317002985129">"کالعدم کریں"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> کیلئے اسنوز کیا گیا"</string> <string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"چارجنگ کے دوران بیٹری سیور دستیاب نہیں ہے"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"بیٹری سیور"</string> @@ -605,24 +596,23 @@ <string name="switch_bar_on" msgid="1142437840752794229">"آن"</string> <string name="switch_bar_off" msgid="8803270596930432874">"آف"</string> <string name="nav_bar" msgid="1993221402773877607">"نیویگیشن بار"</string> - <!-- no translation found for nav_bar_layout (3664072994198772020) --> - <skip /> - <!-- no translation found for nav_bar_left (731491280511316123) --> - <skip /> - <!-- no translation found for nav_bar_right (2523774879720231974) --> - <skip /> - <!-- no translation found for nav_bar_button_type (6947806619897153791) --> - <skip /> - <!-- no translation found for nav_bar_default (8587114043070993007) --> - <skip /> - <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) --> - <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) --> - <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) --> - <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) --> - <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) --> - <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) --> - <!-- no translation found for nav_bar_layouts:2 (89143234390889289) --> - <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) --> + <string name="nav_bar_layout" msgid="3664072994198772020">"لے آؤٹ"</string> + <string name="nav_bar_left" msgid="731491280511316123">"بائیں"</string> + <string name="nav_bar_right" msgid="2523774879720231974">"دائیں"</string> + <string name="nav_bar_button_type" msgid="6947806619897153791">"بٹن کی قسم"</string> + <string name="nav_bar_default" msgid="8587114043070993007">"(ڈیفالٹ)"</string> + <string-array name="nav_bar_buttons"> + <item msgid="1545641631806817203">"کلپ بورڈ"</item> + <item msgid="5742013440802239414">"کی کوڈ"</item> + <item msgid="8748101184830239843">"مینو/ کی بورڈ سوئچر"</item> + <item msgid="8175437057325747277">"کوئی نہیں"</item> + </string-array> + <string-array name="nav_bar_layouts"> + <item msgid="4967898371682516967">"تقسیم شدہ (ڈیفالٹ)"</item> + <item msgid="6210279084134579668">"بیچوں بیچ"</item> + <item msgid="89143234390889289">"بائیں جانب موافق کردہ"</item> + <item msgid="7715533883382410603">"دائیں جانب موافق کردہ"</item> + </string-array> <string name="menu_ime" msgid="4943221416525250684">"مینو/ کی بورڈ سوئچر"</string> <string name="save" msgid="2311877285724540644">"محفوظ کریں"</string> <string name="reset" msgid="2448168080964209908">"دوبارہ ترتیب دیں"</string> @@ -630,8 +620,7 @@ <string name="clipboard" msgid="1313879395099896312">"کلپ بورڈ"</string> <string name="accessibility_key" msgid="5701989859305675896">"حسب ضرورت نیویگیشن بٹن"</string> <string name="keycode" msgid="7335281375728356499">"کی کوڈ"</string> - <!-- no translation found for icon (8732339849035837289) --> - <skip /> + <string name="icon" msgid="8732339849035837289">"آئیکن"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"ٹائٹلز شامل کرنے کیلئے گھسیٹیں"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ہٹانے کیلئے یہاں گھسیٹیں؟"</string> <string name="qs_edit" msgid="2232596095725105230">"ترمیم کریں"</string> @@ -682,28 +671,19 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"پھیلائیں"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"چھوٹی کریں"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"برخاست کریں"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"فون گرم ہو رہا ہے"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"فون کے ٹھنڈے ہو جانے تک کچھ خصوصیات محدود ہیں"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"آپ کا فون خودکار طور پر ٹھنڈا ہونے کی کوشش کرے گا۔ آپ ابھی بھی اپنا فون استعمال کر سکتے ہیں، مگر ہو سکتا ہے یہ سست چلے۔\n\nایک بار آپ کا فون ٹھنڈا ہوجائے تو یہ معمول کے مطابق چلے گا۔"</string> - <!-- no translation found for lockscreen_left (6806490081187499505) --> - <skip /> - <!-- no translation found for lockscreen_right (6093496261656102989) --> - <skip /> - <!-- no translation found for lockscreen_customize (1288691376862981950) --> - <skip /> - <!-- no translation found for lockscreen_shortcut (3734369277470360642) --> - <skip /> - <!-- no translation found for lockscreen_unlock (4934466194763269051) --> - <skip /> - <!-- no translation found for notification_channel_alerts (4496839309318519037) --> - <skip /> - <!-- no translation found for notification_channel_screenshot (6314080179230000938) --> - <skip /> - <!-- no translation found for notification_channel_security (7345516133431326347) --> - <skip /> - <!-- no translation found for notification_channel_user_status (1436913581465146650) --> - <skip /> - <!-- no translation found for notification_channel_storage (3077205683020695313) --> + <string name="lockscreen_left" msgid="6806490081187499505">"بائیں"</string> + <string name="lockscreen_right" msgid="6093496261656102989">"دائیں"</string> + <string name="lockscreen_customize" msgid="1288691376862981950">"شارٹ کٹ کو حسب ضرورت بنائیں"</string> + <string name="lockscreen_shortcut" msgid="3734369277470360642">"شارٹ کٹ"</string> + <string name="lockscreen_unlock" msgid="4934466194763269051">"پاسورڈ کا اشارہ"</string> + <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string> + <string name="notification_channel_screenshot" msgid="6314080179230000938">"اسکرین شاٹس"</string> + <!-- no translation found for notification_channel_general (4525309436693914482) --> <skip /> + <string name="notification_channel_storage" msgid="3077205683020695313">"اسٹوریج"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index f72092b8f17b..f6df9068e9bc 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -529,14 +529,14 @@ <string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string> <string name="notification_done" msgid="5279426047273930175">"Tayyor"</string> <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> - <string name="notification_menu_gear_description" msgid="2204480013726775108">"bildirishnomalarni boshqarish elementlari"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"bildirishnoma sozlamalari"</string> <string name="notification_menu_snooze_description" msgid="3653669438131034525">"bildirishnomalarni kechiktirish parametrlari"</string> <string name="snooze_option_15_min" msgid="1068727451405610715">"15 daqiqa"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 daqiqa"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 soat"</string> <string name="snooze_option_dont_snooze" msgid="655446566007801922">"Kechiktirilmasin"</string> <string name="snooze_undo" msgid="6074877317002985129">"BEKOR QILISH"</string> - <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> kechiktirildi"</string> + <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> muddatga kechiktirildi"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string> <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string> <string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string> @@ -606,12 +606,12 @@ <string-array name="nav_bar_buttons"> <item msgid="1545641631806817203">"Vaqtinchalik xotira"</item> <item msgid="5742013440802239414">"Tugma kodi"</item> - <item msgid="8748101184830239843">"Menyu yoki klaviatura"</item> - <item msgid="8175437057325747277">"Hech qaysi"</item> + <item msgid="8748101184830239843">"Menyu/klaviaturani almashtirish"</item> + <item msgid="8175437057325747277">"Hech biri"</item> </string-array> <string-array name="nav_bar_layouts"> - <item msgid="4967898371682516967">"Bo‘lingan (standart)"</item> - <item msgid="6210279084134579668">"O‘rtaga tekislangan"</item> + <item msgid="4967898371682516967">"Alohida (standart)"</item> + <item msgid="6210279084134579668">"Markazda"</item> <item msgid="89143234390889289">"Chapga tekislangan"</item> <item msgid="7715533883382410603">"O‘ngga tekislangan"</item> </string-array> @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Yoyish"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Yig‘ish"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Yopish"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Telefon qizib ketdi"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon sovish paytida ayrim funksiyalar ishlamasligi mumkin"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon avtomatik ravishda o‘zini sovitadi. Telefoningizdan foydalanishda davom etishingiz mumkin, lekin u sekinroq ishlashi mumkin.\n\nTelefon sovishi bilan normal holatda ishlashni boshlaydi."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Parol uchun bildirgi"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinshotlar"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Xavfsizlik"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Foydalanuvchi holati"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Umumiy xabarlar"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Xotira"</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index e33328a596cd..ce5d46fe1356 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Mở rộng"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Thu nhỏ"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Loại bỏ"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Điện thoại đang nóng lên"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Một số tính năng bị hạn chế trong khi điện thoại nguội dần"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Điện thoại của bạn sẽ tự động nguội dần. Bạn vẫn có thể sử dụng điện thoại, nhưng điện thoại có thể chạy chậm hơn. \n\nSau khi đã nguội, điện thoại sẽ chạy bình thường."</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Lời nhắc nhập mật khẩu"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ảnh chụp màn hình"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Bảo mật"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Trạng thái người dùng"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Thông báo chung"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Bộ nhớ"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index f754c38aec07..d0c9e001941f 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"展开"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"关闭"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"手机温度上升中"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"手机降温时,部分功能的使用会受限制"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"您的手机将自动尝试降温。您依然可以使用您的手机,但是手机运行速度可能会更慢。\n\n手机降温后,就会恢复正常的运行速度。"</string> @@ -682,7 +683,7 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"提示输入密码"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"屏幕截图"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"用户状态"</string> + <!-- no translation found for notification_channel_general (4525309436693914482) --> + <skip /> <string name="notification_channel_storage" msgid="3077205683020695313">"存储空间"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index ca882ab3b037..f7bf78e6b3a8 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -673,7 +673,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"關閉"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"手機溫度正在上升"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"手機降溫時,部分功能會受限制"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"手機會自動嘗試降溫。您仍可以使用手機,但手機的運作速度可能較慢。\n\n手機降溫後便會恢復正常。"</string> @@ -684,7 +685,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"輸入密碼提示"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"使用者狀態"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 82ef5ee6a099..54ef0a6449ff 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"關閉"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"手機變熱"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"手機降溫時,部分功能會受限"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"手機會自動嘗試降溫。你仍可繼續使用手機,但是手機的運作速度可能會較慢。\n\n手機降溫完畢後,就會恢復正常的運作速度。"</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"提示輸入密碼"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"使用者狀態"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 1a6b8d014bac..78589627d6e7 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -671,7 +671,8 @@ <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"Nweba"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Nciphisa"</string> - <string name="pip_phone_dismiss" msgid="1305916715402775904">"Cashisa"</string> + <!-- no translation found for pip_phone_close (8416647892889710330) --> + <skip /> <string name="high_temp_title" msgid="4589508026407318374">"Ifoni iyafudumala"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"Ezinye izici zikhawulelwe ngenkathi ifoni iphola"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ifoni yakho izozama ngokuzenzakalela ukuphola. Ungasasebenzisa ifoni yakho, kodwa ingasebenza ngokungasheshi.\n\nUma ifoni yakho isipholile, izosebenza ngokuvamile."</string> @@ -682,7 +683,6 @@ <string name="lockscreen_unlock" msgid="4934466194763269051">"Yalela iphasiwedi"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Izithombe-skrini"</string> - <string name="notification_channel_security" msgid="7345516133431326347">"Ukuphepha"</string> - <string name="notification_channel_user_status" msgid="1436913581465146650">"Isimo somsebenzisi"</string> + <string name="notification_channel_general" msgid="4525309436693914482">"Imilayezo ejwayelekile"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Isitoreji"</string> </resources> diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml deleted file mode 100644 index bf0cba22ab0c..000000000000 --- a/packages/SystemUI/res/values/arrays.xml +++ /dev/null @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/assets/res/any/colors.xml -** -** Copyright 2012, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- BatteryMeterView parameters --> - <array name="batterymeter_color_levels"> - <item>15</item> - <item>100</item> - </array> - <array name="batterymeter_color_values"> - <item>@*android:color/battery_saver_mode_color</item> - <item>#FFFFFFFF</item> - </array> - <array name="batterymeter_bolt_points"> - <item>73</item> <item>0</item> - <item>392</item><item>0</item> - <item>201</item><item>259</item> - <item>442</item><item>259</item> - <item>4</item> <item>703</item> - <item>157</item><item>334</item> - <item>0</item> <item>334</item> - </array> - <array name="batterymeter_plus_points"> - <item>3</item><item>0</item> - <item>5</item><item>0</item> - <item>5</item><item>3</item> - <item>8</item><item>3</item> - <item>8</item><item>5</item> - <item>5</item><item>5</item> - <item>5</item><item>8</item> - <item>3</item><item>8</item> - <item>3</item><item>5</item> - <item>0</item><item>5</item> - <item>0</item><item>3</item> - <item>3</item><item>3</item> - </array> -</resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index ad5b108f62b5..1249f44cfabf 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -26,9 +26,6 @@ <drawable name="status_bar_notification_row_background_color">#ff090909</drawable> <color name="notification_list_shadow_top">#80000000</color> <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable> - <color name="batterymeter_frame_color">#4DFFFFFF</color><!-- 30% white --> - <color name="batterymeter_charge_color">#FFFFFFFF</color> - <color name="batterymeter_bolt_color">#FFFFFFFF</color> <color name="qs_batterymeter_frame_color">#FF404040</color> <color name="system_warning_color">@*android:color/system_error</color> <color name="qs_tile_divider">#29ffffff</color><!-- 16% white --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index b768f9086675..e69c4a3ed22b 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -520,14 +520,6 @@ <!-- How much two taps can be apart to still be recognized as a double tap on the lockscreen --> <dimen name="double_tap_slop">32dp</dimen> - <!-- Margin on the right side of the system icon group on Keyguard. --> - <fraction name="battery_button_height_fraction">10.5%</fraction> - - <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this - fraction of a pixel.--> - <fraction name="battery_subpixel_smoothing_left">0%</fraction> - <fraction name="battery_subpixel_smoothing_right">0%</fraction> - <dimen name="battery_margin_bottom">0dp</dimen> <!-- Padding at the end of the view that displays the mobile signal icons. If the view is @@ -642,9 +634,6 @@ <dimen name="docked_divider_handle_width">16dp</dimen> <dimen name="docked_divider_handle_height">2dp</dimen> - <dimen name="battery_height">14.5dp</dimen> - <dimen name="battery_width">9.5dp</dimen> - <dimen name="battery_detail_graph_space_top">27dp</dimen> <dimen name="battery_detail_graph_space_bottom">27dp</dimen> diff --git a/packages/SystemUI/res/values/dimens_grid.xml b/packages/SystemUI/res/values/dimens_grid.xml index 5858443f6d8d..febf65b834ee 100644 --- a/packages/SystemUI/res/values/dimens_grid.xml +++ b/packages/SystemUI/res/values/dimens_grid.xml @@ -22,6 +22,7 @@ <dimen name="recents_grid_task_view_header_height">44dp</dimen> <dimen name="recents_grid_task_view_header_button_padding">8dp</dimen> <dimen name="recents_grid_task_view_focused_frame_thickness">8dp</dimen> - <dimen name="recents_grid_task_view_rounded_corners_radius">8dp</dimen> + <dimen name="recents_grid_task_view_rounded_corners_radius">4dp</dimen> + <dimen name="recents_grid_task_view_focused_frame_rounded_corners_radius">8dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 2cc2621f7c5c..f7cf444d2350 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -819,9 +819,6 @@ <!-- Expanded Status Bar Header: Not charging [CHAR LIMIT=40] --> <string name="expanded_header_battery_not_charging">Not charging</string> - <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. --> - <string name="battery_meter_very_low_overlay_symbol">!</string> - <!-- Shows up when there is a user SSL CA Cert installed on the device. Indicates to the user that SSL traffic can be intercepted. If the text fits on one line (~14 chars), it should start with a @@ -1763,14 +1760,6 @@ not appear on production builds ever. --> <string name="pip_drag_to_dismiss_summary" translatable="false">Drag to the dismiss target at the bottom of the screen to close the PIP</string> - <!-- PIP allow minimize title. Non-translatable since it should - not appear on production builds ever. --> - <string name="pip_allow_minimize_title" translatable="false">Allow PIP to minimize</string> - - <!-- PIP allow minimize description. Non-translatable since it should - not appear on production builds ever. --> - <string name="pip_allow_minimize_summary" translatable="false">Allow PIP to minimize slightly offscreen</string> - <!-- Tuner string --> <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string> <!-- Tuner string --> diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 94a7c071ec75..6198ab7a3b73 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -131,12 +131,6 @@ android:summary="@string/pip_drag_to_dismiss_summary" sysui:defValue="false" /> - <com.android.systemui.tuner.TunerSwitch - android:key="pip_allow_minimize" - android:title="@string/pip_allow_minimize_title" - android:summary="@string/pip_allow_minimize_summary" - sysui:defValue="true" /> - </PreferenceScreen> <PreferenceScreen diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java index 5a6afca627ec..2bdb2f33a37e 100755..100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java @@ -16,193 +16,24 @@ package com.android.systemui; -import android.animation.ArgbEvaluator; -import android.annotation.Nullable; import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; import android.database.ContentObserver; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Handler; import android.provider.Settings; - +import com.android.settingslib.graph.BatteryMeterDrawableBase; import com.android.systemui.statusbar.policy.BatteryController; -public class BatteryMeterDrawable extends Drawable implements +public class BatteryMeterDrawable extends BatteryMeterDrawableBase implements BatteryController.BatteryStateChangeCallback { - private static final float ASPECT_RATIO = 9.5f / 14.5f; - public static final String TAG = BatteryMeterDrawable.class.getSimpleName(); - public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; - - private static final boolean SINGLE_DIGIT_PERCENT = false; - - private static final int FULL = 96; - - private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction - - private final int[] mColors; - private final int mIntrinsicWidth; - private final int mIntrinsicHeight; - - private boolean mShowPercent; - private float mButtonHeightFraction; - private float mSubpixelSmoothingLeft; - private float mSubpixelSmoothingRight; - private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint, - mPlusPaint; - private float mTextHeight, mWarningTextHeight; - private int mIconTint = Color.WHITE; - private float mOldDarkIntensity = 0f; - - private int mHeight; - private int mWidth; - private String mWarningString; - private final int mCriticalLevel; - private int mChargeColor; - private final float[] mBoltPoints; - private final Path mBoltPath = new Path(); - private final float[] mPlusPoints; - private final Path mPlusPath = new Path(); - - private final RectF mFrame = new RectF(); - private final RectF mButtonFrame = new RectF(); - private final RectF mBoltFrame = new RectF(); - private final RectF mPlusFrame = new RectF(); - - private final Path mShapePath = new Path(); - private final Path mClipPath = new Path(); - private final Path mTextPath = new Path(); - private BatteryController mBatteryController; - private boolean mPowerSaveEnabled; - - private int mDarkModeBackgroundColor; - private int mDarkModeFillColor; - - private int mLightModeBackgroundColor; - private int mLightModeFillColor; - - private final SettingObserver mSettingObserver; - - private final Context mContext; - - private int mLevel = -1; - private boolean mPluggedIn; - private boolean mListening; + private SettingObserver mSettingObserver; public BatteryMeterDrawable(Context context, int frameColor) { - mContext = context; - mSettingObserver = new SettingObserver(new Handler(mContext.getMainLooper())); - final Resources res = context.getResources(); - TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); - TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); - - final int N = levels.length(); - mColors = new int[2*N]; - for (int i=0; i<N; i++) { - mColors[2*i] = levels.getInt(i, 0); - mColors[2*i+1] = colors.getColor(i, 0); - } - levels.recycle(); - colors.recycle(); - updateShowPercent(); - mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); - mCriticalLevel = mContext.getResources().getInteger( - com.android.internal.R.integer.config_criticalBatteryWarningLevel); - mButtonHeightFraction = context.getResources().getFraction( - R.fraction.battery_button_height_fraction, 1, 1); - mSubpixelSmoothingLeft = context.getResources().getFraction( - R.fraction.battery_subpixel_smoothing_left, 1, 1); - mSubpixelSmoothingRight = context.getResources().getFraction( - R.fraction.battery_subpixel_smoothing_right, 1, 1); - - mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mFramePaint.setColor(frameColor); - mFramePaint.setDither(true); - mFramePaint.setStrokeWidth(0); - mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); - - mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBatteryPaint.setDither(true); - mBatteryPaint.setStrokeWidth(0); - mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); - - mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); - mTextPaint.setTypeface(font); - mTextPaint.setTextAlign(Paint.Align.CENTER); - - mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mWarningTextPaint.setColor(mColors[1]); - font = Typeface.create("sans-serif", Typeface.BOLD); - mWarningTextPaint.setTypeface(font); - mWarningTextPaint.setTextAlign(Paint.Align.CENTER); - - mChargeColor = context.getColor(R.color.batterymeter_charge_color); - - mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color)); - mBoltPoints = loadBoltPoints(res); - - mPlusPaint = new Paint(mBoltPaint); - mPlusPoints = loadPlusPoints(res); - - mDarkModeBackgroundColor = - context.getColor(R.color.dark_mode_icon_color_dual_tone_background); - mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill); - mLightModeBackgroundColor = - context.getColor(R.color.light_mode_icon_color_dual_tone_background); - mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill); - - mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width); - mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height); - } - - @Override - public int getIntrinsicHeight() { - return mIntrinsicHeight; - } - - @Override - public int getIntrinsicWidth() { - return mIntrinsicWidth; - } - - public void startListening() { - mListening = true; - mContext.getContentResolver().registerContentObserver( - Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); - updateShowPercent(); - mBatteryController.addCallback(this); - } - - public void stopListening() { - mListening = false; - mContext.getContentResolver().unregisterContentObserver(mSettingObserver); - mBatteryController.removeCallback(this); - } + super(context, frameColor); - public void disableShowPercent() { - mShowPercent = false; - postInvalidate(); - } - - private void postInvalidate() { - scheduleSelf(this::invalidateSelf, 0); - } - - public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; - mPowerSaveEnabled = mBatteryController.isPowerSave(); + mSettingObserver = new SettingObserver(new Handler(mContext.getMainLooper())); } @Override @@ -219,293 +50,27 @@ public class BatteryMeterDrawable extends Drawable implements invalidateSelf(); } - private static float[] loadBoltPoints(Resources res) { - final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); - int maxX = 0, maxY = 0; - for (int i = 0; i < pts.length; i += 2) { - maxX = Math.max(maxX, pts[i]); - maxY = Math.max(maxY, pts[i + 1]); - } - final float[] ptsF = new float[pts.length]; - for (int i = 0; i < pts.length; i += 2) { - ptsF[i] = (float)pts[i] / maxX; - ptsF[i + 1] = (float)pts[i + 1] / maxY; - } - return ptsF; + public void startListening() { + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); + updateShowPercent(); + mBatteryController.addCallback(this); } - private static float[] loadPlusPoints(Resources res) { - final int[] pts = res.getIntArray(R.array.batterymeter_plus_points); - int maxX = 0, maxY = 0; - for (int i = 0; i < pts.length; i += 2) { - maxX = Math.max(maxX, pts[i]); - maxY = Math.max(maxY, pts[i + 1]); - } - final float[] ptsF = new float[pts.length]; - for (int i = 0; i < pts.length; i += 2) { - ptsF[i] = (float)pts[i] / maxX; - ptsF[i + 1] = (float)pts[i + 1] / maxY; - } - return ptsF; + public void stopListening() { + mContext.getContentResolver().unregisterContentObserver(mSettingObserver); + mBatteryController.removeCallback(this); } @Override - public void setBounds(int left, int top, int right, int bottom) { - super.setBounds(left, top, right, bottom); - mHeight = bottom - top; - mWidth = right - left; - mWarningTextPaint.setTextSize(mHeight * 0.75f); - mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; - } - - private void updateShowPercent() { + protected void updateShowPercent() { mShowPercent = 0 != Settings.System.getInt(mContext.getContentResolver(), SHOW_PERCENT_SETTING, 0); } - private int getColorForLevel(int percent) { - - // If we are in power save mode, always use the normal color. - if (mPowerSaveEnabled) { - return mColors[mColors.length-1]; - } - int thresh, color = 0; - for (int i=0; i<mColors.length; i+=2) { - thresh = mColors[i]; - color = mColors[i+1]; - if (percent <= thresh) { - - // Respect tinting for "normal" level - if (i == mColors.length-2) { - return mIconTint; - } else { - return color; - } - } - } - return color; - } - - public void setDarkIntensity(float darkIntensity) { - if (darkIntensity == mOldDarkIntensity) { - return; - } - int backgroundColor = getBackgroundColor(darkIntensity); - int fillColor = getFillColor(darkIntensity); - setColors(fillColor, backgroundColor); - mOldDarkIntensity = darkIntensity; - } - - public void setColors(int fillColor, int backgroundColor) { - mIconTint = fillColor; - mFramePaint.setColor(backgroundColor); - mBoltPaint.setColor(fillColor); - mChargeColor = fillColor; - invalidateSelf(); - } - - private int getBackgroundColor(float darkIntensity) { - return getColorForDarkIntensity( - darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor); - } - - private int getFillColor(float darkIntensity) { - return getColorForDarkIntensity( - darkIntensity, mLightModeFillColor, mDarkModeFillColor); - } - - private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) { - return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor); - } - - @Override - public void draw(Canvas c) { - final int level = mLevel; - - if (level == -1) return; - - float drawFrac = (float) level / 100f; - final int height = mHeight; - final int width = (int) (ASPECT_RATIO * mHeight); - int px = (mWidth - width) / 2; - - final int buttonHeight = (int) (height * mButtonHeightFraction); - - mFrame.set(0, 0, width, height); - mFrame.offset(px, 0); - - // button-frame: area above the battery body - mButtonFrame.set( - mFrame.left + Math.round(width * 0.25f), - mFrame.top, - mFrame.right - Math.round(width * 0.25f), - mFrame.top + buttonHeight); - - mButtonFrame.top += mSubpixelSmoothingLeft; - mButtonFrame.left += mSubpixelSmoothingLeft; - mButtonFrame.right -= mSubpixelSmoothingRight; - - // frame: battery body area - mFrame.top += buttonHeight; - mFrame.left += mSubpixelSmoothingLeft; - mFrame.top += mSubpixelSmoothingLeft; - mFrame.right -= mSubpixelSmoothingRight; - mFrame.bottom -= mSubpixelSmoothingRight; - - // set the battery charging color - mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level)); - - if (level >= FULL) { - drawFrac = 1f; - } else if (level <= mCriticalLevel) { - drawFrac = 0f; - } - - final float levelTop = drawFrac == 1f ? mButtonFrame.top - : (mFrame.top + (mFrame.height() * (1f - drawFrac))); - - // define the battery shape - mShapePath.reset(); - mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); - mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); - mShapePath.lineTo(mButtonFrame.right, mFrame.top); - mShapePath.lineTo(mFrame.right, mFrame.top); - mShapePath.lineTo(mFrame.right, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); - - if (mPluggedIn) { - // define the bolt shape - final float bl = mFrame.left + mFrame.width() / 4f; - final float bt = mFrame.top + mFrame.height() / 6f; - final float br = mFrame.right - mFrame.width() / 4f; - final float bb = mFrame.bottom - mFrame.height() / 10f; - if (mBoltFrame.left != bl || mBoltFrame.top != bt - || mBoltFrame.right != br || mBoltFrame.bottom != bb) { - mBoltFrame.set(bl, bt, br, bb); - mBoltPath.reset(); - mBoltPath.moveTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); - for (int i = 2; i < mBoltPoints.length; i += 2) { - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); - } - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); - } - - float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); - boltPct = Math.min(Math.max(boltPct, 0), 1); - if (boltPct <= BOLT_LEVEL_THRESHOLD) { - // draw the bolt if opaque - c.drawPath(mBoltPath, mBoltPaint); - } else { - // otherwise cut the bolt out of the overall shape - mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); - } - } else if (mPowerSaveEnabled) { - // define the plus shape - final float pw = mFrame.width() * 2 / 3; - final float pl = mFrame.left + (mFrame.width() - pw) / 2; - final float pt = mFrame.top + (mFrame.height() - pw) / 2; - final float pr = mFrame.right - (mFrame.width() - pw) / 2; - final float pb = mFrame.bottom - (mFrame.height() - pw) / 2; - if (mPlusFrame.left != pl || mPlusFrame.top != pt - || mPlusFrame.right != pr || mPlusFrame.bottom != pb) { - mPlusFrame.set(pl, pt, pr, pb); - mPlusPath.reset(); - mPlusPath.moveTo( - mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), - mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); - for (int i = 2; i < mPlusPoints.length; i += 2) { - mPlusPath.lineTo( - mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(), - mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height()); - } - mPlusPath.lineTo( - mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), - mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); - } - - float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top); - boltPct = Math.min(Math.max(boltPct, 0), 1); - if (boltPct <= BOLT_LEVEL_THRESHOLD) { - // draw the bolt if opaque - c.drawPath(mPlusPath, mPlusPaint); - } else { - // otherwise cut the bolt out of the overall shape - mShapePath.op(mPlusPath, Path.Op.DIFFERENCE); - } - } - - // compute percentage text - boolean pctOpaque = false; - float pctX = 0, pctY = 0; - String pctText = null; - if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) { - mTextPaint.setColor(getColorForLevel(level)); - mTextPaint.setTextSize(height * - (SINGLE_DIGIT_PERCENT ? 0.75f - : (mLevel == 100 ? 0.38f : 0.5f))); - mTextHeight = -mTextPaint.getFontMetrics().ascent; - pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); - pctX = mWidth * 0.5f; - pctY = (mHeight + mTextHeight) * 0.47f; - pctOpaque = levelTop > pctY; - if (!pctOpaque) { - mTextPath.reset(); - mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); - // cut the percentage text out of the overall shape - mShapePath.op(mTextPath, Path.Op.DIFFERENCE); - } - } - - // draw the battery shape background - c.drawPath(mShapePath, mFramePaint); - - // draw the battery shape, clipped to charging level - mFrame.top = levelTop; - mClipPath.reset(); - mClipPath.addRect(mFrame, Path.Direction.CCW); - mShapePath.op(mClipPath, Path.Op.INTERSECT); - c.drawPath(mShapePath, mBatteryPaint); - - if (!mPluggedIn && !mPowerSaveEnabled) { - if (level <= mCriticalLevel) { - // draw the warning text - final float x = mWidth * 0.5f; - final float y = (mHeight + mWarningTextHeight) * 0.48f; - c.drawText(mWarningString, x, y, mWarningTextPaint); - } else if (pctOpaque) { - // draw the percentage text - c.drawText(pctText, pctX, pctY, mTextPaint); - } - } - } - - // Some stuff required by Drawable. - @Override - public void setAlpha(int alpha) { - } - - @Override - public void setColorFilter(@Nullable ColorFilter colorFilter) { - mFramePaint.setColorFilter(colorFilter); - mBatteryPaint.setColorFilter(colorFilter); - mWarningTextPaint.setColorFilter(colorFilter); - mTextPaint.setColorFilter(colorFilter); - mBoltPaint.setColorFilter(colorFilter); - mPlusPaint.setColorFilter(colorFilter); - } - - @Override - public int getOpacity() { - return 0; + public void setBatteryController(BatteryController batteryController) { + mBatteryController = batteryController; + mPowerSaveEnabled = mBatteryController.isPowerSave(); } private final class SettingObserver extends ContentObserver { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java index e1821761ba7a..beec13740442 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java @@ -17,18 +17,15 @@ package com.android.systemui.pip.phone; import android.content.Context; -import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.view.Gravity; import android.view.LayoutInflater; -import android.view.TouchDelegate; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; import com.android.systemui.Interpolators; diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index 3df557d6227c..f59b2a4e25de 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -16,20 +16,16 @@ package com.android.systemui.pip.phone; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.view.Display.DEFAULT_DISPLAY; import android.app.ActivityManager; -import android.app.ActivityManager.StackInfo; -import android.app.ActivityOptions; import android.app.IActivityManager; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.content.pm.ParceledListSlice; +import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; -import android.os.UserHandle; import android.util.Log; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; @@ -94,7 +90,7 @@ public class PipManager { } } if (expandPipToFullscreen) { - mTouchHandler.expandPinnedStackToFullscreen(); + mTouchHandler.getMotionHelper().expandPip(); } else { Log.w(TAG, "Can not expand PiP to fullscreen via intent from the same package."); } @@ -114,28 +110,31 @@ public class PipManager { } @Override - public void onBoundsChanged(boolean adjustedForIme) { - // Do nothing + public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { + mHandler.post(() -> { + mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight); + }); } @Override - public void onActionsChanged(ParceledListSlice actions) { + public void onMinimizedStateChanged(boolean isMinimized) { mHandler.post(() -> { - mMenuController.setAppActions(actions); + mTouchHandler.setMinimizedState(isMinimized, true /* fromController */); }); } @Override - public void onMinimizedStateChanged(boolean isMinimized) { + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + boolean fromImeAdjustement) { mHandler.post(() -> { - mTouchHandler.onMinimizedStateChanged(isMinimized); + mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, fromImeAdjustement); }); } @Override - public void onSnapToEdgeStateChanged(boolean isSnapToEdge) { + public void onActionsChanged(ParceledListSlice actions) { mHandler.post(() -> { - mTouchHandler.onSnapToEdgeStateChanged(isSnapToEdge); + mMenuController.setAppActions(actions); }); } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java index d96baa6b3620..5a665a9770b7 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java @@ -16,16 +16,22 @@ package com.android.systemui.pip.phone; +import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; + import android.app.IActivityManager; +import android.app.PendingIntent; import android.app.RemoteAction; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.graphics.drawable.Icon; import android.media.session.MediaController; -import android.media.session.MediaController.TransportControls; import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; +import android.os.UserHandle; import com.android.systemui.R; @@ -40,6 +46,9 @@ import java.util.List; */ public class PipMediaController { + private static final String ACTION_PLAY = "com.android.systemui.pip.phone.PLAY"; + private static final String ACTION_PAUSE = "com.android.systemui.pip.phone.PAUSE"; + /** * A listener interface to receive notification on changes to the media actions. */ @@ -59,6 +68,18 @@ public class PipMediaController { private RemoteAction mPauseAction; private RemoteAction mPlayAction; + private BroadcastReceiver mPlayPauseActionReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(ACTION_PLAY)) { + mMediaController.getTransportControls().play(); + } else if (action.equals(ACTION_PAUSE)) { + mMediaController.getTransportControls().pause(); + } + } + }; + private MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() { @Override public void onPlaybackStateChanged(PlaybackState state) { @@ -73,6 +94,10 @@ public class PipMediaController { public PipMediaController(Context context, IActivityManager activityManager) { mContext = context; mActivityManager = activityManager; + IntentFilter mediaControlFilter = new IntentFilter(); + mediaControlFilter.addAction(ACTION_PLAY); + mediaControlFilter.addAction(ACTION_PAUSE); + mContext.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter); createMediaActions(); mMediaSessionManager = @@ -135,12 +160,14 @@ public class PipMediaController { String pauseDescription = mContext.getString(R.string.pip_pause); mPauseAction = new RemoteAction(Icon.createWithResource(mContext, R.drawable.ic_pause_white_24dp), pauseDescription, pauseDescription, - action -> mMediaController.getTransportControls().pause()); + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PAUSE), + FLAG_UPDATE_CURRENT)); String playDescription = mContext.getString(R.string.pip_play); mPlayAction = new RemoteAction(Icon.createWithResource(mContext, R.drawable.ic_play_arrow_white_24dp), playDescription, playDescription, - action -> mMediaController.getTransportControls().play()); + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PLAY), + FLAG_UPDATE_CURRENT)); } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index 438b8ddfc47a..90669772bcd1 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -22,6 +22,7 @@ import android.animation.ObjectAnimator; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; +import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; import android.content.Intent; import android.content.pm.ParceledListSlice; @@ -258,7 +259,11 @@ public class PipMenuActivity extends Activity { }, mHandler); actionView.setContentDescription(action.getContentDescription()); actionView.setOnClickListener(v -> { - action.sendActionInvoked(); + try { + action.getActionIntent().send(); + } catch (CanceledException e) { + Log.w(TAG, "Failed to send action", e); + } }); actionsGroup.addView(actionView); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java new file mode 100644 index 000000000000..fb3ed446212b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -0,0 +1,378 @@ +/* + * 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 com.android.systemui.pip.phone; + +import static android.app.ActivityManager.StackId.PINNED_STACK_ID; + +import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN; +import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN; +import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.RectEvaluator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.app.ActivityManager.StackInfo; +import android.app.IActivityManager; +import android.content.Context; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.Rect; +import android.os.Handler; +import android.os.RemoteException; +import android.util.Log; +import android.view.animation.Interpolator; + +import com.android.internal.os.BackgroundThread; +import com.android.internal.policy.PipSnapAlgorithm; +import com.android.systemui.recents.misc.SystemServicesProxy; +import com.android.systemui.statusbar.FlingAnimationUtils; + +/** + * A helper to animate and manipulate the PiP. + */ +public class PipMotionHelper { + + private static final String TAG = "PipMotionHelper"; + + private static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect()); + + private static final int DEFAULT_MOVE_STACK_DURATION = 225; + private static final int SNAP_STACK_DURATION = 225; + private static final int DISMISS_STACK_DURATION = 375; + private static final int SHRINK_STACK_FROM_MENU_DURATION = 175; + private static final int EXPAND_STACK_TO_MENU_DURATION = 175; + private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 225; + private static final int MINIMIZE_STACK_MAX_DURATION = 200; + + // The fraction of the stack width that the user has to drag offscreen to minimize the PiP + private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f; + + private Context mContext; + private IActivityManager mActivityManager; + private Handler mHandler; + + private PipSnapAlgorithm mSnapAlgorithm; + private FlingAnimationUtils mFlingAnimationUtils; + + private final Rect mBounds = new Rect(); + private final Rect mStableInsets = new Rect(); + + private ValueAnimator mBoundsAnimator = null; + private ValueAnimator.AnimatorUpdateListener mUpdateBoundsListener = + new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mBounds.set((Rect) animation.getAnimatedValue()); + } + }; + + public PipMotionHelper(Context context, IActivityManager activityManager, + PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils) { + mContext = context; + mHandler = BackgroundThread.getHandler(); + mActivityManager = activityManager; + mSnapAlgorithm = snapAlgorithm; + mFlingAnimationUtils = flingAnimationUtils; + onConfigurationChanged(); + } + + /** + * Updates whenever the configuration changes. + */ + void onConfigurationChanged() { + mSnapAlgorithm.onConfigurationChanged(); + SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets); + } + + /** + * Synchronizes the current bounds with the pinned stack. + */ + void synchronizePinnedStackBounds() { + cancelAnimations(); + try { + StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); + if (stackInfo != null) { + mBounds.set(stackInfo.bounds); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed to get pinned stack bounds"); + } + } + + /** + * Tries to the move the pinned stack to the given {@param bounds}. + */ + void movePip(Rect toBounds) { + cancelAnimations(); + resizePipUnchecked(toBounds); + mBounds.set(toBounds); + } + + /** + * Resizes the pinned stack back to fullscreen. + */ + void expandPip() { + cancelAnimations(); + mHandler.post(() -> { + try { + mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */, + true /* allowResizeInDockedMode */, true /* preserveWindows */, + true /* animate */, EXPAND_STACK_TO_FULLSCREEN_DURATION); + } catch (RemoteException e) { + Log.e(TAG, "Error showing PiP menu activity", e); + } + }); + } + + /** + * Dismisses the pinned stack. + */ + void dismissPip() { + cancelAnimations(); + mHandler.post(() -> { + try { + mActivityManager.removeStack(PINNED_STACK_ID); + } catch (RemoteException e) { + Log.e(TAG, "Failed to remove PiP", e); + } + }); + } + + /** + * @return the PiP bounds. + */ + Rect getBounds() { + return mBounds; + } + + /** + * @return the closest minimized PiP bounds. + */ + Rect getClosestMinimizedBounds(Rect stackBounds, Rect movementBounds) { + Point displaySize = new Point(); + mContext.getDisplay().getRealSize(displaySize); + Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, stackBounds); + mSnapAlgorithm.applyMinimizedOffset(toBounds, movementBounds, displaySize, mStableInsets); + return toBounds; + } + + /** + * @return whether the PiP at the current bounds should be minimized. + */ + boolean shouldMinimizePip() { + Point displaySize = new Point(); + mContext.getDisplay().getRealSize(displaySize); + if (mBounds.left < 0) { + float offscreenFraction = (float) -mBounds.left / mBounds.width(); + return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION; + } else if (mBounds.right > displaySize.x) { + float offscreenFraction = (float) (mBounds.right - displaySize.x) / + mBounds.width(); + return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION; + } else { + return false; + } + } + + /** + * Flings the minimized PiP to the closest minimized snap target. + */ + Rect flingToMinimizedState(float velocityY, Rect movementBounds) { + cancelAnimations(); + // We currently only allow flinging the minimized stack up and down, so just lock the + // movement bounds to the current stack bounds horizontally + movementBounds = new Rect(mBounds.left, movementBounds.top, mBounds.left, + movementBounds.bottom); + Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds, + 0 /* velocityX */, velocityY); + if (!mBounds.equals(toBounds)) { + mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN, + mUpdateBoundsListener); + mFlingAnimationUtils.apply(mBoundsAnimator, 0, + distanceBetweenRectOffsets(mBounds, toBounds), + velocityY); + mBoundsAnimator.start(); + } + return toBounds; + } + + /** + * Animates the PiP to the minimized state, slightly offscreen. + */ + Rect animateToClosestMinimizedState(Rect movementBounds, + final PipMenuActivityController menuController) { + cancelAnimations(); + Rect toBounds = getClosestMinimizedBounds(mBounds, movementBounds); + if (!mBounds.equals(toBounds)) { + mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, + MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdateBoundsListener); + mBoundsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + menuController.hideMenu(); + } + }); + mBoundsAnimator.start(); + } + return toBounds; + } + + /** + * Flings the PiP to the closest snap target. + */ + Rect flingToSnapTarget(float velocity, float velocityX, float velocityY, Rect movementBounds) { + cancelAnimations(); + Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds, + velocityX, velocityY); + if (!mBounds.equals(toBounds)) { + mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN, + mUpdateBoundsListener); + mFlingAnimationUtils.apply(mBoundsAnimator, 0, + distanceBetweenRectOffsets(mBounds, toBounds), + velocity); + mBoundsAnimator.start(); + } + return toBounds; + } + + /** + * Animates the PiP to the closest snap target. + */ + Rect animateToClosestSnapTarget(Rect movementBounds) { + cancelAnimations(); + Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds); + if (!mBounds.equals(toBounds)) { + mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, SNAP_STACK_DURATION, + FAST_OUT_SLOW_IN, mUpdateBoundsListener); + mBoundsAnimator.start(); + } + return toBounds; + } + + /** + * Animates the PiP to the expanded state to show the menu. + */ + float animateToExpandedState(Rect expandedBounds, Rect movementBounds, + Rect expandedMovementBounds) { + float savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds), movementBounds); + mSnapAlgorithm.applySnapFraction(expandedBounds, expandedMovementBounds, savedSnapFraction); + mBoundsAnimator = createAnimationToBounds(mBounds, expandedBounds, + EXPAND_STACK_TO_MENU_DURATION, FAST_OUT_SLOW_IN, mUpdateBoundsListener); + mBoundsAnimator.start(); + return savedSnapFraction; + } + + /** + * Animates the PiP from the expanded state to the normal state after the menu is hidden. + */ + void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction, + Rect normalMovementBounds) { + if (savedSnapFraction >= 0f) { + mSnapAlgorithm.applySnapFraction(normalBounds, normalMovementBounds, savedSnapFraction); + mBoundsAnimator = createAnimationToBounds(mBounds, normalBounds, + SHRINK_STACK_FROM_MENU_DURATION, FAST_OUT_SLOW_IN, mUpdateBoundsListener); + mBoundsAnimator.start(); + } else { + animateToClosestSnapTarget(normalMovementBounds); + } + } + + /** + * Animates the dismissal of the PiP over the dismiss target bounds. + */ + Rect animateDismissFromDrag(Rect dismissBounds) { + cancelAnimations(); + Rect toBounds = new Rect(dismissBounds.centerX(), + dismissBounds.centerY(), + dismissBounds.centerX() + 1, + dismissBounds.centerY() + 1); + mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, DISMISS_STACK_DURATION, + FAST_OUT_LINEAR_IN, mUpdateBoundsListener); + mBoundsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + dismissPip(); + } + }); + mBoundsAnimator.start(); + return toBounds; + } + + /** + * Animates the PiP to some given bounds. + */ + void animateToBounds(Rect toBounds) { + cancelAnimations(); + if (!mBounds.equals(toBounds)) { + mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, + DEFAULT_MOVE_STACK_DURATION, FAST_OUT_LINEAR_IN, mUpdateBoundsListener); + mBoundsAnimator.start(); + } + } + + /** + * Cancels all existing animations. + */ + void cancelAnimations() { + if (mBoundsAnimator != null) { + mBoundsAnimator.cancel(); + mBoundsAnimator = null; + } + } + + /** + * Creates an animation to move the PiP to give given {@param toBounds}. + */ + private ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds, int duration, + Interpolator interpolator, ValueAnimator.AnimatorUpdateListener updateListener) { + ValueAnimator anim = ValueAnimator.ofObject(RECT_EVALUATOR, fromBounds, toBounds); + anim.setDuration(duration); + anim.setInterpolator(interpolator); + anim.addUpdateListener((ValueAnimator animation) -> { + resizePipUnchecked((Rect) animation.getAnimatedValue()); + }); + if (updateListener != null) { + anim.addUpdateListener(updateListener); + } + return anim; + } + + /** + * Directly resizes the PiP to the given {@param bounds}. + */ + private void resizePipUnchecked(Rect toBounds) { + if (!toBounds.equals(mBounds)) { + mHandler.post(() -> { + try { + mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */); + mBounds.set(toBounds); + } catch (RemoteException e) { + Log.e(TAG, "Could not move pinned stack to bounds: " + toBounds, e); + } + }); + } + } + + /** + * @return the distance between points {@param p1} and {@param p2}. + */ + private float distanceBetweenRectOffsets(Rect r1, Rect r2) { + return PointF.length(r1.left - r2.left, r1.top - r2.top); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 10393c65f492..b3adee0344bb 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -16,21 +16,10 @@ package com.android.systemui.pip.phone; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.view.WindowManager.INPUT_CONSUMER_PIP; -import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN; -import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN; -import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.app.ActivityManager.StackInfo; import android.app.IActivityManager; import android.content.Context; -import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.os.Handler; @@ -47,8 +36,6 @@ import android.view.ViewConfiguration; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.os.BackgroundThread; -import com.android.internal.policy.PipMotionHelper; import com.android.internal.policy.PipSnapAlgorithm; import com.android.systemui.Dependency; import com.android.systemui.statusbar.FlingAnimationUtils; @@ -60,24 +47,15 @@ import com.android.systemui.tuner.TunerService; */ public class PipTouchHandler implements TunerService.Tunable { private static final String TAG = "PipTouchHandler"; - private static final boolean DEBUG_ALLOW_OUT_OF_BOUNDS_STACK = false; // These values are used for metrics and should never change private static final int METRIC_VALUE_DISMISSED_BY_TAP = 0; private static final int METRIC_VALUE_DISMISSED_BY_DRAG = 1; private static final String TUNER_KEY_DRAG_TO_DISMISS = "pip_drag_to_dismiss"; - private static final String TUNER_KEY_ALLOW_MINIMIZE = "pip_allow_minimize"; - private static final int SNAP_STACK_DURATION = 225; - private static final int DISMISS_STACK_DURATION = 375; - private static final int EXPAND_STACK_DURATION = 225; - private static final int MINIMIZE_STACK_MAX_DURATION = 200; private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200; - // The fraction of the stack width that the user has to drag offscreen to minimize the PIP - private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f; - private final Context mContext; private final IActivityManager mActivityManager; private final IWindowManager mWindowManager; @@ -86,34 +64,28 @@ public class PipTouchHandler implements TunerService.Tunable { private IPinnedStackController mPinnedStackController; private PipInputEventReceiver mInputEventReceiver; - private PipMenuActivityController mMenuController; - private PipDismissViewController mDismissViewController; + private final PipMenuActivityController mMenuController; + private final PipDismissViewController mDismissViewController; private final PipSnapAlgorithm mSnapAlgorithm; - private PipMotionHelper mMotionHelper; // Allow dragging the PIP to a location to close it private boolean mEnableDragToDismiss = false; - // Allow the PIP to be "docked" slightly offscreen - private boolean mEnableMinimizing = true; - - private final Rect mStableInsets = new Rect(); - private final Rect mPinnedStackBounds = new Rect(); - private final Rect mBoundedPinnedStackBounds = new Rect(); - private ValueAnimator mPinnedStackBoundsAnimator = null; - private ValueAnimator.AnimatorUpdateListener mUpdatePinnedStackBoundsListener = - new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mPinnedStackBounds.set((Rect) animation.getAnimatedValue()); - } - }; + + // The current movement bounds + private Rect mMovementBounds = new Rect(); + + // The reference bounds used to calculate the normal/expanded target bounds + private Rect mNormalBounds = new Rect(); + private Rect mNormalMovementBounds = new Rect(); + private Rect mExpandedBounds = new Rect(); + private Rect mExpandedMovementBounds = new Rect(); private Handler mHandler = new Handler(); private Runnable mShowDismissAffordance = new Runnable() { @Override public void run() { if (mEnableDragToDismiss) { - mDismissViewController.showDismissTarget(mPinnedStackBounds); + mDismissViewController.showDismissTarget(mMotionHelper.getBounds()); } } }; @@ -121,13 +93,18 @@ public class PipTouchHandler implements TunerService.Tunable { // Behaviour states private boolean mIsTappingThrough; private boolean mIsMinimized; + private boolean mIsMenuVisible; + private boolean mIsImeShowing; + private int mImeHeight; + private float mSavedSnapFraction = -1f; // Touch state private final PipTouchState mTouchState; private final FlingAnimationUtils mFlingAnimationUtils; private final PipTouchGesture[] mGestures; + private final PipMotionHelper mMotionHelper; - // Temporary vars + // Temp vars private final Rect mTmpBounds = new Rect(); /** @@ -160,32 +137,25 @@ public class PipTouchHandler implements TunerService.Tunable { private class PipMenuListener implements PipMenuActivityController.Listener { @Override public void onPipMenuVisibilityChanged(boolean visible) { - if (!visible) { - mIsTappingThrough = false; - registerInputConsumer(); - } else { - unregisterInputConsumer(); - } - MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU, - visible); + setMenuVisibilityState(visible); } @Override public void onPipExpand() { if (!mIsMinimized) { - expandPinnedStackToFullscreen(); + mMotionHelper.expandPip(); } } @Override public void onPipMinimize() { - setMinimizedState(true); - animateToClosestMinimizedTarget(); + setMinimizedStateInternal(true); + mMotionHelper.animateToClosestMinimizedState(mMovementBounds, mMenuController); } @Override public void onPipDismiss() { - BackgroundThread.getHandler().post(PipTouchHandler.this::dismissPinnedStack); + mMotionHelper.dismissPip(); MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED, METRIC_VALUE_DISMISSED_BY_TAP); } @@ -208,13 +178,12 @@ public class PipTouchHandler implements TunerService.Tunable { mGestures = new PipTouchGesture[] { mDefaultMovementGesture }; - mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler()); + mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mSnapAlgorithm, + mFlingAnimationUtils); registerInputConsumer(); - setSnapToEdge(true); // Register any tuner settings changes - Dependency.get(TunerService.class).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS, - TUNER_KEY_ALLOW_MINIMIZE); + Dependency.get(TunerService.class).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS); } @Override @@ -222,17 +191,12 @@ public class PipTouchHandler implements TunerService.Tunable { if (newValue == null) { // Reset back to default mEnableDragToDismiss = false; - mEnableMinimizing = true; - setMinimizedState(false); return; } switch (key) { case TUNER_KEY_DRAG_TO_DISMISS: mEnableDragToDismiss = Integer.parseInt(newValue) != 0; break; - case TUNER_KEY_ALLOW_MINIMIZE: - mEnableMinimizing = Integer.parseInt(newValue) != 0; - break; } } @@ -243,26 +207,70 @@ public class PipTouchHandler implements TunerService.Tunable { registerInputConsumer(); } if (mIsMinimized) { - setMinimizedState(false); + setMinimizedStateInternal(false); } } public void onConfigurationChanged() { - mSnapAlgorithm.onConfigurationChanged(); - updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */); + mMotionHelper.onConfigurationChanged(); + mMotionHelper.synchronizePinnedStackBounds(); } - public void onMinimizedStateChanged(boolean isMinimized) { - if (mIsMinimized != isMinimized) { - MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MINIMIZED, - isMinimized); - } - mIsMinimized = isMinimized; - mSnapAlgorithm.setMinimized(isMinimized); + public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { + mIsImeShowing = imeVisible; + mImeHeight = imeHeight; } - public void onSnapToEdgeStateChanged(boolean isSnapToEdge) { - mSnapAlgorithm.setSnapToEdge(isSnapToEdge); + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + boolean fromImeAdjustement) { + // Re-calculate the expanded bounds + mNormalBounds = normalBounds; + Rect normalMovementBounds = new Rect(); + mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds, + mIsImeShowing ? mImeHeight : 0); + // TODO: Figure out the expanded size policy + mExpandedBounds = new Rect(normalBounds); + Rect expandedMovementBounds = new Rect(); + mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds, + mIsImeShowing ? mImeHeight : 0); + + + // If this is from an IME adjustment, then we should move the PiP so that it is not occluded + // by the IME + if (fromImeAdjustement) { + if (mTouchState.isUserInteracting()) { + // Defer the update of the current movement bounds until after the user finishes + // touching the screen + } else { + final Rect bounds = new Rect(mMotionHelper.getBounds()); + final Rect toMovementBounds = mIsMenuVisible + ? expandedMovementBounds + : normalMovementBounds; + if (mIsImeShowing) { + // IME visible + if (bounds.top == mMovementBounds.bottom) { + // If the PIP is currently resting on top of the IME, then adjust it with + // the hiding IME + bounds.offsetTo(bounds.left, toMovementBounds.bottom); + } else { + bounds.offset(0, Math.min(0, toMovementBounds.bottom - bounds.top)); + } + } else { + // IME hidden + if (bounds.top == mMovementBounds.bottom) { + // If the PIP is resting on top of the IME, then adjust it with the hiding IME + bounds.offsetTo(bounds.left, toMovementBounds.bottom); + } + } + mMotionHelper.animateToBounds(bounds); + } + } + + // Update the movement bounds after doing the calculations based on the old movement bounds + // above + mNormalMovementBounds = normalMovementBounds; + mExpandedMovementBounds = expandedMovementBounds; + updateMovementBounds(); } private boolean handleTouchEvent(MotionEvent ev) { @@ -276,20 +284,11 @@ public class PipTouchHandler implements TunerService.Tunable { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: { - // Cancel any existing animations on the pinned stack - if (mPinnedStackBoundsAnimator != null) { - mPinnedStackBoundsAnimator.cancel(); - } + mMotionHelper.synchronizePinnedStackBounds(); - updateBoundedPinnedStackBounds(true /* updatePinnedStackBounds */); for (PipTouchGesture gesture : mGestures) { gesture.onDown(mTouchState); } - try { - mPinnedStackController.setInInteractiveMode(true); - } catch (RemoteException e) { - Log.e(TAG, "Could not set dragging state", e); - } break; } case MotionEvent.ACTION_MOVE: { @@ -303,7 +302,7 @@ public class PipTouchHandler implements TunerService.Tunable { case MotionEvent.ACTION_UP: { // Update the movement bounds again if the state has changed since the user started // dragging (ie. when the IME shows) - updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */); + updateMovementBounds(); for (PipTouchGesture gesture : mGestures) { if (gesture.onUp(mTouchState)) { @@ -314,11 +313,6 @@ public class PipTouchHandler implements TunerService.Tunable { // Fall through to clean up } case MotionEvent.ACTION_CANCEL: { - try { - mPinnedStackController.setInInteractiveMode(false); - } catch (RemoteException e) { - Log.e(TAG, "Could not set dragging state", e); - } break; } } @@ -326,16 +320,6 @@ public class PipTouchHandler implements TunerService.Tunable { } /** - * @return whether the current touch state places the pip partially offscreen. - */ - private boolean isDraggingOffscreen(PipTouchState touchState) { - PointF lastDelta = touchState.getLastTouchDelta(); - PointF downDelta = touchState.getDownTouchDelta(); - float left = mPinnedStackBounds.left + lastDelta.x; - return !(mBoundedPinnedStackBounds.left <= left && left <= mBoundedPinnedStackBounds.right); - } - - /** * Registers the input consumer. */ private void registerInputConsumer() { @@ -374,27 +358,30 @@ public class PipTouchHandler implements TunerService.Tunable { } /** - * Sets the snap-to-edge state and notifies the controller. + * Sets the minimized state. */ - private void setSnapToEdge(boolean snapToEdge) { - onSnapToEdgeStateChanged(snapToEdge); - - if (mPinnedStackController != null) { - try { - mPinnedStackController.setSnapToEdge(snapToEdge); - } catch (RemoteException e) { - Log.e(TAG, "Could not set snap mode to edge", e); - } - } + void setMinimizedStateInternal(boolean isMinimized) { + setMinimizedState(isMinimized, false /* fromController */); } /** - * Sets the minimized state and notifies the controller. + * Sets the minimized state. */ - private void setMinimizedState(boolean isMinimized) { - onMinimizedStateChanged(isMinimized); + void setMinimizedState(boolean isMinimized, boolean fromController) { + if (mIsMinimized != isMinimized) { + MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MINIMIZED, + isMinimized); + } + mIsMinimized = isMinimized; + mSnapAlgorithm.setMinimized(isMinimized); - if (mPinnedStackController != null) { + if (fromController) { + if (isMinimized) { + // Move the PiP to the new bounds immediately if minimized + mMotionHelper.movePip(mMotionHelper.getClosestMinimizedBounds(mNormalBounds, + mMovementBounds)); + } + } else if (mPinnedStackController != null) { try { mPinnedStackController.setIsMinimized(isMinimized); } catch (RemoteException e) { @@ -404,178 +391,43 @@ public class PipTouchHandler implements TunerService.Tunable { } /** - * @return whether the given {@param pinnedStackBounds} indicates the PIP should be minimized. + * Sets the menu visibility. */ - private boolean shouldMinimizedPinnedStack() { - Point displaySize = new Point(); - mContext.getDisplay().getRealSize(displaySize); - if (mPinnedStackBounds.left < 0) { - float offscreenFraction = (float) -mPinnedStackBounds.left / mPinnedStackBounds.width(); - return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION; - } else if (mPinnedStackBounds.right > displaySize.x) { - float offscreenFraction = (float) (mPinnedStackBounds.right - displaySize.x) / - mPinnedStackBounds.width(); - return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION; + void setMenuVisibilityState(boolean isMenuVisible) { + if (!isMenuVisible) { + mIsTappingThrough = false; + registerInputConsumer(); } else { - return false; + unregisterInputConsumer(); } - } - - /** - * Flings the minimized PIP to the closest minimized snap target. - */ - private void flingToMinimizedSnapTarget(float velocityY) { - // We currently only allow flinging the minimized stack up and down, so just lock the - // movement bounds to the current stack bounds horizontally - Rect movementBounds = new Rect(mPinnedStackBounds.left, mBoundedPinnedStackBounds.top, - mPinnedStackBounds.left, mBoundedPinnedStackBounds.bottom); - Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mPinnedStackBounds, - 0 /* velocityX */, velocityY); - if (!mPinnedStackBounds.equals(toBounds)) { - mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, - toBounds, 0, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener); - mFlingAnimationUtils.apply(mPinnedStackBoundsAnimator, 0, - distanceBetweenRectOffsets(mPinnedStackBounds, toBounds), - velocityY); - mPinnedStackBoundsAnimator.start(); - } - } - - /** - * Animates the PIP to the minimized state, slightly offscreen. - */ - private void animateToClosestMinimizedTarget() { - Point displaySize = new Point(); - mContext.getDisplay().getRealSize(displaySize); - Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, - mPinnedStackBounds); - mSnapAlgorithm.applyMinimizedOffset(toBounds, mBoundedPinnedStackBounds, displaySize, - mStableInsets); - mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, - toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, - mUpdatePinnedStackBoundsListener); - mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - mMenuController.hideMenu(); - } - }); - mPinnedStackBoundsAnimator.start(); - } - - /** - * Flings the PIP to the closest snap target. - */ - private Rect flingToSnapTarget(float velocity, float velocityX, float velocityY) { - Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, - mPinnedStackBounds, velocityX, velocityY); - if (!mPinnedStackBounds.equals(toBounds)) { - mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, - toBounds, 0, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener); - mFlingAnimationUtils.apply(mPinnedStackBoundsAnimator, 0, - distanceBetweenRectOffsets(mPinnedStackBounds, toBounds), - velocity); - mPinnedStackBoundsAnimator.start(); - } - return toBounds; - } - - /** - * Animates the PIP to the closest snap target. - */ - private Rect animateToClosestSnapTarget() { - Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds, - mPinnedStackBounds); - if (!mPinnedStackBounds.equals(toBounds)) { - mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, - toBounds, SNAP_STACK_DURATION, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener); - mPinnedStackBoundsAnimator.start(); - } - return toBounds; - } - - /** - * Animates the dismissal of the PIP over the dismiss target bounds. - */ - private void animateDismissPinnedStack(Rect dismissBounds) { - Rect toBounds = new Rect(dismissBounds.centerX(), - dismissBounds.centerY(), - dismissBounds.centerX() + 1, - dismissBounds.centerY() + 1); - mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds, - toBounds, DISMISS_STACK_DURATION, FAST_OUT_LINEAR_IN, mUpdatePinnedStackBoundsListener); - mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - BackgroundThread.getHandler().post(PipTouchHandler.this::dismissPinnedStack); - } - }); - mPinnedStackBoundsAnimator.start(); - } - - /** - * Resizes the pinned stack back to fullscreen. - */ - void expandPinnedStackToFullscreen() { - BackgroundThread.getHandler().post(() -> { - try { - mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */, - true /* allowResizeInDockedMode */, true /* preserveWindows */, - true /* animate */, EXPAND_STACK_DURATION); - } catch (RemoteException e) { - Log.e(TAG, "Error showing PIP menu activity", e); - } - }); - } - - /** - * Tries to the move the pinned stack to the given {@param bounds}. - */ - private void movePinnedStack(Rect bounds) { - if (!bounds.equals(mPinnedStackBounds)) { - mPinnedStackBounds.set(bounds); - if (mEnableDragToDismiss) { - mDismissViewController.updateDismissTarget(bounds); - } - mMotionHelper.resizeToBounds(mPinnedStackBounds); - } - } - - /** - * Dismisses the pinned stack. - */ - private void dismissPinnedStack() { - try { - mActivityManager.removeStack(PINNED_STACK_ID); - } catch (RemoteException e) { - Log.e(TAG, "Failed to remove PIP", e); - } - } - - /** - * Updates the movement bounds of the pinned stack. - */ - private void updateBoundedPinnedStackBounds(boolean updatePinnedStackBounds) { - try { - StackInfo info = mActivityManager.getStackInfo(PINNED_STACK_ID); - if (info != null) { - if (updatePinnedStackBounds) { - mPinnedStackBounds.set(info.bounds); - } - mWindowManager.getStableInsets(info.displayId, mStableInsets); - mBoundedPinnedStackBounds.set(mWindowManager.getPictureInPictureMovementBounds( - info.displayId)); + MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU, + isMenuVisible); + + if (isMenuVisible != mIsMenuVisible) { + if (isMenuVisible) { + // Save the current snap fraction and if we do not drag or move the PiP, then + // we store back to this snap fraction. Otherwise, we'll reset the snap + // fraction and snap to the closest edge + Rect expandedBounds = new Rect(mExpandedBounds); + mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds, + mMovementBounds, mExpandedMovementBounds); + } else { + // Try and restore the PiP to the closest edge, using the saved snap fraction + // if possible + Rect normalBounds = new Rect(mNormalBounds); + mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction, + mNormalMovementBounds); } - } catch (RemoteException e) { - Log.e(TAG, "Could not fetch PIP movement bounds.", e); + mIsMenuVisible = isMenuVisible; + updateMovementBounds(); } } /** - * @return the distance between points {@param p1} and {@param p2}. + * @return the motion helper. */ - private float distanceBetweenRectOffsets(Rect r1, Rect r2) { - return PointF.length(r1.left - r2.left, r1.top - r2.top); + public PipMotionHelper getMotionHelper() { + return mMotionHelper; } /** @@ -593,25 +445,31 @@ public class PipTouchHandler implements TunerService.Tunable { @Override boolean onMove(PipTouchState touchState) { + if (touchState.startedDragging()) { + mSavedSnapFraction = -1f; + } + if (touchState.startedDragging() && mEnableDragToDismiss) { mHandler.removeCallbacks(mShowDismissAffordance); - mDismissViewController.showDismissTarget(mPinnedStackBounds); + mDismissViewController.showDismissTarget(mMotionHelper.getBounds()); } if (touchState.isDragging()) { // Move the pinned stack freely - PointF lastDelta = touchState.getLastTouchDelta(); - float left = mPinnedStackBounds.left + lastDelta.x; - float top = mPinnedStackBounds.top + lastDelta.y; + mTmpBounds.set(mMotionHelper.getBounds()); + final PointF lastDelta = touchState.getLastTouchDelta(); + float left = mTmpBounds.left + lastDelta.x; + float top = mTmpBounds.top + lastDelta.y; if (!touchState.allowDraggingOffscreen()) { - left = Math.max(mBoundedPinnedStackBounds.left, Math.min( - mBoundedPinnedStackBounds.right, left)); + left = Math.max(mMovementBounds.left, Math.min(mMovementBounds.right, left)); } - top = Math.max(mBoundedPinnedStackBounds.top, Math.min( - mBoundedPinnedStackBounds.bottom, top)); - mTmpBounds.set(mPinnedStackBounds); + top = Math.max(mMovementBounds.top, Math.min(mMovementBounds.bottom, top)); mTmpBounds.offsetTo((int) left, (int) top); - movePinnedStack(mTmpBounds); + mMotionHelper.movePip(mTmpBounds); + + if (mEnableDragToDismiss) { + mDismissViewController.updateDismissTarget(mTmpBounds); + } return true; } return false; @@ -626,9 +484,12 @@ public class PipTouchHandler implements TunerService.Tunable { final float velocity = PointF.length(vel.x, vel.y); if (touchState.isDragging() && velocity < mFlingAnimationUtils.getMinVelocityPxPerSecond()) { - if (mDismissViewController.shouldDismiss(mPinnedStackBounds)) { + if (mDismissViewController.shouldDismiss(mMotionHelper.getBounds())) { Rect dismissBounds = mDismissViewController.getDismissBounds(); - animateDismissPinnedStack(dismissBounds); + mMotionHelper.animateDismissFromDrag(dismissBounds); + MetricsLogger.action(mContext, + MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED, + METRIC_VALUE_DISMISSED_BY_DRAG); return true; } } @@ -638,34 +499,34 @@ public class PipTouchHandler implements TunerService.Tunable { } if (touchState.isDragging()) { PointF vel = mTouchState.getVelocity(); - if (!mIsMinimized && (shouldMinimizedPinnedStack() + if (!mIsMinimized && (mMotionHelper.shouldMinimizePip() || isHorizontalFlingTowardsCurrentEdge(vel))) { // Pip should be minimized - setMinimizedState(true); - animateToClosestMinimizedTarget(); + setMinimizedStateInternal(true); + mMotionHelper.animateToClosestMinimizedState(mMovementBounds, mMenuController); return true; } if (mIsMinimized) { // If we're dragging and it wasn't a minimize gesture // then we shouldn't be minimized. - setMinimizedState(false); + setMinimizedStateInternal(false); } final float velocity = PointF.length(vel.x, vel.y); if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) { - flingToSnapTarget(velocity, vel.x, vel.y); + mMotionHelper.flingToSnapTarget(velocity, vel.x, vel.y, mMovementBounds); } else { - animateToClosestSnapTarget(); + mMotionHelper.animateToClosestSnapTarget(mMovementBounds); } } else if (mIsMinimized) { // This was a tap, so no longer minimized - animateToClosestSnapTarget(); - setMinimizedState(false); + mMotionHelper.animateToClosestSnapTarget(mMovementBounds); + setMinimizedStateInternal(false); } else if (!mIsTappingThrough) { mMenuController.showMenu(); mIsTappingThrough = true; } else { - expandPinnedStackToFullscreen(); + mMotionHelper.expandPip(); } return true; } @@ -679,17 +540,30 @@ public class PipTouchHandler implements TunerService.Tunable { final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y); final boolean isFling = PointF.length(vel.x, vel.y) > mFlingAnimationUtils .getMinVelocityPxPerSecond(); - final boolean towardsCurrentEdge = onEdge(true /* left */) && vel.x < 0 - || onEdge(false /* right */) && vel.x > 0; + final boolean towardsCurrentEdge = isOverEdge(true /* left */) && vel.x < 0 + || isOverEdge(false /* right */) && vel.x > 0; return towardsCurrentEdge && isHorizontal && isFling; } - private boolean onEdge(boolean checkLeft) { + /** + * @return whether the given bounds are on the left or right edge (depending on + * {@param checkLeft}) + */ + private boolean isOverEdge(boolean checkLeft) { + final Rect bounds = mMotionHelper.getBounds(); if (checkLeft) { - return mPinnedStackBounds.left <= mBoundedPinnedStackBounds.left; + return bounds.left <= mMovementBounds.left; } else { - return mPinnedStackBounds.right >= mBoundedPinnedStackBounds.right - + mPinnedStackBounds.width(); + return bounds.right >= mMovementBounds.right + bounds.width(); } } + + /** + * Updates the current movement bounds based on whether the menu is currently visible. + */ + private void updateMovementBounds() { + mMovementBounds = mIsMenuVisible + ? mExpandedMovementBounds + : mNormalMovementBounds; + } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java index 2e84ceda8ae0..868b34b773d0 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java @@ -34,6 +34,7 @@ public class PipTouchState { private final PointF mLastTouch = new PointF(); private final PointF mLastDelta = new PointF(); private final PointF mVelocity = new PointF(); + private boolean mIsUserInteracting = false; private boolean mIsDragging = false; private boolean mStartedDragging = false; private boolean mAllowDraggingOffscreen = false; @@ -57,6 +58,7 @@ public class PipTouchState { mIsDragging = false; mStartedDragging = false; mAllowDraggingOffscreen = true; + mIsUserInteracting = true; break; } case MotionEvent.ACTION_MOVE: { @@ -107,6 +109,7 @@ public class PipTouchState { // Fall through to clean up } case MotionEvent.ACTION_CANCEL: { + mIsUserInteracting = false; recycleVelocityTracker(); break; } @@ -151,6 +154,13 @@ public class PipTouchState { } /** + * @return whether the user is currently interacting with the PiP. + */ + public boolean isUserInteracting() { + return mIsUserInteracting; + } + + /** * @return whether the user has started dragging just in the last handled touch event. */ public boolean startedDragging() { diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index 964fefa1411c..e3db16a069c5 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -25,6 +25,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ParceledListSlice; import android.content.res.Resources; import android.graphics.Rect; import android.media.session.MediaController; @@ -39,6 +40,8 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.Display; +import android.view.IPinnedStackController; +import android.view.IPinnedStackListener; import android.view.IWindowManager; import android.view.WindowManagerGlobal; @@ -51,6 +54,8 @@ import java.util.ArrayList; import java.util.List; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.view.Display.DEFAULT_DISPLAY; + import static com.android.systemui.Prefs.Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN; /** @@ -146,7 +151,7 @@ public class PipManager { private List<MediaListener> mMediaListeners = new ArrayList<>(); private Rect mCurrentPipBounds; private Rect mPipBounds; - private Rect mDefaultPipBounds; + private Rect mDefaultPipBounds = new Rect(); private Rect mSettingsPipBounds; private Rect mMenuModePipBounds; private Rect mRecentsPipBounds; @@ -159,6 +164,8 @@ public class PipManager { private boolean mOnboardingShown; private String[] mLastPackagesResourceGranted; + private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); + private final Runnable mResizePinnedStackRunnable = new Runnable() { @Override public void run() { @@ -196,6 +203,32 @@ public class PipManager { } }; + /** + * Handler for messages from the PIP controller. + */ + private class PinnedStackListener extends IPinnedStackListener.Stub { + + @Override + public void onListenerRegistered(IPinnedStackController controller) {} + + @Override + public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} + + @Override + public void onMinimizedStateChanged(boolean isMinimized) {} + + @Override + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + boolean fromImeAdjustement) { + mHandler.post(() -> { + mDefaultPipBounds.set(normalBounds); + }); + } + + @Override + public void onActionsChanged(ParceledListSlice actions) {} + } + private PipManager() { } /** @@ -221,16 +254,16 @@ public class PipManager { mPipRecentsOverlayManager = new PipRecentsOverlayManager(context); mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); - } - private void loadConfigurationsAndApply() { - Resources res = mContext.getResources(); try { - mDefaultPipBounds = mWindowManager.getPictureInPictureDefaultBounds( - Display.DEFAULT_DISPLAY); + mWindowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener); } catch (RemoteException e) { - Log.e(TAG, "Failed to get default PIP bounds", e); + Log.e(TAG, "Failed to register pinned stack listener", e); } + } + + private void loadConfigurationsAndApply() { + Resources res = mContext.getResources(); mSettingsPipBounds = Rect.unflattenFromString(res.getString( R.string.pip_settings_bounds)); mMenuModePipBounds = Rect.unflattenFromString(res.getString( diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java index a5a1eaaf6662..3b9e7bcfb9b4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java @@ -99,8 +99,9 @@ public class TileLayout extends ViewGroup implements QSTileLayout { record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight)); previousView = record.tileView.updateAccessibilityOrder(previousView); } - setMeasuredDimension(width, - (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin)); + int height = (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin); + if (height < 0) height = 0; + setMeasuredDimension(width, height); } private static int exactly(int size) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 70f81096bb79..dab5967e5e91 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -16,6 +16,9 @@ package com.android.systemui.qs.tiles; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.UserManager; @@ -37,6 +40,9 @@ import com.android.systemui.statusbar.policy.HotspotController; /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> { + static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName( + "com.android.settings", "com.android.settings.TetherSettings")); + private final AnimationIcon mEnable = new AnimationIcon(R.drawable.ic_hotspot_enable_animation, R.drawable.ic_hotspot_disable); @@ -94,7 +100,7 @@ public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> { @Override public Intent getLongClickIntent() { - return new Intent(Settings.ACTION_WIRELESS_SETTINGS); + return new Intent(TETHER_SETTINGS); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 809119922756..55491b24e20d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -656,6 +656,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener synchronized (mHeaderBarLock) { if (mHeaderBar.getMeasuredWidth() != taskViewWidth || mHeaderBar.getMeasuredHeight() != mTaskBarHeight) { + if (mDummyStackView.useGridLayout()) { + mHeaderBar.setShouldDarkenBackgroundColor(true); + mHeaderBar.setNoUserInteractionState(); + } mHeaderBar.forceLayout(); mHeaderBar.measure( MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY), diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 45e766c0dd16..9a52a7b7d5c1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -151,7 +151,7 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @ViewDebug.ExportedProperty(deepExport=true, prefix="thumbnail_") protected TaskViewThumbnail mThumbnailView; @ViewDebug.ExportedProperty(deepExport=true, prefix="header_") - TaskViewHeader mHeaderView; + protected TaskViewHeader mHeaderView; private View mActionButtonView; private View mIncompatibleAppToastView; private TaskViewCallbacks mCb; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 0777163293d9..dc666e90fbdb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -91,6 +91,9 @@ public class TaskViewHeader extends FrameLayout if (mColor != color || Float.compare(mDimAlpha, dimAlpha) != 0) { mColor = color; mDimAlpha = dimAlpha; + if (mShouldDarkenBackgroundColor) { + color = getSecondaryColor(color, false /* useLightOverlayColor */); + } mBackgroundPaint.setColor(color); ColorUtils.colorToHSL(color, mTmpHSL); @@ -179,6 +182,10 @@ public class TaskViewHeader extends FrameLayout // Header dim, which is only used when task view hardware layers are not used private Paint mDimLayerPaint = new Paint(); + // Whether the background color should be darkened to differentiate from the primary color. + // Used in grid layout. + private boolean mShouldDarkenBackgroundColor = false; + private CountDownTimer mFocusTimerCountDown; public TaskViewHeader(Context context) { @@ -443,6 +450,13 @@ public class TaskViewHeader extends FrameLayout } /** + * Sets whether the background color should be darkened to differentiate from the primary color. + */ + public void setShouldDarkenBackgroundColor(boolean flag) { + mShouldDarkenBackgroundColor = flag; + } + + /** * Binds the bar view to the task. */ public void bindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) { @@ -557,7 +571,7 @@ public class TaskViewHeader extends FrameLayout * Mark this task view that the user does has not interacted with the stack after a certain * time. */ - void setNoUserInteractionState() { + public void setNoUserInteractionState() { mDismissButton.setVisibility(View.VISIBLE); mDismissButton.animate().cancel(); mDismissButton.setAlpha(1f); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java index a86abf629109..8b4700c54b00 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java @@ -53,6 +53,7 @@ public class GridTaskView extends TaskView { mThumbnailView.setOverlayHeaderOnThumbnailActionBar(false); mThumbnailView.updateThumbnailMatrix(); mThumbnailView.setTranslationY(mHeaderHeight); + mHeaderView.setShouldDarkenBackgroundColor(true); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java index 3058c0a1e739..ee0116ec7dc6 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java @@ -25,7 +25,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.statusbar.phone.StatusBarIconController; -import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING; +import static com.android.settingslib.graph.BatteryMeterDrawableBase.SHOW_PERCENT_SETTING; public class BatteryPreference extends DropDownPreference implements TunerService.Tunable { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java index ca582b360a48..7acd888483ab 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java @@ -38,7 +38,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import com.android.systemui.BatteryMeterDrawable; +import com.android.settingslib.graph.BatteryMeterDrawableBase; import com.android.systemui.DemoMode; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -200,7 +200,8 @@ public class TunerService { public void clearAll() { // A couple special cases. Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); - Settings.System.putString(mContentResolver, BatteryMeterDrawable.SHOW_PERCENT_SETTING, null); + Settings.System.putString(mContentResolver, + BatteryMeterDrawableBase.SHOW_PERCENT_SETTING, null); Intent intent = new Intent(DemoMode.ACTION_DEMO); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); mContext.sendBroadcast(intent); diff --git a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java index cb0f7a388d01..09808d47a995 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java @@ -16,7 +16,6 @@ package com.android.systemui; -import static junit.framework.Assert.assertEquals; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyFloat; @@ -51,24 +50,6 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { } @Test - public void testGetIntrinsicSize() { - assertEquals( - mResources.getDimensionPixelSize(R.dimen.battery_width), - mBatteryMeter.getIntrinsicWidth()); - assertEquals( - mResources.getDimensionPixelSize(R.dimen.battery_height), - mBatteryMeter.getIntrinsicHeight()); - } - - @Test - public void testDrawNothingBeforeOnBatteryLevelChanged() { - final Canvas canvas = mock(Canvas.class); - mBatteryMeter.draw(canvas); - verify(canvas, never()).drawPath(any(), any()); - verify(canvas, never()).drawText(anyString(), anyFloat(), anyFloat(), any()); - } - - @Test public void testDrawImageButNoTextIfPluggedIn() { mBatteryMeter.onBatteryLevelChanged(0, true, true); final Canvas canvas = mock(Canvas.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index 29d5a36be0b3..f22c1af23efa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -15,11 +15,6 @@ package com.android.systemui.qs; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.os.Handler; -import android.os.Looper; -import android.support.test.runner.AndroidJUnit4; import com.android.systemui.Dependency; import com.android.systemui.FragmentTestCase; @@ -27,28 +22,16 @@ import com.android.systemui.R; import com.android.systemui.statusbar.phone.QSTileHost; import com.android.systemui.statusbar.phone.QuickStatusBarHeader; import com.android.systemui.statusbar.phone.StatusBarIconController; -import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.BluetoothController; -import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.FlashlightController; -import com.android.systemui.statusbar.policy.HotspotController; -import com.android.systemui.statusbar.policy.KeyguardMonitor; -import com.android.systemui.statusbar.policy.LocationController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NextAlarmController; -import com.android.systemui.statusbar.policy.RotationLockController; -import com.android.systemui.statusbar.policy.SecurityController; -import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; -import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; -import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; +import android.os.Handler; +import android.os.Looper; +import android.support.test.runner.AndroidJUnit4; @RunWith(AndroidJUnit4.class) public class QSFragmentTest extends FragmentTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java index 5401c30def54..95190e331d64 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java @@ -161,4 +161,10 @@ public class TileLayoutTest extends SysuiTestCase { assertEquals(top1.getValue().intValue(), top2.getValue().intValue()); assertEquals(bottom1.getValue().intValue(), bottom2.getValue().intValue()); } + + @Test + public void testEmptyHeight() { + mTileLayout.measure(mLayoutSizeForOneTile, mLayoutSizeForOneTile); + assertEquals(0, mTileLayout.getMeasuredHeight()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java index f553277e6e33..b841ce908ca2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java @@ -25,6 +25,7 @@ public class FakeTunerService extends TunerService { public FakeTunerService(Context context, LeakCheckedTest test) { super(context); mBaseLeakChecker = new BaseLeakChecker<>(test, "tunable"); + destroy(); } @Override diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 3d9ef02bf97d..aae5dd83723a 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2932,7 +2932,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public boolean findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - long interrogatingTid) throws RemoteException { + long interrogatingTid, Bundle arguments) throws RemoteException { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; Region partialInteractiveRegion = Region.obtain(); @@ -2964,7 +2964,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { try { connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, - interrogatingPid, interrogatingTid, spec); + interrogatingPid, interrogatingTid, spec, arguments); return true; } catch (RemoteException re) { if (DEBUG) { diff --git a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java index c68ac60bb26b..ed0d23435984 100644 --- a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java +++ b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java @@ -17,134 +17,276 @@ package com.android.server.autofill; import static com.android.server.autofill.Helper.DEBUG; +import android.annotation.Nullable; import android.content.Context; +import android.graphics.PixelFormat; import android.graphics.Rect; +import android.os.IBinder; import android.util.Slog; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; +import android.view.View.MeasureSpec; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; -import java.io.PrintWriter; /** * A window above the application that is smartly anchored to a rectangular region. */ -final class AnchoredWindow { +final class AnchoredWindow implements View.OnLayoutChangeListener, View.OnTouchListener { private static final String TAG = "AutoFill"; + private static final int NULL_HEIGHT = -1; + private final WindowManager mWm; - private final View mRootView; - private final View mView; - private final int mWidth; - private final int mHeight; - private boolean mIsShowing = false; + private final IBinder mAppToken; + private final View mContentView; + + private final View mWindowSizeListenerView; + private final int mMinMargin; + + private int mLastHeight = NULL_HEIGHT; + @Nullable + private Rect mLastBounds; + @Nullable + private Rect mLastDisplayBounds; /** * Constructor. * - * @param wm window manager that draws the view on a window - * @param view singleton view in the window - * @param width requested width of the view - * @param height requested height of the view + * @param wm window manager that draws the content on a window + * @param appToken token to pass to window manager + * @param contentView content of the window */ - AnchoredWindow(WindowManager wm, View view, int width, int height) { + AnchoredWindow(WindowManager wm, IBinder appToken, View contentView) { mWm = wm; - mRootView = wrapView(view, width, height); - mView = view; - mWidth = width; - mHeight = height; + mAppToken = appToken; + mContentView = contentView; + + mContentView.addOnLayoutChangeListener(this); + + Context context = contentView.getContext(); + + mWindowSizeListenerView = new FrameLayout(context); + mWindowSizeListenerView.addOnLayoutChangeListener(this); + + mMinMargin = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.autofill_fill_min_margin); } /** * Shows the window. * - * @param bounds the rectangular region this window should be anchored to + * @param bounds the region the window should be anchored to */ void show(Rect bounds) { - final LayoutParams params = createBaseLayoutParams(); - params.x = bounds.left; - params.y = bounds.bottom; + if (DEBUG) Slog.d(TAG, "show bounds=" + bounds); - if (!mIsShowing) { - if (DEBUG) Slog.d(TAG, "adding view " + mView); - mWm.addView(mRootView, params); - } else { - if (DEBUG) Slog.d(TAG, "updating view " + mView); - mWm.updateViewLayout(mRootView, params); + if (!mWindowSizeListenerView.isAttachedToWindow()) { + if (DEBUG) Slog.d(TAG, "adding mWindowSizeListenerView"); + LayoutParams params = createWindowLayoutParams( + mAppToken, + LayoutParams.FLAG_NOT_TOUCHABLE); // not touchable + params.gravity = Gravity.LEFT | Gravity.TOP; + params.x = 0; + params.y = 0; + params.width = LayoutParams.MATCH_PARENT; + params.height = LayoutParams.MATCH_PARENT; + mWm.addView(mWindowSizeListenerView, params); } - mIsShowing = true; + + updateBounds(bounds); } /** * Hides the window. */ void hide() { - if (DEBUG) Slog.d(TAG, "removing view " + mView); + if (DEBUG) Slog.d(TAG, "hide"); + + mLastHeight = NULL_HEIGHT; + mLastBounds = null; + mLastDisplayBounds = null; - if (mIsShowing) { - mWm.removeView(mRootView); + if (mWindowSizeListenerView.isAttachedToWindow()) { + if (DEBUG) Slog.d(TAG, "removing mWindowSizeListenerView"); + mWm.removeView(mWindowSizeListenerView); } - mIsShowing = false; - } - /** - * Wraps a view with a SelfRemovingView and sets its requested width and height. - */ - private View wrapView(View view, int width, int height) { - final ViewGroup viewGroup = new SelfRemovingView(view.getContext()); - viewGroup.addView(view, new ViewGroup.LayoutParams(width, height)); - return viewGroup; + if (mContentView.isAttachedToWindow()) { + if (DEBUG) Slog.d(TAG, "removing mContentView"); + mContentView.setOnTouchListener(null); + mWm.removeView(mContentView); + } } - private static LayoutParams createBaseLayoutParams() { - final LayoutParams params = new LayoutParams(); - // TODO(b/33197203): LayoutParams.TYPE_AUTOFILL - params.type = LayoutParams.TYPE_SYSTEM_ALERT; - params.flags = - LayoutParams.SOFT_INPUT_STATE_UNCHANGED - | LayoutParams.FLAG_LAYOUT_IN_SCREEN - | LayoutParams.FLAG_LAYOUT_NO_LIMITS - | LayoutParams.FLAG_NOT_FOCUSABLE - | LayoutParams.FLAG_NOT_TOUCH_MODAL - | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; - params.gravity = Gravity.TOP | Gravity.LEFT; - params.width = LayoutParams.WRAP_CONTENT; - params.height = LayoutParams.WRAP_CONTENT; - return params; + @Override + public void onLayoutChange(View view, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (view == mWindowSizeListenerView) { + if (DEBUG) Slog.d(TAG, "onLayoutChange() for mWindowSizeListenerView"); + // mWindowSizeListenerView layout changed, get the size of the display bounds and update + // the window. + final Rect displayBounds = new Rect(); + view.getBoundsOnScreen(displayBounds); + updateDisplayBounds(displayBounds); + } else if (view == mContentView) { + // mContentView layout changed, update the window in case its height changed. + if (DEBUG) Slog.d(TAG, "onLayoutChange() for mContentView"); + updateHeight(); + } } + // When the window is touched outside, hide the window. @Override - public String toString() { - if (!DEBUG) return super.toString(); + public boolean onTouch(View view, MotionEvent event) { + if (view == mContentView && event.getAction() == MotionEvent.ACTION_OUTSIDE) { + hide(); + return true; + } + return false; + } + + private boolean updateHeight() { + final Rect displayBounds = mLastDisplayBounds; + if (displayBounds == null) { + return false; + } + + mContentView.measure( + MeasureSpec.makeMeasureSpec(displayBounds.width(), MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(displayBounds.height(), MeasureSpec.AT_MOST)); + int height = mContentView.getMeasuredHeight(); + if (height != mLastHeight) { + if (DEBUG) Slog.d(TAG, "update height=" + height); + mLastHeight = height; + update(height, mLastBounds, displayBounds); + return true; + } else { + return false; + } + } + + private void updateBounds(Rect bounds) { + if (!bounds.equals(mLastBounds)) { + if (DEBUG) Slog.d(TAG, "update bounds=" + bounds); + mLastBounds = bounds; - return "AnchoredWindow: [width=" + mWidth + ", height=" + mHeight + ", view=" + mView + "]"; + update(mLastHeight, bounds, mLastDisplayBounds); + } } - void dump(PrintWriter pw) { - pw.println("Anchored Window"); - final String prefix = " "; - pw.print(prefix); pw.print("width: "); pw.println(mWidth); - pw.print(prefix); pw.print("height: "); pw.println(mHeight); - pw.print(prefix); pw.print("visible: "); pw.println(mIsShowing); + private void updateDisplayBounds(Rect displayBounds) { + if (!displayBounds.equals(mLastDisplayBounds)) { + if (DEBUG) Slog.d(TAG, "update displayBounds=" + displayBounds); + mLastDisplayBounds = displayBounds; + + if (!updateHeight()) { + update(mLastHeight, mLastBounds, displayBounds); + } + } } - /** FrameLayout that listens for touch events removes itself if the touch event is outside. */ - private final class SelfRemovingView extends FrameLayout { - public SelfRemovingView(Context context) { - super(context); + // Updates the window if height, bounds, and displayBounds are not null. + // Caller should ensure that something changed before calling. + private void update(int height, @Nullable Rect bounds, @Nullable Rect displayBounds) { + if (height == NULL_HEIGHT || bounds == null || displayBounds == null) { + return; } - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { - hide(); - return true; + if (DEBUG) Slog.d(TAG, "update height=" + height + ", bounds=" + bounds + + ", displayBounds=" + displayBounds); + + final LayoutParams params = createWindowLayoutParams(mAppToken, + LayoutParams.FLAG_NOT_TOUCH_MODAL // outside touches go to windows behind us + | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); // outside touches trigger MotionEvent + params.setTitle("AutoFill Fill"); // used for debugging + updatePosition(params, height, mMinMargin, bounds, displayBounds); + if (!mContentView.isAttachedToWindow()) { + if (DEBUG) Slog.d(TAG, "adding mContentView"); + mWm.addView(mContentView, params); + mContentView.setOnTouchListener(this); + } else { + if (DEBUG) Slog.d(TAG, "updating mContentView"); + mWm.updateViewLayout(mContentView, params); + } + } + + /** + * Updates the position of the window by altering the {@link LayoutParams}. + * + * <p>The window can be anchored either above or below the bounds. Anchoring the window below + * the bounds is preferred, if it fits. Otherwise, anchor the window on the side with more + * space. + * + * @param params the params to update + * @param height the requested height of the window + * @param minMargin the minimum margin between the window and the display bounds + * @param bounds the region the window should be anchored to + * @param displayBounds the region in which the window may be displayed + */ + private static void updatePosition( + LayoutParams params, + int height, + int minMargin, + Rect bounds, + Rect displayBounds) { + boolean below; + int verticalSpace; + final int verticalSpaceBelow = displayBounds.bottom - bounds.bottom - minMargin; + if (height <= verticalSpaceBelow) { + // Fits below bounds. + below = true; + verticalSpace = height; + } else { + final int verticalSpaceAbove = bounds.top - displayBounds.top - minMargin; + if (height <= verticalSpaceAbove) { + // Fits above bounds. + below = false; + verticalSpace = height; } else { - return super.onTouchEvent(event); + // Pick above/below based on which has the most space. + if (verticalSpaceBelow >= verticalSpaceAbove) { + below = true; + verticalSpace = verticalSpaceBelow; + } else { + below = false; + verticalSpace = verticalSpaceAbove; + } } } + + int gravity; + int y; + if (below) { + if (DEBUG) Slog.d(TAG, "anchorBelow"); + gravity = Gravity.TOP | Gravity.LEFT; + y = bounds.bottom - displayBounds.top; + } else { + if (DEBUG) Slog.d(TAG, "anchorAbove"); + gravity = Gravity.BOTTOM | Gravity.LEFT; + y = displayBounds.bottom - bounds.top; + } + + final int x = bounds.left - displayBounds.left; + + params.gravity = gravity; + params.x = x; + params.y = y; + params.width = bounds.width(); + params.height = verticalSpace; + } + + private static LayoutParams createWindowLayoutParams(IBinder appToken, int flags) { + final LayoutParams params = new LayoutParams(); + params.token = appToken; + params.type = LayoutParams.TYPE_PHONE; + params.flags = + flags + | LayoutParams.FLAG_NOT_FOCUSABLE // don't receive input events + | LayoutParams.FLAG_ALT_FOCUSABLE_IM; // resize for soft input + params.format = PixelFormat.TRANSLUCENT; + return params; } } diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java index 178a6973a7b1..93473503479b 100644 --- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java @@ -18,8 +18,11 @@ package com.android.server.autofill; import static android.Manifest.permission.MANAGE_AUTO_FILL; import static android.content.Context.AUTO_FILL_MANAGER_SERVICE; +import static com.android.server.autofill.Helper.DEBUG; +import static com.android.server.autofill.Helper.VERBOSE; import android.Manifest; +import android.annotation.Nullable; import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.content.ComponentName; @@ -34,7 +37,6 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; @@ -70,12 +72,11 @@ import java.util.List; public final class AutoFillManagerService extends SystemService { private static final String TAG = "AutoFillManagerService"; - static final boolean DEBUG = false; - protected static final int MSG_REQUEST_AUTO_FILL_FOR_USER = 1; - protected static final int MSG_REQUEST_AUTO_FILL = 2; - private static final int MSG_REQUEST_SAVE_FOR_USER = 3; - private static final int MSG_ON_VALUE_CHANGED = 4; + private static final int MSG_START_SESSION = 1; + private static final int MSG_UPDATE_SESSION = 2; + private static final int MSG_FINISH_SESSION = 3; + private static final int MSG_REQUEST_SAVE_FOR_USER = 4; private final Context mContext; private final AutoFillUI mUi; @@ -84,30 +85,31 @@ public final class AutoFillManagerService extends SystemService { private final HandlerCaller.Callback mHandlerCallback = (msg) -> { switch (msg.what) { - case MSG_REQUEST_AUTO_FILL_FOR_USER: { - handleAutoFillForUser(msg.arg1); + case MSG_START_SESSION: { + final SomeArgs args = (SomeArgs) msg.obj; + final int userId = msg.arg1; + final IBinder activityToken = (IBinder) args.arg1; + final IBinder appCallback = (IBinder) args.arg2; + final AutoFillId autoFillId = (AutoFillId) args.arg3; + final Rect bounds = (Rect) args.arg4; + final AutoFillValue value = (AutoFillValue) args.arg5; + handleStartSession(userId, activityToken, appCallback, autoFillId, bounds, value); + return; + } case MSG_FINISH_SESSION: { + handleFinishSession(msg.arg1, (IBinder) msg.obj); return; } case MSG_REQUEST_SAVE_FOR_USER: { handleSaveForUser(msg.arg1); return; - } case MSG_REQUEST_AUTO_FILL: { + } case MSG_UPDATE_SESSION: { final SomeArgs args = (SomeArgs) msg.obj; - final int userId = msg.arg1; - final int flags = msg.arg2; final IBinder activityToken = (IBinder) args.arg1; final AutoFillId autoFillId = (AutoFillId) args.arg2; final Rect bounds = (Rect) args.arg3; - args.recycle(); - handleAutoFill(activityToken, userId, autoFillId, bounds, flags); - return; - } case MSG_ON_VALUE_CHANGED: { - final SomeArgs args = (SomeArgs) msg.obj; - final int userId = msg.arg1; - final IBinder activityToken = (IBinder) args.arg1; - final AutoFillId autoFillId = (AutoFillId) args.arg2; - final AutoFillValue newValue = (AutoFillValue) args.arg3; - args.recycle(); - handleValueChanged(activityToken, userId, autoFillId, newValue); + final AutoFillValue value = (AutoFillValue) args.arg4; + final int userId = args.argi5; + final int flags = args.argi6; + handleUpdateSession(userId, activityToken, autoFillId, bounds, value, flags); return; } default: { Slog.w(TAG, "Invalid message: " + msg); @@ -188,8 +190,11 @@ public final class AutoFillManagerService extends SystemService { /** * Gets the service instance for an user. + * + * @return service instance or {@code null} if user does not have a service set. */ - AutoFillManagerServiceImpl getOrCreateServiceForUserLocked(int userId) { + @Nullable + AutoFillManagerServiceImpl getServiceForUserLocked(int userId) { AutoFillManagerServiceImpl service = mServicesCache.get(userId); if (service == null) { service = newServiceForUser(userId); @@ -209,107 +214,114 @@ public final class AutoFillManagerService extends SystemService { } } - private void handleAutoFill(IBinder activityToken, int userId, AutoFillId autoFillId, - Rect bounds, int flags) { + private void handleStartSession(int userId, IBinder activityToken, IBinder appCallback, + AutoFillId autoFillId, Rect bounds, AutoFillValue value) { + synchronized (mLock) { + final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId); + if (service == null) { + return; + } + service.startSessionLocked(activityToken, appCallback, autoFillId, bounds, value); + } + } + + private void handleFinishSession(int userId, IBinder activityToken) { synchronized (mLock) { - final AutoFillManagerServiceImpl service = getOrCreateServiceForUserLocked(userId); - if (service != null) { - service.requestAutoFillLocked(activityToken, autoFillId, bounds, flags); + final AutoFillManagerServiceImpl service = mServicesCache.get(userId); + if (service == null) { + return; } + service.finishSessionLocked(activityToken); } } - private void handleValueChanged(IBinder activityToken, int userId, AutoFillId autoFillId, - AutoFillValue newValue) { + private void handleUpdateSession(int userId, IBinder activityToken, AutoFillId autoFillId, + Rect bounds, AutoFillValue value, int flags) { synchronized (mLock) { - final AutoFillManagerServiceImpl service = getOrCreateServiceForUserLocked(userId); - if (service != null) { - service.onValueChangeLocked(activityToken, autoFillId, newValue); + final AutoFillManagerServiceImpl service = mServicesCache.get(userId); + if (service == null) { + return; } + + service.updateSessionLocked(activityToken, autoFillId, bounds, value, flags); } } private IBinder getTopActivityForUser() { final List<IBinder> topActivities = LocalServices .getService(ActivityManagerInternal.class).getTopVisibleActivities(); + if (DEBUG) Slog.d(TAG, "Top activities (" + topActivities.size() + "): " + topActivities); if (topActivities.isEmpty()) { + Slog.w(TAG, "Could not get top activity"); return null; } return topActivities.get(0); } - private void handleAutoFillForUser(int userId) { - final IBinder activityToken = getTopActivityForUser(); - if (activityToken != null) { - synchronized (mLock) { - final AutoFillManagerServiceImpl service = - getOrCreateServiceForUserLocked(userId); - service.requestAutoFillLocked(activityToken, null, null, 0); - } - } - - } - private void handleSaveForUser(int userId) { final IBinder activityToken = getTopActivityForUser(); if (activityToken != null) { synchronized (mLock) { - final AutoFillManagerServiceImpl service = - getOrCreateServiceForUserLocked(userId); + final AutoFillManagerServiceImpl service = mServicesCache.get(userId); + if (service == null) { + Log.w(TAG, "handleSaveForUser(): no cached service for userId " + userId); + return; + } + service.requestSaveForUserLocked(activityToken); } } } - private IBinder getTopActivity() { - final int uid = Binder.getCallingUid(); - final IBinder activityToken = LocalServices.getService(ActivityManagerInternal.class) - .getTopVisibleActivity(uid); - if (activityToken == null) { - // Make sure its called by the top activity. - if (uid == Process.SYSTEM_UID) { - // TODO(b/33197203, b/34819567, b/34171325): figure out proper way to handle it - if (DEBUG) Log.w(TAG, "requestAutoFill(): ignoring call from system"); + final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub { - return null; + @Override + public void startSession(IBinder activityToken, IBinder appCallback, AutoFillId autoFillId, + Rect bounds, AutoFillValue value) throws RemoteException { + // TODO(b/33197203): make sure it's called by resumed / focused activity + + final int userId = UserHandle.getCallingUserId(); + if (VERBOSE) { + Slog.v(TAG, "startSession: autoFillId=" + autoFillId + ", bounds=" + bounds + + ", value=" + value); } - throw new SecurityException("uid " + uid + " does not own the top activity"); - } - return activityToken; - } + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = activityToken; + args.arg2 = appCallback; + args.arg3 = autoFillId; + args.arg4 = bounds; + args.arg5 = value; - final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub { + mHandlerCaller.sendMessage(mHandlerCaller.getHandler().obtainMessage(MSG_START_SESSION, + userId, 0, args)); + } @Override - public void requestAutoFill(AutoFillId id, Rect bounds, int flags) { - final IBinder activityToken = getTopActivity(); - if (activityToken != null) { - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIIOOO(MSG_REQUEST_AUTO_FILL, - UserHandle.getCallingUserId(), flags, activityToken, id, bounds)); + public void updateSession(IBinder activityToken, AutoFillId id, Rect bounds, + AutoFillValue value, int flags) throws RemoteException { + if (DEBUG) { + Slog.d(TAG, "updateSession: flags=" + flags + ", autoFillId=" + id + + ", bounds=" + bounds + ", value=" + value); } + + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOOII(MSG_UPDATE_SESSION, + activityToken, id, bounds, value, UserHandle.getCallingUserId(), flags)); } @Override - public void requestAutoFillForUser(int userId) { - mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageI( - MSG_REQUEST_AUTO_FILL_FOR_USER, userId)); + public void finishSession(IBinder activityToken) throws RemoteException { + if (VERBOSE) Slog.v(TAG, "finishSession(): " + activityToken); + + mHandlerCaller.sendMessage(mHandlerCaller.getHandler().obtainMessage(MSG_FINISH_SESSION, + UserHandle.getCallingUserId(), 0, activityToken)); } @Override public void requestSaveForUser(int userId) { mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageI(MSG_REQUEST_SAVE_FOR_USER, userId)); - } - - @Override - public void onValueChanged(AutoFillId id, AutoFillValue value) { - final IBinder activityToken = getTopActivity(); - if (activityToken != null) { - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOOO(MSG_ON_VALUE_CHANGED, - UserHandle.getCallingUserId(), activityToken, id, value)); - } + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageI(MSG_REQUEST_SAVE_FOR_USER, + userId)); } @Override diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java index e32e21d54b56..8c74532532e1 100644 --- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java @@ -16,11 +16,17 @@ package com.android.server.autofill; -import static android.view.autofill.AutoFillManager.FLAG_UPDATE_UI_SHOW; -import static android.view.autofill.AutoFillManager.FLAG_UPDATE_UI_HIDE; +import static android.service.autofill.AutoFillService.EXTRA_ACTIVITY_TOKEN; +import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS; +import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE; +import static android.view.autofill.AutoFillManager.FLAG_FOCUS_GAINED; +import static android.view.autofill.AutoFillManager.FLAG_FOCUS_LOST; +import static android.view.autofill.AutoFillManager.FLAG_START_SESSION; +import static android.view.autofill.AutoFillManager.FLAG_VALUE_CHANGED; import static com.android.server.autofill.Helper.DEBUG; import static com.android.server.autofill.Helper.VERBOSE; +import static com.android.server.autofill.Helper.findValue; import android.annotation.Nullable; import android.app.Activity; @@ -40,6 +46,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; import android.os.ICancellationSignal; +import android.os.Looper; import android.os.RemoteException; import android.service.autofill.AutoFillService; import android.service.autofill.AutoFillServiceInfo; @@ -47,25 +54,22 @@ import android.service.autofill.FillCallback; import android.service.autofill.IAutoFillAppCallback; import android.service.autofill.IAutoFillService; import android.service.autofill.IFillCallback; -import android.service.voice.VoiceInteractionSession; import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; import android.util.PrintWriterPrinter; import android.util.Slog; -import android.util.SparseArray; import android.view.autofill.AutoFillId; import android.view.autofill.AutoFillValue; import android.view.autofill.Dataset; import android.view.autofill.FillResponse; import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.HandlerCaller; import com.android.internal.os.IResultReceiver; import com.android.server.FgThread; import java.io.PrintWriter; -import java.lang.ref.WeakReference; -import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -78,8 +82,7 @@ final class AutoFillManagerServiceImpl { private static final String TAG = "AutoFillManagerServiceImpl"; - /** Used do assign ids to new ServerCallback instances. */ - private static int sSessionIdCounter = 0; + private static final int MSG_SERVICE_SAVE = 1; private final int mUserId; private final ComponentName mComponent; @@ -103,8 +106,20 @@ final class AutoFillManagerServiceImpl { } }; + private final HandlerCaller.Callback mHandlerCallback = (msg) -> { + switch (msg.what) { + case MSG_SERVICE_SAVE: + handleSessionSave((IBinder) msg.obj); + break; + default: + Slog.d(TAG, "invalid msg: " + msg); + } + }; + + private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), + mHandlerCallback, true); /** - * Cache of pending {@link Session}s, keyed by {@link Session#mId}. + * Cache of pending {@link Session}s, keyed by {@code activityToken}. * * <p>They're kept until the {@link AutoFillService} finished handling a request, an error * occurs, or the session times out. @@ -112,42 +127,44 @@ final class AutoFillManagerServiceImpl { // TODO(b/33197203): need to make sure service is bound while callback is pending and/or // use WeakReference @GuardedBy("mLock") - private final SparseArray<Session> mSessions = new SparseArray<>(); + private final ArrayMap<IBinder, Session> mSessions = new ArrayMap<>(); /** - * Receiver of assist data from the app's {@link Activity}, uses the {@code resultData} as - * the {@link Session#mId}. + * Receiver of assist data from the app's {@link Activity}. */ private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { @Override public void send(int resultCode, Bundle resultData) throws RemoteException { if (DEBUG) Slog.d(TAG, "resultCode on mAssistReceiver: " + resultCode); - final IBinder appBinder = resultData.getBinder(AutoFillService.KEY_CALLBACK); - if (appBinder == null) { - Slog.w(TAG, "no app callback on mAssistReceiver's resultData"); - return; - } + final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE); - final AssistStructure structure = resultData - .getParcelable(VoiceInteractionSession.KEY_STRUCTURE); if (structure == null) { Slog.w(TAG, "no assist structure for id " + resultCode); return; } + final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS); + if (receiverExtras == null) { + // Should not happen + Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver"); + return; + } + + final IBinder activityToken = receiverExtras.getBinder(EXTRA_ACTIVITY_TOKEN); final Session session; synchronized (mLock) { - session = mSessions.get(resultCode); + session = mSessions.get(activityToken); if (session == null) { - Slog.w(TAG, "no server callback for id " + resultCode); + Slog.w(TAG, "no server session for activityToken " + activityToken); return; } + // TODO(b/33197203): since service is fetching the data (to use for save later), + // we should optimize what's sent (for example, remove layout containers, + // color / font info, etc...) + session.mStructure = structure; } - // TODO(b/33197203): since service is fetching the data (to use for save later), - // we should optimize what's sent (for example, remove layout containers, - // color / font info, etc...) // TODO(b/33197203, b/33269702): Must fetch the data so it's available later on // handleSave(), even if if the activity is gone by then, but structure.ensureData() @@ -156,14 +173,11 @@ final class AutoFillManagerServiceImpl { // method that sends all the data structure.ensureData(); + // Sanitize structure before it's sent to service. structure.sanitizeForParceling(true); - if (VERBOSE) { - Slog.v(TAG, "Dumping " + structure + " before calling service.autoFill()"); - structure.dump(); - } - - session.onApplicationDataAvailable(structure, appBinder); + // TODO(b/33197203): Need to pipe the bundle + session.mRemoteFillService.onFillRequest(structure, null); } }; @@ -190,46 +204,50 @@ final class AutoFillManagerServiceImpl { * Used by {@link AutoFillManagerServiceShellCommand} to request save for the current top app. */ void requestSaveForUserLocked(IBinder activityToken) { - final Session session = getOrCreateSessionByTokenLocked(activityToken); - session.onSaveLocked(); + final Session session = mSessions.get(activityToken); + if (session == null) { + Slog.w(TAG, "requestSaveForUserLocked(): no session for " + activityToken); + return; + } + + session.callSaveLocked(); } - /** - * Asks service to auto-fill an activity. - * - * @param activityToken activity token. - * @param autoFillId id of the view that requested auto-fill. - * @param bounds boundaries of the view that requested auto-fill. - * @param flags optional flags. - */ - void requestAutoFillLocked(IBinder activityToken, @Nullable AutoFillId autoFillId, - @Nullable Rect bounds, int flags) { - final String historyItem = "s=" + mComponentName + " u=" + mUserId + " f=" + flags - + " a=" + activityToken + " i=" + autoFillId + " b=" + bounds; + void startSessionLocked(IBinder activityToken, IBinder appCallbackToken, AutoFillId autoFillId, + Rect bounds, AutoFillValue value) { + final String historyItem = "s=" + mComponentName + " u=" + mUserId + " a=" + activityToken + + " i=" + autoFillId + " b=" + bounds + " v=" + value; mRequestsHistory.log(historyItem); // TODO(b/33197203): Handle partitioning - Session session = getOrCreateSessionByTokenLocked(activityToken); - session.updateAutoFillInput(flags, autoFillId, null, bounds); + final Session session = mSessions.get(activityToken); + if (session != null) { + // Already started... + return; + } + + final Session newSession = createSessionByTokenLocked(activityToken, appCallbackToken); + newSession.updateLocked(autoFillId, bounds, value, FLAG_START_SESSION); + newSession.enableSessionLocked(); } - private Session getOrCreateSessionByTokenLocked(IBinder activityToken) { - final int size = mSessions.size(); - for (int i = 0; i < size; i++) { - final Session session = mSessions.valueAt(i); - if (activityToken.equals(session.mActivityToken.get())) { - return session; - } + void finishSessionLocked(IBinder activityToken) { + if (DEBUG) Slog.d(TAG, "finishSessionLocked(): " + activityToken); + final Session session = mSessions.get(activityToken); + + if (session == null) { + Slog.w(TAG, "finishSessionLocked(): no session for " + activityToken); + return; } - return createSessionByTokenLocked(activityToken); + + mUi.hideFillUi(); + session.showSaveLocked(); } - private Session createSessionByTokenLocked(IBinder activityToken) { - final int sessionId = ++sSessionIdCounter; - if (DEBUG) Slog.d(TAG, "creating session for " + activityToken + ": " + sessionId); + private Session createSessionByTokenLocked(IBinder activityToken, IBinder appCallbackToken) { - final Session newSession = new Session(mContext, activityToken, sessionId); - mSessions.put(sessionId, newSession); + final Session newSession = new Session(mContext, activityToken, appCallbackToken); + mSessions.put(activityToken, newSession); /* * TODO(b/33197203): apply security checks below: @@ -240,7 +258,9 @@ final class AutoFillManagerServiceImpl { */ try { // TODO(b/33197203): add MetricsLogger call - if (!mAm.requestAutoFillData(mAssistReceiver, null, sessionId, activityToken)) { + final Bundle receiverExtras = new Bundle(); + receiverExtras.putBinder(EXTRA_ACTIVITY_TOKEN, activityToken); + if (!mAm.requestAutoFillData(mAssistReceiver, receiverExtras, activityToken)) { // TODO(b/33197203): might need a way to warn user (perhaps a new method on // AutoFillService). Slog.w(TAG, "failed to request auto-fill data for " + activityToken); @@ -251,39 +271,53 @@ final class AutoFillManagerServiceImpl { return newSession; } - /** - * Callback indicating the value of a field change in the app. - */ - void onValueChangeLocked(IBinder activityToken, AutoFillId autoFillId, AutoFillValue newValue) { + void updateSessionLocked(IBinder activityToken, AutoFillId autoFillId, Rect bounds, + AutoFillValue value, int flags) { + // TODO(b/33197203): add MetricsLogger call - final Session session = getOrCreateSessionByTokenLocked(activityToken); - session.updateValueLocked(autoFillId, newValue); + final Session session = mSessions.get(activityToken); + if (session == null) { + Slog.w(TAG, "updateSessionLocked(): session gone for " + activityToken); + return; + } + + session.updateLocked(autoFillId, bounds, value, flags); } - void removeSessionLocked(int id) { - if (DEBUG) Slog.d(TAG, "Removing session " + id); - mSessions.get(id); + private void handleSessionSave(IBinder activityToken) { + + synchronized (mLock) { + final Session session = mSessions.get(activityToken); + if (session == null) { + Slog.w(TAG, "handleSessionSave(): already gone: " + activityToken); + + return; + } + session.callSaveLocked(); + } } void destroyLocked() { + if (VERBOSE) Slog.v(TAG, "destroyLocked()"); + mContext.unregisterReceiver(mBroadcastReceiver); - final int sessionCount = mSessions.size(); - for (int i = sessionCount - 1; i >= 0; i--) { - Session session = mSessions.valueAt(i); - session.destroy(); - mSessions.removeAt(i); + for (Session session : mSessions.values()) { + session.destroyLocked(); } + mSessions.clear(); } void dumpLocked(String prefix, PrintWriter pw) { final String prefix2 = prefix + " "; - if (DEBUG) { + + pw.print(prefix); pw.println("Component:"); pw.println(mComponentName); + + if (VERBOSE) { // ServiceInfo dump is too noisy and redundant (it can be obtained through other dumps) pw.print(prefix); pw.println("ServiceInfo:"); mInfo.getServiceInfo().dump(new PrintWriterPrinter(pw), prefix + prefix); } - pw.print(prefix); pw.print("sSessionIdCounter="); pw.println(sSessionIdCounter); final int size = mSessions.size(); if (size == 0) { pw.print(prefix); pw.println("No sessions"); @@ -317,13 +351,17 @@ final class AutoFillManagerServiceImpl { @Nullable AutoFillValue value); } + final AutoFillId mId; private final Listener mListener; // // TODO(b/33197203): does it really need a reference to the session's response? private FillResponse mResponse; private AutoFillValue mAutoFillValue; private Rect mBounds; - ViewState(Listener listener) { + private boolean mValueUpdated; + + ViewState(AutoFillId id, Listener listener) { + mId = id; mListener = listener; } @@ -335,6 +373,9 @@ final class AutoFillManagerServiceImpl { maybeCallOnFillReady(); } + // TODO(b/33197203): need to refactor / rename / document this method to make it clear that + // it can change the value and update the UI; similarly, should replace code that + // directly sets mAutoFilLValue to use encapsulation. void update(@Nullable AutoFillValue autoFillValue, @Nullable Rect bounds) { if (autoFillValue != null) { mAutoFillValue = autoFillValue; @@ -360,9 +401,17 @@ final class AutoFillManagerServiceImpl { public String toString() { if (!DEBUG) return super.toString(); - return "ViewState: [response=" + mResponse + ", value=" + mAutoFillValue - + ", bounds=" + mBounds + "]"; + return "ViewState: [id=" + mId + ", value=" + mAutoFillValue + ", bounds=" + mBounds + + ", updated = " + mValueUpdated + "]"; } + + void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("id:" ); pw.println(mId); + pw.print(prefix); pw.print("value:" ); pw.println(mAutoFillValue); + pw.print(prefix); pw.print("updated:" ); pw.println(mValueUpdated); + pw.print(prefix); pw.print("bounds:" ); pw.println(mBounds); + } + } /** @@ -383,9 +432,7 @@ final class AutoFillManagerServiceImpl { // - When service is unbound. final class Session implements RemoteFillService.FillServiceCallbacks, ViewState.Listener, AutoFillUI.AutoFillUiCallback { - private final int mId; - - private final WeakReference<IBinder> mActivityToken; + private final IBinder mActivityToken; @GuardedBy("mLock") private final Map<AutoFillId, ViewState> mViewStates = new ArrayMap<>(); @@ -394,7 +441,7 @@ final class AutoFillManagerServiceImpl { @Nullable private ViewState mCurrentViewState; - private IAutoFillAppCallback mAppCallback; + private final IAutoFillAppCallback mAppCallback; @GuardedBy("mLock") RemoteFillService mRemoteFillService; @@ -404,10 +451,11 @@ final class AutoFillManagerServiceImpl { private FillResponse mCurrentResponse; /** - * Map of ids that must be updated so they're send to {@link #onSaveLocked()}. + * Used to remember which {@link Dataset} filled the session. */ + // TODO(b/33197203): might need more than one once we support partitions @GuardedBy("mLock") - private Map<AutoFillId, AutoFillValue> mUpdatedValues; + private Dataset mAutoFilledDataset; /** * Assist structure sent by the app; it will be updated (sanitized, change values for save) @@ -416,18 +464,29 @@ final class AutoFillManagerServiceImpl { @GuardedBy("mLock") private AssistStructure mStructure; - private Session(Context context, IBinder activityToken, int id) { - mActivityToken = new WeakReference<>(activityToken); + private Session(Context context, IBinder activityToken, IBinder appCallback) { mRemoteFillService = new RemoteFillService(context, mComponent, mUserId, this); - mId = id; + mActivityToken = activityToken; + + mAppCallback = IAutoFillAppCallback.Stub.asInterface(appCallback); + try { + appCallback.linkToDeath(() -> { + if (DEBUG) Slog.d(TAG, "app binder died"); + + removeSelf(); + }, 0); + } catch (RemoteException e) { + Slog.w(TAG, "linkToDeath() on mAppCallback failed: " + e); + } } + // FillServiceCallbacks @Override public void onFillRequestSuccess(FillResponse response) { // TODO(b/33197203): add MetricsLogger call if (response == null) { - destroy(); + removeSelf(); return; } synchronized (mLock) { @@ -440,13 +499,15 @@ final class AutoFillManagerServiceImpl { public void onFillRequestFailure(CharSequence message) { // TODO(b/33197203): add MetricsLogger call getUiForShowing().showError(message); - destroy(); + removeSelf(); } // FillServiceCallbacks @Override public void onSaveRequestSuccess() { - // TODO: Implement + // TODO(b/33197203): add MetricsLogger call + // Nothing left to do... + removeSelf(); } // FillServiceCallbacks @@ -454,7 +515,7 @@ final class AutoFillManagerServiceImpl { public void onSaveRequestFailure(CharSequence message) { // TODO(b/33197203): add MetricsLogger call getUiForShowing().showError(message); - destroy(); + removeSelf(); } // FillServiceCallbacks @@ -466,7 +527,7 @@ final class AutoFillManagerServiceImpl { // FillServiceCallbacks @Override public void onServiceDied(RemoteFillService service) { - // TODO: Implement + // TODO(b/33197203): implement } // AutoFillUiCallback @@ -478,58 +539,93 @@ final class AutoFillManagerServiceImpl { // AutoFillUiCallback @Override public void save() { - synchronized (mLock) { - onSaveLocked(); - } - } - - private Session(int id, IBinder activityToken) { - mId = id; - mActivityToken = new WeakReference<>(activityToken); - } - - /** - * Callback used to indivate a field has been updated. - */ - void updateValueLocked(AutoFillId id, AutoFillValue newValue) { - if (DEBUG) Slog.d(TAG, "updateValueLocked(): id=" + id + ", newValue=" + newValue); - - // TODO(b/33197203): ignore if not part of the savable ids. - if (mUpdatedValues == null) { - // Lazy initializes it - mUpdatedValues = new HashMap<>(); - } - mUpdatedValues.put(id, newValue); + mHandlerCaller.getHandler().obtainMessage(MSG_SERVICE_SAVE, mActivityToken) + .sendToTarget(); } /** - * Calls service when user requested save. + * Show the save UI, when session can be saved. */ - void onSaveLocked() { - if (DEBUG) Slog.d(TAG, "onSaveLocked(): mUpdateValues=" + mUpdatedValues); - + public void showSaveLocked() { if (mStructure == null) { // Sanity check; should not happen... - Slog.wtf(TAG, "onSaveLocked(): no mStructure"); + Slog.wtf(TAG, "showSaveLocked(): no mStructure"); return; } + final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds(); + if (VERBOSE) Slog.v(TAG, "showSaveLocked(): savableIds=" + savableIds); - if (mUpdatedValues == null || mUpdatedValues.isEmpty()) { - // Nothing changed - if (DEBUG) Slog.d(TAG, "onSave(): when no changes, comes no responsibilities"); + if (savableIds.isEmpty()) { + if (DEBUG) Slog.d(TAG, "showSaveLocked(): service doesn't want to save"); return; } - // TODO(b/33197203): make sure the extras are tested by CTS - for (Entry<AutoFillId, AutoFillValue> entry : mUpdatedValues.entrySet()) { + final int size = savableIds.size(); + for (int i = 0; i < size; i++) { + final AutoFillId id = savableIds.valueAt(i); + final ViewState state = mViewStates.get(id); + if (state != null && state.mValueUpdated) { + final AutoFillValue filledValue = findValue(mAutoFilledDataset, id); + if (state.mAutoFillValue == null || state.mAutoFillValue.equals(filledValue)) { + continue; + } + if (DEBUG) { + Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": " + + state.mAutoFillValue); + } + + mUi.showSaveUi(); + return; + } + } + // Nothing changed... + if (DEBUG) Slog.d(TAG, "showSaveLocked(): with no changes, comes no responsibilities"); + } + + /** + * Calls service when user requested save. + */ + private void callSaveLocked() { + if (DEBUG) Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates); + + // TODO(b/33197203): hookup extras and make sure they're tested by CTS + final Bundle extras = null; +// // TODO(b/33197203): make sure the extras are tested by CTS +// final Bundle responseExtras = mCurrentResponse == null ? null +// : mCurrentResponse.getExtras(); +// final Bundle datasetExtras = mAutoFilledDataset == null ? null +// : mAutoFilledDataset.getExtras(); +// final Bundle extras = (responseExtras == null && datasetExtras == null) +// ? null : new Bundle(); +// if (responseExtras != null) { +// if (DEBUG) { +// Slog.d(TAG, "response extras on save extras: " +// + bundleToString(responseExtras)); +// } +// extras.putBundle(AutoFillService.EXTRA_RESPONSE_EXTRAS, responseExtras); +// } +// if (datasetExtras != null) { +// if (DEBUG) { +// Slog.d(TAG, "dataset extras on save extras: " + bundleToString(datasetExtras)); +// } +// extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetExtras); +// } + + + for (Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) { + final AutoFillValue value = entry.getValue().mAutoFillValue; + if (value == null) { + if (VERBOSE) Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey()); + continue; + } final AutoFillId id = entry.getKey(); final ViewNode node = findViewNodeByIdLocked(id); if (node == null) { - Slog.w(TAG, "onSaveLocked(): did not find node with id " + id); + Slog.w(TAG, "callSaveLocked(): did not find node with id " + id); continue; } - final AutoFillValue value = entry.getValue(); - if (DEBUG) Slog.d(TAG, "onSaveLocked(): updating " + id + " to " + value); + if (DEBUG) Slog.d(TAG, "callSaveLocked(): updating " + id + " to " + value); + node.updateAutoFillValue(value); } @@ -540,62 +636,77 @@ final class AutoFillManagerServiceImpl { mStructure.dump(); } - mRemoteFillService.onSaveRequest(mStructure, mCurrentResponse.getExtras()); + mRemoteFillService.onSaveRequest(mStructure, extras); } - void onApplicationDataAvailable(AssistStructure structure, IBinder appCallback) { - setAppCallback(appCallback); - mStructure = structure; - // TODO(b/33197203): Need to pipe the bundle - mRemoteFillService.onFillRequest(structure, null); - } + void updateLocked(AutoFillId id, Rect bounds, AutoFillValue value, int flags) { + if (DEBUG) Slog.d(TAG, "updateLocked(): id=" + id + ", flags=" + flags); - private void setAppCallback(IBinder appBinder) { - try { - appBinder.linkToDeath(() -> { - if (DEBUG) Slog.d(TAG, "app callback died"); - // TODO(b/33197203): more cleanup here? - mAppCallback = null; - destroy(); - }, 0); - } catch (RemoteException e) { - Slog.w(TAG, "linkToDeath() failed: " + e); + if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) { + // TODO(b/33197203): ignoring because we don't support partitions yet + if (DEBUG) Slog.d(TAG, "updateLocked(): ignoring " + flags + " after auto-filled"); + return; } - mAppCallback = IAutoFillAppCallback.Stub.asInterface(appBinder); - } - void updateAutoFillInput(int flags, AutoFillId autoFillId, - @Nullable AutoFillValue autoFillValue, @Nullable Rect bounds) { - synchronized (mLock) { - ViewState viewState = mViewStates.get(autoFillId); - if (viewState == null) { - viewState = new ViewState(this); - mViewStates.put(autoFillId, viewState); - } + ViewState viewState = mViewStates.get(id); + if (viewState == null) { + viewState = new ViewState(id, this); + mViewStates.put(id, viewState); + } - if ((flags & FLAG_UPDATE_UI_SHOW) != 0) { - // Remove the UI if the ViewState has changed. - if (mCurrentViewState != viewState) { - mUi.hideFillUi(); - mCurrentViewState = viewState; - } + if ((flags & FLAG_START_SESSION) != 0 ) { + // View is triggering auto-fill. + mCurrentViewState = viewState; + viewState.update(value, bounds); + return; + } - // If the ViewState is ready to be displayed, onReady() will be called. - viewState.update(autoFillValue, bounds); + if ((flags & FLAG_VALUE_CHANGED) != 0 && value != null && + !value.equals(viewState.mAutoFillValue)) { + viewState.mValueUpdated = true; - // TODO(b/33197203): Remove when there is a response per activity. - if (mCurrentResponse != null) { - viewState.setResponse(mCurrentResponse); - } - } else if ((flags & FLAG_UPDATE_UI_HIDE) != 0) { - if (mCurrentViewState == viewState) { - mUi.hideFillUi(); - mCurrentViewState = null; + // Must check if this update was caused by auto-filling the view, in which + // case we just update the value, but not the UI. + if (mAutoFilledDataset != null) { + final AutoFillValue filledValue = findValue(mAutoFilledDataset, id); + if (value.equals(filledValue)) { + viewState.mAutoFillValue = value; + return; } - } else { - Slog.w(TAG, "unknown flags " + flags); } + + // Just change value, don't update the UI + viewState.mAutoFillValue = value; + return; + } + + if ((flags & FLAG_FOCUS_GAINED) != 0) { + // Remove the UI if the ViewState has changed. + if (mCurrentViewState != viewState) { + mUi.hideFillUi(); + mCurrentViewState = viewState; + } + + // If the ViewState is ready to be displayed, onReady() will be called. + viewState.update(value, bounds); + + // TODO(b/33197203): Remove when there is a response per activity. + if (mCurrentResponse != null) { + viewState.setResponse(mCurrentResponse); + } + + return; + } + + if ((flags & FLAG_FOCUS_LOST) != 0) { + if (mCurrentViewState == viewState) { + mUi.hideFillUi(); + mCurrentViewState = null; + } + return; } + + Slog.w(TAG, "unknown flags " + flags); } @Override @@ -609,11 +720,13 @@ final class AutoFillManagerServiceImpl { filterText = text.toString(); } } - getUiForShowing().showFillUi(viewState, response.getDatasets(), bounds, filterText); + + getUiForShowing().showFillUi(mActivityToken, viewState, response.getDatasets(), + bounds, filterText); } private void processResponseLocked(FillResponse response) { - if (DEBUG) Slog.d(TAG, "showResponse(authRequired=" + if (DEBUG) Slog.d(TAG, "processResponseLocked(authRequired=" + response.getAuthentication() +"):" + response); // TODO(b/33197203): add MetricsLogger calls @@ -621,8 +734,8 @@ final class AutoFillManagerServiceImpl { mCurrentResponse = response; if (mCurrentResponse.getAuthentication() != null) { - // ...or handle authentication. - Intent fillInIntent = createAuthFillInIntent(response.getId(), mStructure, + // Handle authentication. + final Intent fillInIntent = createAuthFillInIntent(response.getId(), mStructure, new Bundle(), new FillCallback(new IFillCallback.Stub() { @Override public void onCancellable(ICancellationSignal cancellation) { @@ -639,17 +752,28 @@ final class AutoFillManagerServiceImpl { @Override public void onFailure(CharSequence message) { getUiForShowing().showError(message); - destroy(); + removeSelf(); } })); getUiForShowing().showFillResponseAuthRequest( mCurrentResponse.getAuthentication(), fillInIntent); - } else { - // TODO(b/33197203): Consider using mCurrentResponse, depends on partitioning design - if (mCurrentViewState != null) { - mCurrentViewState.setResponse(mCurrentResponse); - } + return; + } + + final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds(); + if (savableIds == null || savableIds.isEmpty()) { + // NOTE: it's assuming the response has no datasets, since when a dataset is added + // it's view id is automatically added to savable_ids + if (DEBUG) Slog.d(TAG, "processResponseLocked(): nothing to do"); + + removeSelf(); + return; + } + + // TODO(b/33197203): Consider using mCurrentResponse, depends on partitioning design + if (mCurrentViewState != null) { + mCurrentViewState.setResponse(mCurrentResponse); } } @@ -658,8 +782,6 @@ final class AutoFillManagerServiceImpl { // Autofill it directly... if (dataset.getAuthentication() == null) { autoFillApp(dataset); - // For now just show this on every fill - getUiForShowing().showSaveUi(); return; } @@ -675,7 +797,7 @@ final class AutoFillManagerServiceImpl { public void onSuccess(FillResponse response) { mCurrentResponse = createAuthenticatedResponse( mCurrentResponse, response); - Dataset augmentedDataset = Helper.findDatasetById(dataset.getId(), + final Dataset augmentedDataset = Helper.findDatasetById(dataset.getId(), mCurrentResponse); if (augmentedDataset != null) { autoFill(augmentedDataset); @@ -685,7 +807,7 @@ final class AutoFillManagerServiceImpl { @Override public void onFailure(CharSequence message) { getUiForShowing().showError(message); - destroy(); + removeSelf(); } })); @@ -712,24 +834,25 @@ final class AutoFillManagerServiceImpl { } void dumpLocked(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("mId: "); pw.println(mId); - pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken.get()); + pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken); pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse); + pw.print(prefix); pw.print("mAutoFilledDataset: "); pw.println(mAutoFilledDataset); pw.print(prefix); pw.print("mCurrentViewStates: "); pw.println(mCurrentViewState); pw.print(prefix); pw.print("mViewStates: "); pw.println(mViewStates.size()); final String prefix2 = prefix + " "; for (Map.Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) { - pw.print(prefix2); - pw.print(entry.getKey()); pw.print(": " ); pw.println(entry.getValue()); + pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey()); + entry.getValue().dump(prefix2, pw); } - pw.print(prefix); pw.print("mUpdatedValues: "); pw.println(mUpdatedValues); - pw.print(prefix); pw.print("mStructure: " ); - // TODO(b/33197203): add method do dump AssistStructure on pw - if (mStructure != null) { - pw.println("look at logcat" ); - mStructure.dump(); // dumps to logcat - } else { - pw.println("null"); + if (VERBOSE) { + pw.print(prefix); pw.print("mStructure: " ); + // TODO(b/33197203): add method do dump AssistStructure on pw + if (mStructure != null) { + pw.println("look at logcat" ); + mStructure.dump(); // dumps to logcat + } else { + pw.println("null"); + } } mRemoteFillService.dump(prefix, pw); @@ -739,15 +862,27 @@ final class AutoFillManagerServiceImpl { synchronized (mLock) { try { if (DEBUG) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); + mAppCallback.autoFill(dataset); + mAutoFilledDataset = dataset; } catch (RemoteException e) { Slog.w(TAG, "Error auto-filling activity: " + e); } } } + void enableSessionLocked() { + if (DEBUG) Slog.d(TAG, "enableSessionLocked()"); + + try { + mAppCallback.enableSession(); + } catch (RemoteException e) { + Slog.w(TAG, "Error enabling session: " + e); + } + } + private AutoFillUI getUiForShowing() { - mUi.setCallback(this, mId); + mUi.setCallback(this, mActivityToken); return mUi; } @@ -784,12 +919,18 @@ final class AutoFillManagerServiceImpl { return null; } - private void destroy() { + private void destroyLocked() { + mRemoteFillService.destroy(); + mUi.hideAll(); + mUi.setCallback(null, null); + } + + private void removeSelf() { + if (VERBOSE) Slog.v(TAG, "removeSelf()"); + synchronized (mLock) { - mRemoteFillService.destroy(); - mUi.hideAll(); - mUi.setCallback(null, 0); - removeSessionLocked(mId); + destroyLocked(); + mSessions.remove(mActivityToken); } } diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java index 5c6009a8cf0b..201a8890aad0 100644 --- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java +++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java @@ -40,8 +40,6 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand { final PrintWriter pw = getOutPrintWriter(); try { switch (cmd) { - case "fill": - return requestAutoFill(); case "save": return requestSave(); default: @@ -60,20 +58,12 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand { pw.println(" help"); pw.println(" Prints this help text."); pw.println(""); - pw.println(" fill [--user USER_ID]"); - pw.println(" Request provider to auto-fill the top activity. "); pw.println(" save [--user USER_ID]"); pw.println(" Request provider to save contents of the top activity. "); pw.println(""); } } - private int requestAutoFill() throws RemoteException { - final int userId = getUserIdFromArgs(); - mService.requestAutoFillForUser(userId); - return 0; - } - private int requestSave() throws RemoteException { final int userId = getUserIdFromArgs(); mService.requestSaveForUser(userId); diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java index da54d853135b..e9fc0440ba3a 100644 --- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java @@ -15,9 +15,9 @@ */ package com.android.server.autofill; - import static com.android.server.autofill.Helper.DEBUG; +import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -29,7 +29,10 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.graphics.Rect; import android.os.Binder; +import android.os.IBinder; import android.util.ArraySet; +import android.os.Looper; +import android.text.format.DateUtils; import android.util.Slog; import android.view.autofill.Dataset; import android.view.autofill.FillResponse; @@ -40,6 +43,7 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.Toast; +import com.android.internal.os.HandlerCaller; import com.android.server.UiThread; import com.android.server.autofill.AutoFillManagerServiceImpl.ViewState; @@ -51,6 +55,8 @@ import java.io.PrintWriter; // TODO(b/33197203): document exactly what once the auto-fill bar is implemented final class AutoFillUI { private static final String TAG = "AutoFillUI"; + private static final long SNACK_BAR_LIFETIME_MS = 30 * DateUtils.SECOND_IN_MILLIS; + private static final int MSG_HIDE_SNACK_BAR = 1; private static final String EXTRA_AUTH_INTENT_SENDER = "com.android.server.autofill.extra.AUTH_INTENT_SENDER"; @@ -66,17 +72,23 @@ final class AutoFillUI { private AnchoredWindow mFillWindow; private DatasetPicker mFillView; private ViewState mViewState; - private Rect mBounds; - private String mFilterText; private AutoFillUiCallback mCallback; - private int mClientId; + private IBinder mActivityToken; - public interface AutoFillUiCallback { - void authenticate(IntentSender intent, Intent fillInIntent); - void fill(Dataset dataset); - void save(); - } + private final HandlerCaller.Callback mHandlerCallback = (msg) -> { + switch (msg.what) { + case MSG_HIDE_SNACK_BAR: { + hideSnackbarUiThread(); + return; + } + default: { + Slog.w(TAG, "Invalid message: " + msg); + } + } + }; + private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), + mHandlerCallback, true); /** * Custom snackbar UI used for saving autofill or other informational messages. @@ -88,10 +100,10 @@ final class AutoFillUI { mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); } - void setCallback(AutoFillUiCallback callback, int clientId) { + void setCallback(AutoFillUiCallback callback, IBinder activityToken) { hideAll(); mCallback = callback; - mClientId = clientId; + mActivityToken = activityToken; } /** @@ -125,8 +137,6 @@ final class AutoFillUI { } mViewState = null; - mBounds = null; - mFilterText = null; mFillView = null; mFillWindow = null; } @@ -134,19 +144,34 @@ final class AutoFillUI { /** * Shows the fill UI, removing the previous fill UI if the has changed. * + * @param appToken the token of the app to be autofilled * @param viewState the view state, compared by reference to know if new UI should be shown * @param datasets the datasets to show, not used if viewState is the same * @param bounds bounds of the view to be filled, used if changed * @param filterText text of the view to be filled, used if changed */ - void showFillUi(ViewState viewState, ArraySet<Dataset> datasets, Rect bounds, - String filterText) { + void showFillUi(IBinder appToken, ViewState viewState, @Nullable ArraySet<Dataset> datasets, + Rect bounds, String filterText) { if (!hasCallback()) { return; } - hideAll(); + + UiThread.getHandler().runWithScissors(() -> { + hideSnackbarUiThread(); + hideFillResponseAuthUiUiThread(); + }, 0); + + if (datasets == null) { + // TODO(b/33197203): shouldn't be called, but keeping the WTF for a while just to be + // safe, otherwise it would crash system server... + Slog.wtf(TAG, "showFillUI(): no dataset"); + return; + } + UiThread.getHandler().runWithScissors(() -> { - if (mViewState != viewState) { + if (mViewState == null || !mViewState.mId.equals(viewState.mId)) { + hideFillUiUiThread(); + mViewState = viewState; mFillView = new DatasetPicker(mContext, datasets, @@ -158,23 +183,15 @@ final class AutoFillUI { callback.fill(dataset); hideFillUi(); }); - // TODO: No magical numbers - mFillWindow = new AnchoredWindow( - mWm, mFillView, 800, ViewGroup.LayoutParams.WRAP_CONTENT); - if (DEBUG) Slog.d(TAG, "show FillUi"); - } - if (!bounds.equals(mBounds)) { - if (DEBUG) Slog.d(TAG, "update FillUi bounds: " + mBounds); - mBounds = bounds; - mFillWindow.show(mBounds); - } + mFillWindow = new AnchoredWindow(mWm, appToken, mFillView); - if (!filterText.equals(mFilterText)) { - if (DEBUG) Slog.d(TAG, "update FillUi filter text: " + mFilterText); - mFilterText = filterText; - mFillView.update(mFilterText); + if (DEBUG) Slog.d(TAG, "showFillUi(): view changed"); } + + if (DEBUG) Slog.d(TAG, "showFillUi(): bounds=" + bounds + ", filterText=" + filterText); + mFillView.update(filterText); + mFillWindow.show(bounds); }, 0); } @@ -216,6 +233,7 @@ final class AutoFillUI { @Override public void onCancelClick() { + // TODO(b/33197203): add MetricsLogger call hideSnackbarUiThread(); } })); @@ -237,11 +255,9 @@ final class AutoFillUI { pw.println("AufoFill UI"); final String prefix = " "; pw.print(prefix); pw.print("sResultCode: "); pw.println(sResultCode); - pw.print(prefix); pw.print("mClientId: "); pw.println(mClientId); + pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken); pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar); pw.print(prefix); pw.print("mViewState: "); pw.println(mViewState); - pw.print(prefix); pw.print("mBounds: "); pw.println(mBounds); - pw.print(prefix); pw.print("mFilterText: "); pw.println(mFilterText); } //similar to a snackbar, but can be a bit custom since it is more than just text. This will @@ -264,9 +280,16 @@ final class AutoFillUI { mSnackbar = snackBar; mWm.addView(mSnackbar, params); }, 0); + + if (DEBUG) { + Slog.d(TAG, "showSnackbar(): auto dismissing it in " + SNACK_BAR_LIFETIME_MS + " ms"); + } + mHandlerCaller.sendMessageDelayed(mHandlerCaller.obtainMessage(MSG_HIDE_SNACK_BAR), + SNACK_BAR_LIFETIME_MS); } private void hideSnackbarUiThread() { + mHandlerCaller.getHandler().removeMessages(MSG_HIDE_SNACK_BAR); if (mSnackbar != null) { mWm.removeView(mSnackbar); mSnackbar = null; @@ -279,6 +302,12 @@ final class AutoFillUI { } } + interface AutoFillUiCallback { + void authenticate(IntentSender intent, Intent fillInIntent); + void fill(Dataset dataset); + void save(); + } + ///////////////////////////////////////////////////////////////////////////////// // TODO(b/33197203): temporary code using a notification to request auto-fill. // // Will be removed once UX decide the right way to present it to the user. // @@ -345,7 +374,7 @@ final class AutoFillUI { final long identity = Binder.clearCallingIdentity(); try { - NotificationManager.from(mContext).notify(mClientId, notification.build()); + NotificationManager.from(mContext).notify(0, notification.build()); } finally { Binder.restoreCallingIdentity(identity); } @@ -355,7 +384,7 @@ final class AutoFillUI { private void hideFillResponseAuthUiUiThread() { final long identity = Binder.clearCallingIdentity(); try { - NotificationManager.from(mContext).cancel(mClientId); + NotificationManager.from(mContext).cancel(0); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java index 7fff41008866..7400a64c36f8 100644 --- a/services/autofill/java/com/android/server/autofill/Helper.java +++ b/services/autofill/java/com/android/server/autofill/Helper.java @@ -16,11 +16,15 @@ package com.android.server.autofill; +import android.annotation.Nullable; import android.os.Bundle; import android.util.ArraySet; +import android.view.autofill.AutoFillId; +import android.view.autofill.AutoFillValue; import android.view.autofill.Dataset; import android.view.autofill.FillResponse; +import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; import java.util.Set; @@ -55,8 +59,22 @@ final class Helper { return builder.toString(); } - private Helper() { - throw new UnsupportedOperationException("contains static members only"); + /** + * Gets the value of a {@link Dataset} field by its id, or {@code null} if not found. + */ + @Nullable + static AutoFillValue findValue(Dataset dataset, AutoFillId id) { + if (dataset != null) { + final ArrayList<AutoFillId> ids = dataset.getFieldIds(); + final int size = ids.size(); + for (int i = 0; i < size; i++) { + if (id.equals(ids.get(i))) { + return dataset.getFieldValues().get(i); + } + + } + } + return null; } /** @@ -80,4 +98,8 @@ final class Helper { } return null; } + + private Helper() { + throw new UnsupportedOperationException("contains static members only"); + } } diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 22eca77c3a06..08cb1094ae38 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -1297,7 +1297,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return flags; } - InputBindResult attachNewInputLocked(boolean initial) { + InputBindResult attachNewInputLocked( + /* @InputMethodClient.StartInputReason */ final int startInputReason, boolean initial) { if (!mBoundToMethod) { executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO( MSG_BIND_INPUT, mCurMethod, mCurClient.binding)); @@ -1361,12 +1362,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } return startInputUncheckedLocked(cs, inputContext, missingMethods, attribute, - controlFlags); + controlFlags, startInputReason); } InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext, /* @InputConnectionInspector.missingMethods */ final int missingMethods, - @NonNull EditorInfo attribute, int controlFlags) { + @NonNull EditorInfo attribute, int controlFlags, + /* @InputMethodClient.StartInputReason */ final int startInputReason) { // If no method is currently selected, do nothing. if (mCurMethodId == null) { return mNoBinding; @@ -1408,7 +1410,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (cs.curSession != null) { // Fast case: if we are already connected to the input method, // then just return it. - return attachNewInputLocked( + return attachNewInputLocked(startInputReason, (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0); } if (mHaveConnection) { @@ -1549,7 +1551,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub clearClientSessionLocked(mCurClient); mCurClient.curSession = new SessionState(mCurClient, method, session, channel); - InputBindResult res = attachNewInputLocked(true); + InputBindResult res = attachNewInputLocked( + InputMethodClient.START_INPUT_REASON_SESSION_CREATED_BY_IME, true); if (res.method != null) { executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO( MSG_BIND_CLIENT, mCurClient.client, res)); @@ -2289,7 +2292,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (attribute != null) { return startInputUncheckedLocked(cs, inputContext, missingMethods, - attribute, controlFlags); + attribute, controlFlags, startInputReason); } return null; } @@ -2339,7 +2342,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Unspecified window will show input"); if (attribute != null) { res = startInputUncheckedLocked(cs, inputContext, - missingMethods, attribute, controlFlags); + missingMethods, attribute, controlFlags, startInputReason); didStart = true; } showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null); @@ -2365,7 +2368,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Window asks to show input going forward"); if (attribute != null) { res = startInputUncheckedLocked(cs, inputContext, - missingMethods, attribute, controlFlags); + missingMethods, attribute, controlFlags, startInputReason); didStart = true; } showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null); @@ -2375,7 +2378,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Window asks to always show input"); if (attribute != null) { res = startInputUncheckedLocked(cs, inputContext, missingMethods, - attribute, controlFlags); + attribute, controlFlags, startInputReason); didStart = true; } showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null); @@ -2384,7 +2387,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!didStart && attribute != null) { res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute, - controlFlags); + controlFlags, startInputReason); } } } finally { diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 4ab894f05126..42eb958bba0b 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -17,6 +17,7 @@ package com.android.server; import android.app.ActivityManager; +import android.annotation.NonNull; import android.content.pm.PackageManagerInternal; import com.android.internal.content.PackageMonitor; import com.android.internal.location.ProviderProperties; @@ -62,6 +63,7 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.IBatchedLocationCallback; import android.location.IGnssMeasurementsListener; import android.location.IGnssStatusListener; import android.location.IGnssStatusProvider; @@ -101,6 +103,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; /** @@ -142,7 +145,7 @@ public class LocationManagerService extends ILocationManager.Stub { private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000; // default background throttling interval if not overriden in settings - private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 10 * 60 * 1000; + private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000; // Location Providers may sometimes deliver location updates // slightly faster that requested - provide grace period so @@ -229,6 +232,11 @@ public class LocationManagerService extends ILocationManager.Stub { private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider; + private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider; + private IBatchedLocationCallback mGnssBatchingCallback; + private LinkedCallback mGnssBatchingDeathCallback; + private boolean mGnssBatchingInProgress = false; + public LocationManagerService(Context context) { super(); mContext = context; @@ -545,6 +553,7 @@ public class LocationManagerService extends ILocationManager.Stub { GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this, mLocationHandler.getLooper()); mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider(); + mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider(); mGnssStatusProvider = gnssProvider.getGnssStatusProvider(); mNetInitiatedListener = gnssProvider.getNetInitiatedListener(); addProviderLocked(gnssProvider); @@ -1073,13 +1082,197 @@ public class LocationManagerService extends ILocationManager.Stub { */ @Override public int getGnssYearOfHardware() { - if (mGnssNavigationMessageProvider != null) { + if (mGnssSystemInfoProvider != null) { return mGnssSystemInfoProvider.getGnssYearOfHardware(); } else { return 0; } } + /** + * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly + * (try to) access GNSS information at this layer. + */ + private boolean hasGnssPermissions(String packageName) { + int allowedResolutionLevel = getCallerAllowedResolutionLevel(); + checkResolutionLevelIsSufficientForProviderUse( + allowedResolutionLevel, + LocationManager.GPS_PROVIDER); + + int pid = Binder.getCallingPid(); + int uid = Binder.getCallingUid(); + long identity = Binder.clearCallingIdentity(); + boolean hasLocationAccess; + try { + hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel); + } finally { + Binder.restoreCallingIdentity(identity); + } + + return hasLocationAccess; + } + + /** + * Returns the GNSS batching size, if available. + */ + @Override + public int getGnssBatchSize(String packageName) { + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to access hardware batching"); + + if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) { + return mGnssBatchingProvider.getSize(); + } else { + return 0; + } + } + + /** + * Adds a callback for GNSS Batching events, if permissions allow, which are transported + * to potentially multiple listeners by the BatchedLocationCallbackTransport above this. + */ + @Override + public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) { + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to access hardware batching"); + + if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) { + return false; + } + + mGnssBatchingCallback = callback; + mGnssBatchingDeathCallback = new LinkedCallback(callback); + try { + callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */); + } catch (RemoteException e) { + // if the remote process registering the listener is already dead, just swallow the + // exception and return + Log.e(TAG, "Remote listener already died.", e); + return false; + } + + return true; + } + + private class LinkedCallback implements IBinder.DeathRecipient { + private final IBatchedLocationCallback mCallback; + + public LinkedCallback(@NonNull IBatchedLocationCallback callback) { + mCallback = callback; + } + + @NonNull + public IBatchedLocationCallback getUnderlyingListener() { + return mCallback; + } + + @Override + public void binderDied() { + Log.d(TAG, "Remote Batching Callback died: " + mCallback); + stopGnssBatch(); + removeGnssBatchingCallback(); + } + } + + /** + * Removes callback for GNSS batching + */ + @Override + public void removeGnssBatchingCallback() { + try { + mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback, + 0 /* flags */); + } catch (NoSuchElementException e) { + // if the death callback isn't connected (it should be...), log error, swallow the + // exception and return + Log.e(TAG, "Couldn't unlink death callback.", e); + } + mGnssBatchingCallback = null; + mGnssBatchingDeathCallback = null; + } + + + /** + * Starts GNSS batching, if available. + */ + @Override + public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) { + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to access hardware batching"); + + if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) { + return false; + } + + if (mGnssBatchingInProgress) { + // Current design does not expect multiple starts to be called repeatedly + Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch"); + // Try to clean up anyway, and continue + stopGnssBatch(); + } + + mGnssBatchingInProgress = true; + return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull); + } + + /** + * Flushes a GNSS batch in progress + */ + @Override + public void flushGnssBatch(String packageName) { + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to access hardware batching"); + + if (!hasGnssPermissions(packageName)) { + Log.e(TAG, "flushGnssBatch called without GNSS permissions"); + return; + } + + if (!mGnssBatchingInProgress) { + Log.w(TAG, "flushGnssBatch called with no batch in progress"); + } + + if (mGnssBatchingProvider != null) { + mGnssBatchingProvider.flush(); + } + } + + /** + * Stops GNSS batching + */ + @Override + public boolean stopGnssBatch() { + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to access hardware batching"); + + if (mGnssBatchingProvider != null) { + mGnssBatchingInProgress = false; + return mGnssBatchingProvider.stop(); + } else { + return false; + } + } + + @Override + public void reportLocationBatch(List<Location> locations) { + checkCallerIsProvider(); + + // Currently used only for GNSS locations - update permissions check if changed + if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) { + if (mGnssBatchingCallback == null) { + Slog.e(TAG, "reportLocationBatch() called without active Callback"); + return; + } + try { + mGnssBatchingCallback.onLocationBatch(locations); + } catch (RemoteException e) { + Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e); + } + } else { + Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked"); + } + } + private void addProviderLocked(LocationProviderInterface provider) { mProviders.add(provider); mProvidersByName.put(provider.getName(), provider); @@ -2000,22 +2193,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) { - int allowedResolutionLevel = getCallerAllowedResolutionLevel(); - checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, - LocationManager.GPS_PROVIDER); - - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - try { - if (!checkLocationAccess(pid, uid, packageName, allowedResolutionLevel)) { - return false; - } - } finally { - Binder.restoreCallingIdentity(ident); - } - - if (mGnssStatusProvider == null) { + if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) { return false; } @@ -2043,22 +2221,7 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean addGnssMeasurementsListener( IGnssMeasurementsListener listener, String packageName) { - int allowedResolutionLevel = getCallerAllowedResolutionLevel(); - checkResolutionLevelIsSufficientForProviderUse( - allowedResolutionLevel, - LocationManager.GPS_PROVIDER); - - int pid = Binder.getCallingPid(); - int uid = Binder.getCallingUid(); - long identity = Binder.clearCallingIdentity(); - boolean hasLocationAccess; - try { - hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel); - } finally { - Binder.restoreCallingIdentity(identity); - } - - if (!hasLocationAccess || mGnssMeasurementsProvider == null) { + if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { return false; } return mGnssMeasurementsProvider.addListener(listener); @@ -2075,22 +2238,7 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean addGnssNavigationMessageListener( IGnssNavigationMessageListener listener, String packageName) { - int allowedResolutionLevel = getCallerAllowedResolutionLevel(); - checkResolutionLevelIsSufficientForProviderUse( - allowedResolutionLevel, - LocationManager.GPS_PROVIDER); - - int pid = Binder.getCallingPid(); - int uid = Binder.getCallingUid(); - long identity = Binder.clearCallingIdentity(); - boolean hasLocationAccess; - try { - hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel); - } finally { - Binder.restoreCallingIdentity(identity); - } - - if (!hasLocationAccess || mGnssNavigationMessageProvider == null) { + if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) { return false; } return mGnssNavigationMessageProvider.addListener(listener); @@ -2866,6 +3014,9 @@ public class LocationManagerService extends ILocationManager.Stub { pw.println(":"); provider.dump(fd, pw, args); } + if (mGnssBatchingInProgress) { + pw.println(" GNSS batching in progress"); + } } } } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index fdd7cb139204..fbc444026539 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -636,11 +636,10 @@ public class AccountManagerService return visibility; } - if (isPermittedForPackage(packageName, accounts.userId, - Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) { - return AccountManager.VISIBILITY_VISIBLE; - } - // Profile owner gets visibility by default. + boolean isPrivileged = isPermittedForPackage(packageName, accounts.userId, + Manifest.permission.GET_ACCOUNTS_PRIVILEGED); + + // Device/Profile owner gets visibility by default. if (isProfileOwner(uid)) { return AccountManager.VISIBILITY_VISIBLE; } @@ -650,7 +649,7 @@ public class AccountManagerService boolean preO = isPreOApplication(packageName); if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH) || (preO && checkGetAccountsPermission(packageName, accounts.userId)) - || canReadContacts) { + || canReadContacts || isPrivileged) { // Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature // match. visibility = getAccountVisibility(account, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d75048d25eba..93fb9114beba 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -701,18 +701,15 @@ public class ActivityManagerService extends IActivityManager.Stub public AssistStructure structure = null; public AssistContent content = null; public Bundle receiverExtras; - public int resultCode; public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent, - String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _resultCode, - int _userHandle) { + String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _userHandle) { activity = _activity; extras = _extras; intent = _intent; hint = _hint; receiver = _receiver; receiverExtras = _receiverExtras; - resultCode = _resultCode; userHandle = _userHandle; } @Override @@ -1627,10 +1624,6 @@ public class ActivityManagerService extends IActivityManager.Stub int mThumbnailHeight; float mFullscreenThumbnailScale; - /** The aspect ratio bounds of the PIP. */ - float mMinPipAspectRatio; - float mMaxPipAspectRatio; - final ServiceThread mHandlerThread; final MainHandler mHandler; final UiHandler mUiHandler; @@ -7665,12 +7658,13 @@ public class ActivityManagerService extends IActivityManager.Stub r.pictureInPictureArgs.copyOnlySet(args); final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); - final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio) - ? mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio) - : mWindowManager.getPictureInPictureDefaultBounds(DEFAULT_DISPLAY); + final Rect bounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, + aspectRatio); mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode", bounds, true /* moveHomeStackToFront */); - mStackSupervisor.getStack(PINNED_STACK_ID).setPictureInPictureActions(actions); + final ActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID); + stack.setPictureInPictureAspectRatio(aspectRatio); + stack.setPictureInPictureActions(actions); MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_ENTERED, r.supportsPictureInPictureWhilePausing); @@ -7747,10 +7741,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - private boolean isValidPictureInPictureAspectRatio(float aspectRatio) { - return mMinPipAspectRatio <= aspectRatio && aspectRatio <= mMaxPipAspectRatio; - } - /** * Checks the state of the system and the activity associated with the given {@param token} to * verify that picture-in-picture is supported for that activity. @@ -7781,10 +7771,15 @@ public class ActivityManagerService extends IActivityManager.Stub } if (args.hasSetAspectRatio() - && !isValidPictureInPictureAspectRatio(args.getAspectRatio())) { + && !mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId, + args.getAspectRatio())) { + final float minAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); + final float maxAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio); throw new IllegalArgumentException(String.format(caller + ": Aspect ratio is too extreme (must be between %f and %f).", - mMinPipAspectRatio, mMaxPipAspectRatio)); + minAspectRatio, maxAspectRatio)); } if (args.hasSetActions() @@ -12457,7 +12452,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public Bundle getAssistContextExtras(int requestType) { PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null, - null, 0, null, true /* focused */, true /* newSessionId */, + null, null, true /* focused */, true /* newSessionId */, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT); if (pae == null) { return null; @@ -12524,29 +12519,29 @@ public class ActivityManagerService extends IActivityManager.Stub public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId) { return enqueueAssistContext(requestType, null, null, receiver, receiverExtras, - 0, activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null, + activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT) != null; } @Override public boolean requestAutoFillData(IResultReceiver receiver, Bundle receiverExtras, - int resultCode, IBinder activityToken) { + IBinder activityToken) { // NOTE: we could always use ActivityManager.ASSIST_CONTEXT_FULL and let ActivityThread // rely on the flags to decide whether the handleRequestAssistContextExtras() is for // auto-fill, but it's safer to explicitly use new AutoFill types, in case the Assist // requests use flags in the future as well (since their flags value might collide with the // auto-fill flag values). return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTO_FILL, null, null, - receiver, receiverExtras, resultCode, activityToken, true, true, - UserHandle.getCallingUserId(), null, - PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT) != null; + receiver, receiverExtras, activityToken, true, true, UserHandle.getCallingUserId(), + null, PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT) != null; } private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint, - IResultReceiver receiver, Bundle receiverExtras, int resultCode, IBinder activityToken, + IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout) { enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO, "enqueueAssistContext()"); + synchronized (this) { ActivityRecord activity = getFocusedStack().topActivity(); if (activity == null) { @@ -12582,8 +12577,10 @@ public class ActivityManagerService extends IActivityManager.Stub } extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName); extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid); + pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras, - resultCode, userHandle); + userHandle); + // Increment the sessionId if necessary if (newSessionId) { mViSessionId++; @@ -12666,15 +12663,11 @@ public class ActivityManagerService extends IActivityManager.Stub sendBundle.putParcelable(VoiceInteractionSession.KEY_CONTENT, pae.content); sendBundle.putBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS, pae.receiverExtras); - IBinder cb = extras.getBinder(AutoFillService.KEY_CALLBACK); - if (cb != null) { - sendBundle.putBinder(AutoFillService.KEY_CALLBACK, cb); - } } } if (sendReceiver != null) { try { - sendReceiver.send(pae.resultCode, sendBundle); + sendReceiver.send(0, sendBundle); } catch (RemoteException e) { } return; @@ -12699,7 +12692,7 @@ public class ActivityManagerService extends IActivityManager.Stub public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle, Bundle args) { - return enqueueAssistContext(requestType, intent, hint, null, null, 0, null, + return enqueueAssistContext(requestType, intent, hint, null, null, null, true /* focused */, true /* newSessionId */, userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT) != null; } @@ -13469,10 +13462,6 @@ public class ActivityManagerService extends IActivityManager.Stub com.android.internal.R.dimen.thumbnail_width); mThumbnailHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.thumbnail_height); - mMinPipAspectRatio = res.getFloat( - com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); - mMaxPipAspectRatio = res.getFloat( - com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio); mAppErrors.loadAppsNotReportingCrashesFromConfigLocked(res.getString( com.android.internal.R.string.config_appsNotReportingCrashes)); mUserController.mUserSwitchUiEnabled = !res.getBoolean( @@ -22739,13 +22728,6 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public IBinder getTopVisibleActivity(int uid) { - synchronized (ActivityManagerService.this) { - return mStackSupervisor.getTopVisibleActivity(uid); - } - } - - @Override public void notifyDockedStackMinimizedChanged(boolean minimized) { synchronized (ActivityManagerService.this) { mStackSupervisor.setDockedStackMinimized(minimized); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index ba2512020ad3..104fc6a6e565 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -544,6 +544,10 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL mWindowContainerController.setPictureInPictureAspectRatio(aspectRatio); } + void setPictureInPictureActions(List<RemoteAction> actions) { + mWindowContainerController.setPictureInPictureActions(actions); + } + void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds, Rect outTempInsetBounds, boolean ignoreVisibility) { mWindowContainerController.getStackDockedModeBounds(outBounds, outTempBounds, @@ -554,10 +558,6 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL mWindowContainerController.prepareFreezingTaskBounds(); } - void setPictureInPictureActions(List<RemoteAction> actions) { - mWindowContainerController.setPictureInPictureActions(actions); - } - void getWindowContainerBounds(Rect outBounds) { if (mWindowContainerController != null) { mWindowContainerController.getBounds(outBounds); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index da7dc7d8b0ee..e954363a936b 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -4913,24 +4913,4 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } return topActivityTokens; } - - public IBinder getTopVisibleActivity(int uid) { - // TODO(b/33197203): get rid of DEFAULT_DISPLAY here?. Used in - // VoiceInteractionManagerServiceImpl#showSessionLocked. - final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY); - if (display == null) { - return null; - } - final ArrayList<ActivityStack> stacks = display.mStacks; - for (int i = stacks.size() - 1; i >= 0; i--) { - ActivityStack stack = stacks.get(i); - if (stack.getStackVisibilityLocked(null) == ActivityStack.STACK_VISIBLE) { - ActivityRecord top = stack.topActivity(); - if (top != null && stack == mFocusedStack && top.app.uid == uid) { - return top.appToken; - } - } - } - return null; - } } diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index eb8f8fc9af96..17b005d8c890 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -72,7 +72,6 @@ import android.os.WorkSource; import android.provider.Settings; import android.provider.Telephony.Carriers; import android.provider.Telephony.Sms.Intents; -import android.telephony.SmsMessage; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyManager; @@ -82,17 +81,17 @@ import android.text.TextUtils; import android.util.Log; import android.util.NtpTrustedTime; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; -import java.io.StringReader; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.List; import java.util.Map.Entry; import java.util.Properties; import java.util.Map; @@ -411,7 +410,6 @@ public class GnssLocationProvider implements LocationProviderInterface { private WorkSource mClientSource = new WorkSource(); private GeofenceHardwareImpl mGeofenceHardwareImpl; - private int mYearOfHardware = 0; // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL @@ -1125,6 +1123,7 @@ public class GnssLocationProvider implements LocationProviderInterface { mGnssMeasurementsProvider.onGpsEnabledChanged(); mGnssNavigationMessageProvider.onGpsEnabledChanged(); + enableBatching(); } else { synchronized (mLock) { mEnabled = false; @@ -1156,6 +1155,7 @@ public class GnssLocationProvider implements LocationProviderInterface { mAlarmManager.cancel(mWakeupIntent); mAlarmManager.cancel(mTimeoutIntent); + disableBatching(); // do this before releasing wakelock native_cleanup(); @@ -1791,6 +1791,84 @@ public class GnssLocationProvider implements LocationProviderInterface { }; } + public interface GnssBatchingProvider { + /** + * Returns the GNSS batching size + */ + int getSize(); + /** + * Starts the hardware batching operation + */ + boolean start(long periodNanos, boolean wakeOnFifoFull); + /** + * Forces a flush of existing locations from the hardware batching + */ + void flush(); + /** + * Stops the batching operation + */ + boolean stop(); + } + + /** + * @hide + */ + public GnssBatchingProvider getGnssBatchingProvider() { + return new GnssBatchingProvider() { + @Override + public int getSize() { + return native_get_batch_size(); + } + @Override + public boolean start(long periodNanos, boolean wakeOnFifoFull) { + if (periodNanos <= 0) { + Log.e(TAG, "Invalid periodNanos " + periodNanos + + "in batching request, not started"); + return false; + } + return native_start_batch(periodNanos, wakeOnFifoFull); + } + @Override + public void flush() { + native_flush_batch(); + } + @Override + public boolean stop() { + return native_stop_batch(); + } + }; + } + + /** + * Initialize Batching if enabled + */ + private void enableBatching() { + if (!native_init_batching()) { + Log.e(TAG, "Failed to initialize GNSS batching"); + }; + } + + /** + * Disable batching + */ + private void disableBatching() { + native_stop_batch(); + native_cleanup_batching(); + } + + /** + * called from native code - GNSS location batch callback + */ + private void reportLocationBatch(Location[] locationArray) { + List<Location> locations = new ArrayList<>(Arrays.asList(locationArray)); + if(DEBUG) { Log.d(TAG, "Location batch of size " + locationArray.length + "reported"); } + try { + mILocationManager.reportLocationBatch(locations); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException calling reportLocationBatch"); + } + } + /** * called from native code to request XTRA data */ @@ -2117,7 +2195,10 @@ public class GnssLocationProvider implements LocationProviderInterface { // note that this assumes the message will not be removed from the queue before // it is handled (otherwise the wake lock would be leaked). mWakeLock.acquire(); - Log.i(TAG, "WakeLock acquired by sendMessage(" + message + ", " + arg + ", " + obj + ")"); + if (Log.isLoggable(TAG, Log.INFO)) { + Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg + + ", " + obj + ")"); + } mHandler.obtainMessage(message, arg, 1, obj).sendToTarget(); } @@ -2175,8 +2256,10 @@ public class GnssLocationProvider implements LocationProviderInterface { if (msg.arg2 == 1) { // wakelock was taken for this message, release it mWakeLock.release(); - Log.i(TAG, "WakeLock released by handleMessage(" + message + ", " + msg.arg1 + ", " - + msg.obj + ")"); + if (Log.isLoggable(TAG, Log.INFO)) { + Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message) + + ", " + msg.arg1 + ", " + msg.obj + ")"); + } } } @@ -2424,6 +2507,40 @@ public class GnssLocationProvider implements LocationProviderInterface { } } + /** + * @return A string representing the given message ID. + */ + private String messageIdAsString(int message) { + switch (message) { + case ENABLE: + return "ENABLE"; + case SET_REQUEST: + return "SET_REQUEST"; + case UPDATE_NETWORK_STATE: + return "UPDATE_NETWORK_STATE"; + case REQUEST_SUPL_CONNECTION: + return "REQUEST_SUPL_CONNECTION"; + case RELEASE_SUPL_CONNECTION: + return "RELEASE_SUPL_CONNECTION"; + case INJECT_NTP_TIME: + return "INJECT_NTP_TIME"; + case DOWNLOAD_XTRA_DATA: + return "DOWNLOAD_XTRA_DATA"; + case INJECT_NTP_TIME_FINISHED: + return "INJECT_NTP_TIME_FINISHED"; + case DOWNLOAD_XTRA_DATA_FINISHED: + return "DOWNLOAD_XTRA_DATA_FINISHED"; + case UPDATE_LOCATION: + return "UPDATE_LOCATION"; + case SUBSCRIPTION_OR_SIM_CHANGED: + return "SUBSCRIPTION_OR_SIM_CHANGED"; + case INITIALIZE_HANDLER: + return "INITIALIZE_HANDLER"; + default: + return "<Unknown>"; + } + } + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { StringBuilder s = new StringBuilder(); @@ -2441,7 +2558,9 @@ public class GnssLocationProvider implements LocationProviderInterface { if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES "); s.append(")\n"); - s.append(native_get_internal_state()); + s.append(" internal state: ").append(native_get_internal_state()); + s.append("\n"); + pw.append(s); } @@ -2562,4 +2681,12 @@ public class GnssLocationProvider implements LocationProviderInterface { private static native boolean native_set_gps_lock(int gpsLock); private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn); + // GNSS Batching + private static native int native_get_batch_size(); + private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull); + private static native void native_flush_batch(); + private static native boolean native_stop_batch(); + private static native boolean native_init_batching(); + private static native void native_cleanup_batching(); + } diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index d301463db164..0a1574b730a9 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -474,11 +474,12 @@ public class UserRestrictionsUtils { } break; case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES: - if (newValue) { - android.provider.Settings.Secure.putIntForUser(cr, - android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, 0, - userId); - } + // Since Android O, the secure setting is not available to be changed by the + // user. Hence, when the restriction is cleared, we need to reset the state of + // the setting to its default value which is now 1. + android.provider.Settings.Secure.putIntForUser(cr, + android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, + newValue ? 0 : 1, userId); break; case UserManager.DISALLOW_RUN_IN_BACKGROUND: if (newValue) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c795676eddcf..3e051571aab0 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -149,6 +149,7 @@ import android.hardware.display.DisplayManager; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; +import android.hardware.input.InputManager; import android.hardware.input.InputManagerInternal; import android.hardware.power.V1_0.PowerHint; import android.media.AudioAttributes; @@ -203,6 +204,7 @@ import android.view.KeyCharacterMap; import android.view.KeyCharacterMap.FallbackAction; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.PointerIcon; import android.view.Surface; import android.view.View; import android.view.ViewConfiguration; @@ -4246,6 +4248,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(), INPUT_CONSUMER_NAVIGATION, (channel, looper) -> new HideNavInputEventReceiver(channel, looper)); + // As long as mInputConsumer is active, hover events are not dispatched to the app + // and the pointer icon is likely to become stale. Hide it to avoid confusion. + InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL); } // For purposes of positioning and showing the nav bar, if we have diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 596c3d81dcfe..a872ea4602bb 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -22,7 +22,6 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import android.animation.ValueAnimator; import android.app.RemoteAction; import android.content.pm.ParceledListSlice; import android.content.res.Resources; @@ -42,7 +41,6 @@ import android.view.Gravity; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; -import com.android.internal.policy.PipMotionHelper; import com.android.internal.policy.PipSnapAlgorithm; import com.android.server.UiThread; @@ -51,7 +49,20 @@ import java.util.ArrayList; import java.util.List; /** - * Holds the common state of the pinned stack between the system and SystemUI. + * Holds the common state of the pinned stack between the system and SystemUI. If SystemUI ever + * needs to be restarted, it will be notified with the last known state. + * + * Changes to the pinned stack also flow through this controller, and generally, the system only + * changes the pinned stack bounds through this controller in two ways: + * + * 1) When first entering PiP: the controller returns the valid bounds given, taking aspect ratio + * and IME state into account. + * 2) When rotating the device: the controller calculates the new bounds in the new orientation, + * taking the minimized and IME state into account. In this case, we currently ignore the + * SystemUI adjustments (ie. expanded for menu, interaction, etc). + * + * Other changes in the system, including adjustment of IME, configuration change, and more are + * handled by SystemUI (similar to the docked stack divider). */ class PinnedStackController { @@ -67,18 +78,15 @@ class PinnedStackController { private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback(); private final PipSnapAlgorithm mSnapAlgorithm; - private final PipMotionHelper mMotionHelper; // States that affect how the PIP can be manipulated - private boolean mInInteractiveMode; private boolean mIsMinimized; - private boolean mIsSnappingToEdge; private boolean mIsImeShowing; private int mImeHeight; - private ValueAnimator mBoundsAnimator = null; - // The set of actions that are currently allowed on the PiP activity + // The set of actions and aspect-ratio for the that are currently allowed on the PiP activity private ArrayList<RemoteAction> mActions = new ArrayList<>(); + private float mAspectRatio = -1f; // Used to calculate stack bounds across rotations private final DisplayInfo mDisplayInfo = new DisplayInfo(); @@ -89,6 +97,10 @@ class PinnedStackController { private Size mDefaultStackSize; private Point mScreenEdgeInsets; + // The aspect ratio bounds of the PIP. + private float mMinAspectRatio; + private float mMaxAspectRatio; + // Temp vars for calculation private final DisplayMetrics mTmpMetrics = new DisplayMetrics(); private final Rect mTmpInsets = new Rect(); @@ -100,31 +112,12 @@ class PinnedStackController { private class PinnedStackControllerCallback extends IPinnedStackController.Stub { @Override - public void setInInteractiveMode(final boolean inInteractiveMode) { - mHandler.post(() -> { - // Cancel any existing animations on the PIP once the user starts dragging it - if (mBoundsAnimator != null && inInteractiveMode) { - mBoundsAnimator.cancel(); - } - mInInteractiveMode = inInteractiveMode; - }); - } - - @Override public void setIsMinimized(final boolean isMinimized) { mHandler.post(() -> { mIsMinimized = isMinimized; mSnapAlgorithm.setMinimized(isMinimized); }); } - - @Override - public void setSnapToEdge(final boolean snapToEdge) { - mHandler.post(() -> { - mIsSnappingToEdge = snapToEdge; - mSnapAlgorithm.setSnapToEdge(snapToEdge); - }); - } } /** @@ -135,7 +128,6 @@ class PinnedStackController { @Override public void binderDied() { // Clean up the state if the listener dies - mInInteractiveMode = false; mPinnedStackListener = null; } } @@ -144,13 +136,13 @@ class PinnedStackController { mService = service; mDisplayContent = displayContent; mSnapAlgorithm = new PipSnapAlgorithm(service.mContext); - mMotionHelper = new PipMotionHelper(UiThread.getHandler()); mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo()); reloadResources(); } void onConfigurationChanged() { reloadResources(); + notifyMovementBoundsChanged(false /* fromImeAdjustment */); } /** @@ -169,6 +161,10 @@ class PinnedStackController { dpToPx(defaultSizeDp.getHeight(), mTmpMetrics)); mScreenEdgeInsets = new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics), dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics)); + mMinAspectRatio = res.getFloat( + com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); + mMaxAspectRatio = res.getFloat( + com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio); } /** @@ -179,20 +175,29 @@ class PinnedStackController { listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0); listener.onListenerRegistered(mCallbacks); mPinnedStackListener = listener; - notifyBoundsChanged(mIsImeShowing); - notifyMinimizeChanged(mIsMinimized); - notifySnapToEdgeChanged(mIsSnappingToEdge); + notifyImeVisibilityChanged(mIsImeShowing, mImeHeight); + // The movement bounds notification needs to be sent before the minimized state, since + // SystemUI may use the bounds to retore the minimized position + notifyMovementBoundsChanged(false /* fromImeAdjustment */); notifyActionsChanged(mActions); + notifyMinimizeChanged(mIsMinimized); } catch (RemoteException e) { Log.e(TAG, "Failed to register pinned stack listener", e); } } /** + * @return whether the given {@param aspectRatio} is valid. + */ + public boolean isValidPictureInPictureAspectRatio(float aspectRatio) { + return mMinAspectRatio <= aspectRatio && aspectRatio <= mMaxAspectRatio; + } + + /** * Returns the current bounds (or the default bounds if there are no current bounds) with the * specified aspect ratio. */ - Rect getAspectRatioBounds(Rect stackBounds, float aspectRatio) { + Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio) { // Save the snap fraction, calculate the aspect ratio based on the current bounds final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds)); @@ -236,27 +241,20 @@ class PinnedStackController { final Rect movementBounds = new Rect(); getInsetBounds(movementBounds); - // Adjust the right/bottom to ensure the stack bounds never goes offscreen - movementBounds.right = Math.max(movementBounds.left, movementBounds.right - - stackBounds.width()); - movementBounds.bottom = Math.max(movementBounds.top, movementBounds.bottom - - stackBounds.height()); - // Apply the movement bounds adjustments based on the current state - if (adjustForIme) { - if (mIsImeShowing) { - movementBounds.bottom -= mImeHeight; - } - } + mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds, + (adjustForIme && mIsImeShowing) ? mImeHeight : 0); return movementBounds; } /** + * @param preChangeTargetBounds The final bounds of the stack if it is currently animating * @return the repositioned PIP bounds given it's pre-change bounds, and the new display * content. */ - Rect onDisplayChanged(Rect preChangeStackBounds, DisplayContent displayContent) { - final Rect postChangeStackBounds = new Rect(preChangeStackBounds); + Rect onDisplayChanged(Rect preChangeStackBounds, Rect preChangeTargetBounds, + DisplayContent displayContent) { + final Rect postChangeStackBounds = new Rect(preChangeTargetBounds); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); if (!mDisplayInfo.equals(displayInfo)) { // Calculate the snap fraction of the current stack along the old movement bounds, and @@ -277,6 +275,7 @@ class PinnedStackController { mSnapAlgorithm.applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds, displaySize, mStableInsets); } + notifyMovementBoundsChanged(false /* fromImeAdjustment */); } return postChangeStackBounds; } @@ -290,42 +289,19 @@ class PinnedStackController { return; } - final Rect stackBounds = new Rect(); - mService.getStackBounds(PINNED_STACK_ID, stackBounds); - final Rect prevMovementBounds = getMovementBounds(stackBounds); mIsImeShowing = adjustedForIme; mImeHeight = imeHeight; - if (mInInteractiveMode) { - // If the user is currently interacting with the PIP and the ime state changes, then - // don't adjust the bounds and defer that to after the interaction - notifyBoundsChanged(adjustedForIme /* adjustedForIme */); - } else { - // Otherwise, we can move the PIP to a sane location to ensure that it does not block - // the user from interacting with the IME - final Rect movementBounds = getMovementBounds(stackBounds); - final Rect toBounds = new Rect(stackBounds); - if (adjustedForIme) { - // IME visible - if (stackBounds.top == prevMovementBounds.bottom) { - // If the PIP is resting on top of the IME, then adjust it with the hiding IME - toBounds.offsetTo(toBounds.left, movementBounds.bottom); - } else { - toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top)); - } - } else { - // IME hidden - if (stackBounds.top == prevMovementBounds.bottom) { - // If the PIP is resting on top of the IME, then adjust it with the hiding IME - toBounds.offsetTo(toBounds.left, movementBounds.bottom); - } - } - if (!toBounds.equals(stackBounds)) { - if (mBoundsAnimator != null) { - mBoundsAnimator.cancel(); - } - mBoundsAnimator = mMotionHelper.createAnimationToBounds(stackBounds, toBounds); - mBoundsAnimator.start(); - } + notifyImeVisibilityChanged(adjustedForIme, imeHeight); + notifyMovementBoundsChanged(true /* fromImeAdjustment */); + } + + /** + * Sets the current aspect ratio. + */ + void setAspectRatio(float aspectRatio) { + if (Float.compare(mAspectRatio, aspectRatio) != 0) { + mAspectRatio = aspectRatio; + notifyMovementBoundsChanged(false /* fromImeAdjustment */); } } @@ -341,12 +317,12 @@ class PinnedStackController { } /** - * Notifies listeners that the PIP movement bounds have changed. + * Notifies listeners that the PIP needs to be adjusted for the IME. */ - private void notifyBoundsChanged(boolean adjustedForIme) { + private void notifyImeVisibilityChanged(boolean imeVisible, int imeHeight) { if (mPinnedStackListener != null) { try { - mPinnedStackListener.onBoundsChanged(adjustedForIme); + mPinnedStackListener.onImeVisibilityChanged(imeVisible, imeHeight); } catch (RemoteException e) { Slog.e(TAG_WM, "Error delivering bounds changed event.", e); } @@ -367,25 +343,32 @@ class PinnedStackController { } /** - * Notifies listeners that the PIP snap-to-edge state has changed. + * Notifies listeners that the PIP actions have changed. */ - private void notifySnapToEdgeChanged(boolean isSnappingToEdge) { + private void notifyActionsChanged(List<RemoteAction> actions) { if (mPinnedStackListener != null) { try { - mPinnedStackListener.onSnapToEdgeStateChanged(isSnappingToEdge); + mPinnedStackListener.onActionsChanged(new ParceledListSlice(actions)); } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering snap-to-edge changed event.", e); + Slog.e(TAG_WM, "Error delivering actions changed event.", e); } } } /** - * Notifies listeners that the PIP actions have changed. + * Notifies listeners that the PIP movement bounds have changed. */ - private void notifyActionsChanged(List<RemoteAction> actions) { + private void notifyMovementBoundsChanged(boolean fromImeAdjustement) { if (mPinnedStackListener != null) { try { - mPinnedStackListener.onActionsChanged(new ParceledListSlice(actions)); + Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + Rect normalBounds = getDefaultBounds(); + if (isValidPictureInPictureAspectRatio(mAspectRatio)) { + transformBoundsToAspectRatio(normalBounds, mAspectRatio); + } + mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, + fromImeAdjustement); } catch (RemoteException e) { Slog.e(TAG_WM, "Error delivering actions changed event.", e); } @@ -418,7 +401,6 @@ class PinnedStackController { pw.print(prefix + " movementBounds="); getMovementBounds(mTmpRect).printShortString(pw); pw.println(); pw.println(prefix + " mIsImeShowing=" + mIsImeShowing); - pw.println(prefix + " mInInteractiveMode=" + mInInteractiveMode); pw.println(prefix + " mIsMinimized=" + mIsMinimized); if (mActions.isEmpty()) { pw.println(prefix + " mActions=[]"); diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java index e2ea2c53a318..36d07e01e5c1 100644 --- a/services/core/java/com/android/server/wm/StackWindowController.java +++ b/services/core/java/com/android/server/wm/StackWindowController.java @@ -216,7 +216,28 @@ public class StackWindowController final int displayId = mContainer.getDisplayContent().getDisplayId(); final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio); - animateResizePinnedStack(toBounds, -1 /* duration */); + final Rect targetBounds = new Rect(); + mContainer.getAnimatingBounds(targetBounds); + if (!toBounds.equals(targetBounds)) { + animateResizePinnedStack(toBounds, -1 /* duration */); + } + + final PinnedStackController pinnedStackController = + mContainer.getDisplayContent().getPinnedStackController(); + pinnedStackController.setAspectRatio( + pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio) + ? aspectRatio : -1f); + } + } + + /** Sets the current picture-in-picture actions. */ + public void setPictureInPictureActions(List<RemoteAction> actions) { + synchronized (mWindowMap) { + if (!mService.mSupportsPictureInPicture || mContainer == null) { + return; + } + + mContainer.getDisplayContent().getPinnedStackController().setActions(actions); } } @@ -244,17 +265,6 @@ public class StackWindowController } } - /** Sets the current picture-in-picture actions. */ - public void setPictureInPictureActions(List<RemoteAction> actions) { - synchronized (mWindowMap) { - if (!mService.mSupportsPictureInPicture || mContainer == null) { - return; - } - - mContainer.getDisplayContent().getPinnedStackController().setActions(actions); - } - } - private void getRawBounds(Rect outBounds) { if (mContainer.getRawFullscreen()) { outBounds.setEmpty(); diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index a1c9c294bc05..544d1e3d88db 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -393,8 +393,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2); switch (mStackId) { case PINNED_STACK_ID: + Rect targetBounds = new Rect(); + getAnimatingBounds(targetBounds); mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds, - mDisplayContent); + targetBounds, mDisplayContent); break; case DOCKED_STACK_ID: repositionDockedStackAfterRotation(mTmpRect2); @@ -670,7 +672,9 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye // Update the pinned stack controller after the display info is updated if (mStackId == PINNED_STACK_ID) { - mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds, + Rect targetBounds = new Rect(); + getAnimatingBounds(targetBounds); + mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds, targetBounds, mDisplayContent); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 971794be2cbb..597e8b6ac8fc 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2829,36 +2829,6 @@ public class WindowManagerService extends IWindowManager.Stub mDockedStackCreateBounds = bounds; } - @Override - public Rect getPictureInPictureDefaultBounds(int displayId) { - synchronized (mWindowMap) { - if (!mSupportsPictureInPicture) { - return null; - } - - final DisplayContent displayContent = mRoot.getDisplayContent(displayId); - return displayContent.getPinnedStackController().getDefaultBounds(); - } - } - - @Override - public Rect getPictureInPictureMovementBounds(int displayId) { - synchronized (mWindowMap) { - if (!mSupportsPictureInPicture) { - return null; - } - - final Rect stackBounds = new Rect(); - getStackBounds(PINNED_STACK_ID, stackBounds); - if (stackBounds.isEmpty()) { - return stackBounds; - } - - final DisplayContent displayContent = mRoot.getDisplayContent(displayId); - return displayContent.getPinnedStackController().getMovementBounds(stackBounds); - } - } - public Rect getPictureInPictureBounds(int displayId, float aspectRatio) { synchronized (mWindowMap) { if (!mSupportsPictureInPicture) { @@ -2871,6 +2841,8 @@ public class WindowManagerService extends IWindowManager.Stub return null; } + final PinnedStackController pinnedStackController = + displayContent.getPinnedStackController(); final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID); if (stack != null) { // If the stack exists, then use its final bounds to calculate the new aspect ratio @@ -2879,13 +2851,23 @@ public class WindowManagerService extends IWindowManager.Stub stack.getAnimatingBounds(stackBounds); } else { // Otherwise, just calculate the aspect ratio bounds from the default bounds - stackBounds = displayContent.getPinnedStackController().getDefaultBounds(); + stackBounds = pinnedStackController.getDefaultBounds(); + } + + if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) { + return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio); + } else { + return stackBounds; } - return displayContent.getPinnedStackController().getAspectRatioBounds(stackBounds, - aspectRatio); } } + public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) { + final DisplayContent displayContent = mRoot.getDisplayContent(displayId); + return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio( + aspectRatio); + } + @Override public void getStackBounds(int stackId, Rect bounds) { synchronized (mWindowMap) { diff --git a/services/core/jni/com_android_server_location_ContextHubService.cpp b/services/core/jni/com_android_server_location_ContextHubService.cpp index 517fce058d1a..05ef0d11e16c 100644 --- a/services/core/jni/com_android_server_location_ContextHubService.cpp +++ b/services/core/jni/com_android_server_location_ContextHubService.cpp @@ -558,12 +558,12 @@ void getHubsCb(const ::android::hardware::hidl_vec<ContextHub>& hubs) { void initContextHubService() { db.hubInfo.numHubs = 0; - db.hubInfo.contextHub = IContexthub::getService("context_hub_hal"); + db.hubInfo.contextHub = IContexthub::getService("context_hub"); if (db.hubInfo.contextHub == nullptr) { ALOGE("Could not load context hub hal"); } else { - ALOGI("Loaded context hub hal"); + ALOGI("Loaded context hub hal, isRemote %s", db.hubInfo.contextHub->isRemote() ? "TRUE" : "FALSE"); } // Prep for storing app info diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 01a1efc3506e..1578562a4faf 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -58,6 +58,7 @@ static jmethodID method_reportGeofencePauseStatus; static jmethodID method_reportGeofenceResumeStatus; static jmethodID method_reportMeasurementData; static jmethodID method_reportNavigationMessages; +static jmethodID method_reportLocationBatch; /* * Save a pointer to JavaVm to attach/detach threads executing @@ -80,6 +81,8 @@ using android::hardware::gnss::V1_0::IAGnssCallback; using android::hardware::gnss::V1_0::IAGnssRil; using android::hardware::gnss::V1_0::IAGnssRilCallback; using android::hardware::gnss::V1_0::IGnss; +using android::hardware::gnss::V1_0::IGnssBatching; +using android::hardware::gnss::V1_0::IGnssBatchingCallback; using android::hardware::gnss::V1_0::IGnssCallback; using android::hardware::gnss::V1_0::IGnssConfiguration; using android::hardware::gnss::V1_0::IGnssDebug; @@ -100,6 +103,7 @@ sp<IGnssXtra> gnssXtraIface = nullptr; sp<IAGnssRil> agnssRilIface = nullptr; sp<IGnssGeofencing> gnssGeofencingIface = nullptr; sp<IAGnss> agnssIface = nullptr; +sp<IGnssBatching> gnssBatchingIface = nullptr; sp<IGnssDebug> gnssDebugIface = nullptr; sp<IGnssConfiguration> gnssConfigurationIface = nullptr; sp<IGnssNi> gnssNiIface = nullptr; @@ -139,6 +143,7 @@ void JavaMethodHelper<T>::callJavaMethod( class JavaObject { public: JavaObject(JNIEnv* env, const char* class_name); + JavaObject(JNIEnv* env, const char* class_name, const char * sz_arg_1); virtual ~JavaObject(); template<class T> @@ -159,6 +164,12 @@ JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) { object_ = env_->NewObject(clazz_, ctor); } +JavaObject::JavaObject(JNIEnv* env, const char* class_name, const char * sz_arg_1) : env_(env) { + clazz_ = env_->FindClass(class_name); + jmethodID ctor = env->GetMethodID(clazz_, "<init>", "(Ljava/lang/String;)V"); + object_ = env_->NewObject(clazz_, ctor, env->NewStringUTF(sz_arg_1)); +} + JavaObject::~JavaObject() { env_->DeleteLocalRef(clazz_); } @@ -591,6 +602,7 @@ Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb( env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessage); + checkAndClearExceptionFromCallback(env, __FUNCTION__); env->DeleteLocalRef(navigationMessage); return Void(); } @@ -925,6 +937,81 @@ Return<void> AGnssRilCallback::requestRefLocCb() { return Void(); } +/* + * GnssBatchingCallback interface implements the callback methods + * required by the IGnssBatching interface. + */ +struct GnssBatchingCallback : public IGnssBatchingCallback { + /* + * Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback + * follow. + */ + Return<void> gnssLocationBatchCb( + const ::android::hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation> & locations) + override; + private: + jobject translateLocation( + JNIEnv* env, const hardware::gnss::V1_0::GnssLocation* location); +}; + +Return<void> GnssBatchingCallback::gnssLocationBatchCb( + const ::android::hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation> & locations) { + JNIEnv* env = getJniEnv(); + + jobjectArray jLocations = env->NewObjectArray(locations.size(), + env->FindClass("android/location/Location"), nullptr); + + for (uint16_t i = 0; i < locations.size(); ++i) { + jobject jLocation = translateLocation(env, &locations[i]); + env->SetObjectArrayElement(jLocations, i, jLocation); + env->DeleteLocalRef(jLocation); + } + + env->CallVoidMethod(mCallbacksObj, method_reportLocationBatch, jLocations); + checkAndClearExceptionFromCallback(env, __FUNCTION__); + + env->DeleteLocalRef(jLocations); + + return Void(); +} + +// TODO: Use this common code to translate location for Geofencing and regular Location +jobject GnssBatchingCallback::translateLocation( + JNIEnv* env, const hardware::gnss::V1_0::GnssLocation* location) { + JavaObject object(env, "android/location/Location", "gps"); + + uint16_t flags = static_cast<uint32_t>(location->gnssLocationFlags); + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) { + SET(Latitude, location->latitudeDegrees); + SET(Longitude, location->longitudeDegrees); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) { + SET(Altitude, location->altitudeMeters); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) { + SET(Speed, location->speedMetersPerSec); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) { + SET(Bearing, location->bearingDegrees); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + SET(Accuracy, location->horizontalAccuracyMeters); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + SET(VerticalAccuracyMeters, location->verticalAccuracyMeters); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) { + SET(SpeedAccuracyMetersPerSecond, location->speedAccuracyMetersPerSecond); + } + if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) { + SET(BearingAccuracyDegrees, location->bearingAccuracyDegrees); + } + SET(Time, location->timestamp); + + return object.get(); +} + + static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFFFFJ)V"); method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); @@ -959,6 +1046,10 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, clazz, "reportNavigationMessage", "(Landroid/location/GnssNavigationMessage;)V"); + method_reportLocationBatch = env->GetMethodID( + clazz, + "reportLocationBatch", + "([Landroid/location/Location;)V"); /* * Save a pointer to JVM. @@ -1033,6 +1124,13 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, } else { gnssGeofencingIface = gnssGeofencing; } + + auto gnssBatching = gnssHal->getExtensionGnssBatching(); + if (!gnssBatching.isOk()) { + ALOGD("Unable to get a handle to gnssBatching"); + } else { + gnssBatchingIface = gnssBatching; + } } else { ALOGE("Unable to get GPS service\n"); } @@ -1704,6 +1802,67 @@ static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_sele } } +static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) { + if (gnssBatchingIface == nullptr) { + return 0; // batching not supported, size = 0 + } + auto result = gnssBatchingIface->getBatchSize(); + if (result.isOk()) { + return static_cast<jint>(result); + } else { + return 0; // failure in binder, don't support batching + } +} + +static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jclass) { + if (gnssBatchingIface == nullptr) { + return JNI_FALSE; // batching not supported + } + sp<IGnssBatchingCallback> gnssBatchingCbIface = new GnssBatchingCallback(); + + return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface)); +} + +static void android_location_GnssLocationProvider_cleanup_batching(JNIEnv*, jclass) { + if (gnssBatchingIface == nullptr) { + return; // batching not supported + } + gnssBatchingIface->cleanup(); +} + +static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclass, + jlong periodNanos, jboolean wakeOnFifoFull) { + if (gnssBatchingIface == nullptr) { + return JNI_FALSE; // batching not supported + } + + IGnssBatching::Options options; + options.periodNanos = periodNanos; + if (wakeOnFifoFull) { + options.flags = static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL); + } else { + options.flags = 0; + } + + return static_cast<jboolean>(gnssBatchingIface->start(options)); +} + +static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) { + if (gnssBatchingIface == nullptr) { + return; // batching not supported + } + + gnssBatchingIface->flush(); +} + +static jboolean android_location_GnssLocationProvider_stop_batch(JNIEnv*, jclass) { + if (gnssBatchingIface == nullptr) { + return JNI_FALSE; // batching not supported + } + + return gnssBatchingIface->stop(); +} + static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", reinterpret_cast<void *>( @@ -1829,6 +1988,27 @@ static const JNINativeMethod sMethods[] = { {"native_set_emergency_supl_pdn", "(I)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)}, + {"native_get_batch_size", + "()I", + reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)}, + {"native_init_batching", + "()Z", + reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)}, + {"native_start_batch", + "(JZ)Z", + reinterpret_cast<void *>(android_location_GnssLocationProvider_start_batch)}, + {"native_flush_batch", + "()V", + reinterpret_cast<void *>(android_location_GnssLocationProvider_flush_batch)}, + {"native_stop_batch", + "()Z", + reinterpret_cast<void *>(android_location_GnssLocationProvider_stop_batch)}, + {"native_init_batching", + "()Z", + reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)}, + {"native_cleanup_batching", + "()V", + reinterpret_cast<void *>(android_location_GnssLocationProvider_cleanup_batching)}, }; int register_android_server_location_GnssLocationProvider(JNIEnv* env) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index deb9ee0a41c9..003b6d0d3be9 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -60,6 +60,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.AppGlobals; import android.app.IActivityManager; @@ -6151,8 +6152,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { intent.setComponent(mOwners.getDeviceOwnerComponent()); intent.setDataAndType(bugreportUri, RemoteBugreportUtils.BUGREPORT_MIMETYPE); intent.putExtra(DeviceAdminReceiver.EXTRA_BUGREPORT_HASH, bugreportHash); - mContext.grantUriPermission(mOwners.getDeviceOwnerComponent().getPackageName(), - bugreportUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + LocalServices.getService(ActivityManagerInternal.class) + .grantUriPermissionFromIntent(Process.SHELL_UID, + mOwners.getDeviceOwnerComponent().getPackageName(), + intent, mOwners.getDeviceOwnerUserId()); mContext.sendBroadcastAsUser(intent, UserHandle.of(mOwners.getDeviceOwnerUserId())); } } catch (FileNotFoundException e) { @@ -8612,9 +8617,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - /** - * This function returns the list of components allowed to start the task lock mode. - */ @Override public String[] getLockTaskPackages(ComponentName who) { Preconditions.checkNotNull(who, "ComponentName is null"); diff --git a/tools/layoutlib/.idea/libraries/mockito.xml b/tools/layoutlib/.idea/libraries/mockito.xml new file mode 100644 index 000000000000..032963e40b94 --- /dev/null +++ b/tools/layoutlib/.idea/libraries/mockito.xml @@ -0,0 +1,9 @@ +<component name="libraryTable"> + <library name="mockito"> + <CLASSES> + <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/mockito-host_intermediates/javalib.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> +</component>
\ No newline at end of file diff --git a/tools/layoutlib/.idea/libraries/objenesis.xml b/tools/layoutlib/.idea/libraries/objenesis.xml new file mode 100644 index 000000000000..1484de59be6a --- /dev/null +++ b/tools/layoutlib/.idea/libraries/objenesis.xml @@ -0,0 +1,9 @@ +<component name="libraryTable"> + <library name="objenesis"> + <CLASSES> + <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/objenesis-host_intermediates/javalib.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> +</component>
\ No newline at end of file diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml index fbaed520fff9..85ec3eb73b92 100644 --- a/tools/layoutlib/bridge/bridge.iml +++ b/tools/layoutlib/bridge/bridge.iml @@ -86,5 +86,7 @@ </library> </orderEntry> <orderEntry type="library" scope="TEST" name="junit" level="project" /> + <orderEntry type="library" scope="TEST" name="mockito" level="project" /> + <orderEntry type="library" scope="TEST" name="objenesis" level="project" /> </component> </module>
\ No newline at end of file diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java index 138b2d5fca3d..9fd1e1557537 100644 --- a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java +++ b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java @@ -16,6 +16,7 @@ package android.util; +import com.android.ide.common.rendering.api.AttrResourceValue; import com.android.ide.common.rendering.api.RenderResources; import com.android.ide.common.rendering.api.ResourceValue; import com.android.internal.util.XmlUtils; @@ -27,6 +28,11 @@ import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParser; +import android.annotation.NonNull; + +import java.util.Map; +import java.util.function.Function; + /** * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser */ @@ -34,12 +40,30 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes { private final BridgeContext mContext; private final boolean mPlatformFile; - - public BridgeXmlPullAttributes(XmlPullParser parser, BridgeContext context, - boolean platformFile) { + private final Function<String, Map<String, Integer>> mFrameworkEnumValueSupplier; + private final Function<String, Map<String, Integer>> mProjectEnumValueSupplier; + + // VisibleForTesting + BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context, + boolean platformFile, + @NonNull Function<String, Map<String, Integer>> frameworkEnumValueSupplier, + @NonNull Function<String, Map<String, Integer>> projectEnumValueSupplier) { super(parser); mContext = context; mPlatformFile = platformFile; + mFrameworkEnumValueSupplier = frameworkEnumValueSupplier; + mProjectEnumValueSupplier = projectEnumValueSupplier; + } + + public BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context, + boolean platformFile) { + this(parser, context, platformFile, Bridge::getEnumValues, attrName -> { + // get the styleable matching the resolved name + RenderResources res = context.getRenderResources(); + ResourceValue attr = res.getProjectResource(ResourceType.ATTR, attrName); + return attr instanceof AttrResourceValue ? + ((AttrResourceValue) attr).getAttributeValues() : null; + }); } /* @@ -59,12 +83,8 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes { String ns = mParser.getAttributeNamespace(index); if (BridgeConstants.NS_RESOURCES.equals(ns)) { - Integer v = Bridge.getResourceId(ResourceType.ATTR, name); - if (v != null) { - return v.intValue(); - } + return Bridge.getResourceId(ResourceType.ATTR, name); - return 0; } // this is not an attribute in the android namespace, we query the customviewloader, if @@ -72,7 +92,7 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes { if (mContext.getLayoutlibCallback().getNamespace().equals(ns)) { Integer v = mContext.getLayoutlibCallback().getResourceId(ResourceType.ATTR, name); if (v != null) { - return v.intValue(); + return v; } } @@ -121,20 +141,38 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes { } @Override - public int getAttributeIntValue(String namespace, String attribute, - int defaultValue) { + public int getAttributeIntValue(String namespace, String attribute, int defaultValue) { String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); + if (value == null) { + return defaultValue; + } - if (r != null) { - value = r.getValue(); - } + ResourceValue r = getResourceValue(value); - return XmlUtils.convertValueToInt(value, defaultValue); + if (r != null) { + value = r.getValue(); } - return defaultValue; + if (value.charAt(0) == '#') { + return ResourceHelper.getColor(value); + } + + try { + return XmlUtils.convertValueToInt(value, defaultValue); + } catch (NumberFormatException e) { + // This is probably an enum + Map<String, Integer> enumValues = BridgeConstants.NS_RESOURCES.equals(namespace) ? + mFrameworkEnumValueSupplier.apply(attribute) : + mProjectEnumValueSupplier.apply(attribute); + + Integer enumValue = enumValues != null ? enumValues.get(value) : null; + if (enumValue != null) { + return enumValue; + } + + // We weren't able to find the enum int value + throw e; + } } @Override @@ -203,21 +241,9 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes { @Override public int getAttributeIntValue(int index, int defaultValue) { - String value = getAttributeValue(index); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - if (value.charAt(0) == '#') { - return ResourceHelper.getColor(value); - } - return XmlUtils.convertValueToInt(value, defaultValue); - } - - return defaultValue; + return getAttributeIntValue(mParser.getAttributeNamespace(index), + getAttributeName(index) + , defaultValue); } @Override diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 56898f185d15..253ea6f27201 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -483,16 +483,6 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public Rect getPictureInPictureDefaultBounds(int displayId) { - return null; - } - - @Override - public Rect getPictureInPictureMovementBounds(int displayId) { - return null; - } - - @Override public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) throws RemoteException { } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index dff4f6905db5..c9b04dcf8ed4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -111,7 +111,7 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP * Custom implementation of Context/Activity to handle non compiled resources. */ @SuppressWarnings("deprecation") // For use of Pair. -public final class BridgeContext extends Context { +public class BridgeContext extends Context { private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2); diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk index 33d55dea6f79..1b65eee729e6 100644 --- a/tools/layoutlib/bridge/tests/Android.mk +++ b/tools/layoutlib/bridge/tests/Android.mk @@ -31,7 +31,8 @@ LOCAL_JAVA_LIBRARIES := layoutlib \ tools-common-prebuilt \ sdk-common \ junit-host \ - guavalib + guavalib \ + mockito-host include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png Binary files differindex 199ea60e0e24..affc31ee48e2 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png Binary files differindex 89ff5db8f40b..a53dcbae327b 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png Binary files differindex 1f4405d49ffc..88fa9ddbd349 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png Binary files differindex 26aed6a7ed7c..e33f92d7e1bd 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png Binary files differindex aaf1514ddc24..915868c59f11 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png Binary files differindex c3bd70837ff1..ee72a6fe27e8 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png Binary files differindex 0c1621544870..781d617cc975 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png Binary files differindex 81755cec9b15..5b64d336235f 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png Binary files differindex 868cd51f8bb5..a8567b3ef023 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png Binary files differindex 601f711f32d3..5ae95ea34ad4 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png Binary files differindex 0b8f1a96791c..b2b6a970c29f 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png Binary files differindex 87bd5020bcd4..cf1a769f0550 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png Binary files differindex eb431b0280da..e0abcf412844 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png Binary files differindex 4e448c8f2efc..3d0fbd606188 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png Binary files differindex b75671990ce6..86b00415c3ec 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png Binary files differindex 466eca8d1721..7bbae09c13d3 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png Binary files differindex 940fe5bc44ba..e9dca69281be 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png diff --git a/tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java b/tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java new file mode 100644 index 000000000000..2fcec8e98585 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java @@ -0,0 +1,110 @@ +/* + * 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.util; + +import com.android.ide.common.rendering.api.RenderResources; +import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.android.BridgeContext; + +import org.junit.Test; +import org.xmlpull.v1.XmlPullParser; + +import com.google.common.collect.ImmutableMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BridgeXmlPullAttributesTest { + @Test + public void testGetAttributeIntValueForEnums() { + RenderResources renderResources = new RenderResources(); + + XmlPullParser parser = mock(XmlPullParser.class); + when(parser.getAttributeValue(BridgeConstants.NS_RESOURCES, "layout_width")) + .thenReturn("match_parent"); + when(parser.getAttributeName(0)).thenReturn("layout_width"); + when(parser.getAttributeNamespace(0)).thenReturn(BridgeConstants.NS_RESOURCES); + // Return every value twice since there is one test using name and other using index + when(parser.getAttributeValue("http://custom", "my_custom_attr")) + .thenReturn("a", "a", "b", "b", "invalid", "invalid"); + when(parser.getAttributeName(1)).thenReturn("my_custom_attr"); + when(parser.getAttributeNamespace(1)).thenReturn("http://custom"); + + BridgeContext context = mock(BridgeContext.class); + when(context.getRenderResources()).thenReturn(renderResources); + + BridgeXmlPullAttributes attributes = new BridgeXmlPullAttributes( + parser, + context, + false, + attrName -> { + if ("layout_width".equals(attrName)) { + return ImmutableMap.of( + "match_parent", 123); + } + return ImmutableMap.of(); + }, + attrName -> { + if ("my_custom_attr".equals(attrName)) { + return ImmutableMap.of( + "a", 1, + "b", 2 + ); + } + return ImmutableMap.of(); + }); + + // Test a framework defined enum attribute + assertEquals(123, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES, + "layout_width", 500)); + assertEquals(123, attributes.getAttributeIntValue(0, 500)); + // Test non existing attribute (it should return the default value) + assertEquals(500, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES, + "layout_height", 500)); + assertEquals(500, attributes.getAttributeIntValue(2, 500)); + + // Test project defined enum attribute + assertEquals(1, attributes.getAttributeIntValue("http://custom", + "my_custom_attr", 500)); + assertEquals(1, attributes.getAttributeIntValue(1, 500)); + assertEquals(2, attributes.getAttributeIntValue("http://custom", + "my_custom_attr", 500)); + assertEquals(2, attributes.getAttributeIntValue(1, 500)); + // Test an invalid enum + boolean exception = false; + try { + attributes.getAttributeIntValue("http://custom", "my_custom_attr", 500); + } catch(NumberFormatException e) { + exception = true; + } + assertTrue(exception); + exception = false; + try { + attributes.getAttributeIntValue(1, 500); + } catch(NumberFormatException e) { + exception = true; + } + assertTrue(exception); + + // Test non existing project attribute + assertEquals(500, attributes.getAttributeIntValue("http://custom", + "my_other_attr", 500)); + } + +}
\ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java index 18c662915a6d..cdf56334cbc5 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java @@ -54,7 +54,7 @@ public class ImageUtils { */ private static final boolean FAIL_ON_MISSING_THUMBNAIL = true; - private static final int THUMBNAIL_SIZE = 250; + private static final int THUMBNAIL_SIZE = 1000; private static final double MAX_PERCENT_DIFFERENCE = 0.3; |