Merge "don't log non-instant app resolutions" into oc-dev
diff --git a/Android.mk b/Android.mk
index f1db6b7..ee7d471 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1460,8 +1460,7 @@
LOCAL_SRC_FILES := \
$(call all-proto-files-under, core/proto) \
$(call all-proto-files-under, libs/incident/proto)
-LOCAL_SHARED_LIBRARIES := libprotobuf-cpp-full
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
# ==== c++ proto host library ==============================
include $(CLEAR_VARS)
diff --git a/api/current.txt b/api/current.txt
index c99f325..c5f4816 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3578,7 +3578,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
@@ -4358,7 +4358,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public android.app.ActionBar getActionBar();
method public final android.content.Context getContext();
method public android.view.View getCurrentFocus();
@@ -7044,6 +7044,7 @@
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();
@@ -20913,6 +20914,7 @@
method public int getContentType();
method public int getFlags();
method public int getUsage();
+ method public static deprecated int getVolumeControlStream(android.media.AudioAttributes);
method public int getVolumeControlStream();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
@@ -24555,85 +24557,6 @@
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
- public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
- field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
- field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
- field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
- field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
- 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_BROWSABLE = "browsable";
- field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
- field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
- field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
- 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_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_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_PREVIEW_VIDEO_URI = "preview_video_uri";
- 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_STARTING_PRICE = "starting_price";
- field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
- field public static final java.lang.String COLUMN_TRANSIENT = "transient";
- field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
- field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
- field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
- field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
- field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
- field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
- field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
- field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
- field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
- field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
- field public static final int TYPE_ALBUM = 8; // 0x8
- field public static final int TYPE_ARTIST = 9; // 0x9
- field public static final int TYPE_CHANNEL = 6; // 0x6
- field public static final int TYPE_CLIP = 4; // 0x4
- field public static final int TYPE_EVENT = 5; // 0x5
- field public static final int TYPE_MOVIE = 0; // 0x0
- field public static final int TYPE_PLAYLIST = 10; // 0xa
- field public static final int TYPE_STATION = 11; // 0xb
- field public static final int TYPE_TRACK = 7; // 0x7
- field public static final int TYPE_TV_EPISODE = 3; // 0x3
- field public static final int TYPE_TV_SEASON = 2; // 0x2
- field public static final int TYPE_TV_SERIES = 1; // 0x1
- }
-
- 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_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";
}
@@ -24720,22 +24643,116 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ 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_BROWSABLE = "browsable";
+ 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_ID = "content_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_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_INTENT_URI = "intent_uri";
+ 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_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 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_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_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.Programs 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_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 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_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_PROHIBITED = "recording_prohibited";
+ 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_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/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -24764,28 +24781,122 @@
field public static final java.lang.String TRAVEL = "TRAVEL";
}
- public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.RecordedPrograms 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_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;
}
- public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
ctor public TvContract.WatchNextPrograms();
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ 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_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CONTENT_ID = "content_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_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_INTENT_URI = "intent_uri";
+ 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_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+ 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_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 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_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 CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
@@ -34410,14 +34521,15 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final java.lang.String WEIGHT = "font_weight";
}
public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -38639,6 +38751,7 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public final long getConnectTimeMillis();
+ method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
method public android.telecom.GatewayInfo getGatewayInfo();
@@ -41212,6 +41325,8 @@
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
public static final class Layout.Alignment extends java.lang.Enum {
@@ -41413,7 +41528,7 @@
method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
method public android.text.StaticLayout.Builder setIncludePad(boolean);
method public android.text.StaticLayout.Builder setIndents(int[], int[]);
- method public android.text.StaticLayout.Builder setJustify(boolean);
+ method public android.text.StaticLayout.Builder setJustificationMode(int);
method public android.text.StaticLayout.Builder setLineSpacing(float, float);
method public android.text.StaticLayout.Builder setMaxLines(int);
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46492,7 +46607,7 @@
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public boolean getAllowEnterTransitionOverlap();
method public boolean getAllowReturnTransitionOverlap();
method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -48617,7 +48732,7 @@
method public abstract boolean getOffscreenPreRaster();
method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
method public abstract java.lang.String getSansSerifFontFamily();
- method public abstract boolean getSaveFormData();
+ method public abstract deprecated boolean getSaveFormData();
method public abstract deprecated boolean getSavePassword();
method public abstract java.lang.String getSerifFontFamily();
method public abstract java.lang.String getStandardFontFamily();
@@ -48666,7 +48781,7 @@
method public abstract deprecated void setPluginState(android.webkit.WebSettings.PluginState);
method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
method public abstract void setSansSerifFontFamily(java.lang.String);
- method public abstract void setSaveFormData(boolean);
+ method public abstract deprecated void setSaveFormData(boolean);
method public abstract deprecated void setSavePassword(boolean);
method public abstract void setSerifFontFamily(java.lang.String);
method public abstract void setStandardFontFamily(java.lang.String);
@@ -48957,12 +49072,12 @@
public abstract class WebViewDatabase {
ctor public WebViewDatabase();
- method public abstract void clearFormData();
+ method public abstract deprecated void clearFormData();
method public abstract void clearHttpAuthUsernamePassword();
method public abstract deprecated void clearUsernamePassword();
method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
- method public abstract boolean hasFormData();
+ method public abstract deprecated boolean hasFormData();
method public abstract boolean hasHttpAuthUsernamePassword();
method public abstract deprecated boolean hasUsernamePassword();
method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -51223,7 +51338,7 @@
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
method public int getInputType();
- method public boolean getJustify();
+ method public int getJustificationMode();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
@@ -51336,7 +51451,7 @@
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
- method public void setJustify(boolean);
+ method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
method public void setLetterSpacing(float);
method public void setLineSpacing(float, float);
diff --git a/api/removed.txt b/api/removed.txt
index 42b2ae6..d20c08c 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -296,6 +296,10 @@
field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
}
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field public static final java.lang.String STYLE = "font_style";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 222f706..9b295bf 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3702,7 +3702,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
@@ -4509,7 +4509,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public android.app.ActionBar getActionBar();
method public final android.content.Context getContext();
method public android.view.View getCurrentFocus();
@@ -4621,6 +4621,7 @@
method public android.database.Cursor query(android.app.DownloadManager.Query);
method public int remove(long...);
field public static final java.lang.String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
+ field public static final java.lang.String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
field public static final java.lang.String ACTION_NOTIFICATION_CLICKED = "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
field public static final java.lang.String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS";
field public static final java.lang.String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far";
@@ -7502,6 +7503,7 @@
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();
@@ -9796,6 +9798,7 @@
field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
field public static final java.lang.String ACTION_EDIT = "android.intent.action.EDIT";
+ field public static final deprecated java.lang.String ACTION_EPHEMERAL_RESOLVER_SETTINGS = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
@@ -9808,7 +9811,10 @@
field public static final java.lang.String ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
+ field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
+ field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
@@ -9867,6 +9873,8 @@
field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
field public static final java.lang.String ACTION_QUICK_VIEW = "android.intent.action.QUICK_VIEW";
field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
+ field public static final deprecated java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
@@ -9876,6 +9884,7 @@
field public static final java.lang.String ACTION_SEND = "android.intent.action.SEND";
field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
+ field public static final deprecated java.lang.String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
@@ -9950,6 +9959,8 @@
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
+ field public static final deprecated java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
+ field public static final deprecated java.lang.String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
field public static final deprecated java.lang.String EXTRA_CHANGED_COMPONENT_NAME = "android.intent.extra.changed_component_name";
field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
@@ -9959,7 +9970,14 @@
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_CONTENT_ANNOTATIONS = "android.intent.extra.CONTENT_ANNOTATIONS";
+ field public static final deprecated java.lang.String EXTRA_CSS_INDICATOR = "cssIndicator";
+ field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long";
+ field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_SHORT = "data-operator-alpha-short";
+ field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_NUMERIC = "data-operator-numeric";
+ field public static final deprecated java.lang.String EXTRA_DATA_RADIO_TECH = "dataRadioTechnology";
+ field public static final deprecated java.lang.String EXTRA_DATA_REG_STATE = "dataRegState";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
+ field public static final deprecated java.lang.String EXTRA_DATA_ROAMING_TYPE = "dataRoamingType";
field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
field public static final int EXTRA_DOCK_STATE_CAR = 2; // 0x2
field public static final int EXTRA_DOCK_STATE_DESK = 1; // 0x1
@@ -9968,6 +9986,7 @@
field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+ field public static final deprecated java.lang.String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
@@ -9975,10 +9994,18 @@
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
field public static final java.lang.String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_INTENT = "android.intent.extra.INTENT";
+ field public static final deprecated java.lang.String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION = "isDataRoamingFromRegistration";
+ field public static final deprecated java.lang.String EXTRA_IS_USING_CARRIER_AGGREGATION = "isUsingCarrierAggregation";
field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
+ field public static final deprecated java.lang.String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
+ field public static final deprecated java.lang.String EXTRA_MANUAL = "manual";
field public static final java.lang.String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
+ field public static final deprecated java.lang.String EXTRA_NETWORK_ID = "networkId";
field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+ field public static final deprecated java.lang.String EXTRA_OPERATOR_ALPHA_LONG = "operator-alpha-long";
+ field public static final deprecated java.lang.String EXTRA_OPERATOR_ALPHA_SHORT = "operator-alpha-short";
+ field public static final deprecated java.lang.String EXTRA_OPERATOR_NUMERIC = "operator-numeric";
field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
@@ -10010,11 +10037,15 @@
field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
+ field public static final deprecated java.lang.String EXTRA_SYSTEM_ID = "systemId";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
field public static final java.lang.String EXTRA_USER = "android.intent.extra.USER";
+ field public static final deprecated java.lang.String EXTRA_VOICE_RADIO_TECH = "radioTechnology";
+ field public static final deprecated java.lang.String EXTRA_VOICE_REG_STATE = "voiceRegState";
+ field public static final deprecated java.lang.String EXTRA_VOICE_ROAMING_TYPE = "voiceRoamingType";
field public static final int FILL_IN_ACTION = 1; // 0x1
field public static final int FILL_IN_CATEGORIES = 4; // 0x4
field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -22653,6 +22684,7 @@
method public int getContentType();
method public int getFlags();
method public int getUsage();
+ method public static deprecated int getVolumeControlStream(android.media.AudioAttributes);
method public int getVolumeControlStream();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
@@ -26500,85 +26532,6 @@
field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
}
- public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
- field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
- field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
- field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
- field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
- 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_BROWSABLE = "browsable";
- field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
- field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
- field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
- 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_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_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_PREVIEW_VIDEO_URI = "preview_video_uri";
- 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_STARTING_PRICE = "starting_price";
- field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
- field public static final java.lang.String COLUMN_TRANSIENT = "transient";
- field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
- field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
- field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
- field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
- field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
- field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
- field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
- field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
- field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
- field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
- field public static final int TYPE_ALBUM = 8; // 0x8
- field public static final int TYPE_ARTIST = 9; // 0x9
- field public static final int TYPE_CHANNEL = 6; // 0x6
- field public static final int TYPE_CLIP = 4; // 0x4
- field public static final int TYPE_EVENT = 5; // 0x5
- field public static final int TYPE_MOVIE = 0; // 0x0
- field public static final int TYPE_PLAYLIST = 10; // 0xa
- field public static final int TYPE_STATION = 11; // 0xb
- field public static final int TYPE_TRACK = 7; // 0x7
- field public static final int TYPE_TV_EPISODE = 3; // 0x3
- field public static final int TYPE_TV_SEASON = 2; // 0x2
- field public static final int TYPE_TV_SERIES = 1; // 0x1
- }
-
- 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_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";
}
@@ -26666,22 +26619,116 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ 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_BROWSABLE = "browsable";
+ 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_ID = "content_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_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_INTENT_URI = "intent_uri";
+ 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_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 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_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_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.Programs 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_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 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_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_PROHIBITED = "recording_prohibited";
+ 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_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/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -26710,28 +26757,122 @@
field public static final java.lang.String TRAVEL = "TRAVEL";
}
- public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.RecordedPrograms 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_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;
}
- public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
ctor public TvContract.WatchNextPrograms();
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ 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_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CONTENT_ID = "content_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_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_INTENT_URI = "intent_uri";
+ 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_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+ 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_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 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_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 CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
@@ -37319,14 +37460,15 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final java.lang.String WEIGHT = "font_weight";
}
public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -41801,6 +41943,7 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public final long getConnectTimeMillis();
+ method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
method public android.telecom.GatewayInfo getGatewayInfo();
@@ -44674,6 +44817,8 @@
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
public static final class Layout.Alignment extends java.lang.Enum {
@@ -44875,7 +45020,7 @@
method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
method public android.text.StaticLayout.Builder setIncludePad(boolean);
method public android.text.StaticLayout.Builder setIndents(int[], int[]);
- method public android.text.StaticLayout.Builder setJustify(boolean);
+ method public android.text.StaticLayout.Builder setJustificationMode(int);
method public android.text.StaticLayout.Builder setLineSpacing(float, float);
method public android.text.StaticLayout.Builder setMaxLines(int);
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -49955,7 +50100,7 @@
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public boolean getAllowEnterTransitionOverlap();
method public boolean getAllowReturnTransitionOverlap();
method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -52165,7 +52310,7 @@
method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
method public abstract deprecated boolean getPluginsEnabled();
method public abstract java.lang.String getSansSerifFontFamily();
- method public abstract boolean getSaveFormData();
+ method public abstract deprecated boolean getSaveFormData();
method public abstract deprecated boolean getSavePassword();
method public abstract java.lang.String getSerifFontFamily();
method public abstract java.lang.String getStandardFontFamily();
@@ -52220,7 +52365,7 @@
method public abstract deprecated void setPluginsEnabled(boolean);
method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
method public abstract void setSansSerifFontFamily(java.lang.String);
- method public abstract void setSaveFormData(boolean);
+ method public abstract deprecated void setSaveFormData(boolean);
method public abstract deprecated void setSavePassword(boolean);
method public abstract void setSerifFontFamily(java.lang.String);
method public abstract void setStandardFontFamily(java.lang.String);
@@ -52548,12 +52693,12 @@
public abstract class WebViewDatabase {
ctor public WebViewDatabase();
- method public abstract void clearFormData();
+ method public abstract deprecated void clearFormData();
method public abstract void clearHttpAuthUsernamePassword();
method public abstract deprecated void clearUsernamePassword();
method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
- method public abstract boolean hasFormData();
+ method public abstract deprecated boolean hasFormData();
method public abstract boolean hasHttpAuthUsernamePassword();
method public abstract deprecated boolean hasUsernamePassword();
method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -55053,7 +55198,7 @@
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
method public int getInputType();
- method public boolean getJustify();
+ method public int getJustificationMode();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
@@ -55166,7 +55311,7 @@
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
- method public void setJustify(boolean);
+ method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
method public void setLetterSpacing(float);
method public void setLineSpacing(float, float);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1bafe96..1effe9c 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -290,6 +290,10 @@
field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
}
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field public static final java.lang.String STYLE = "font_style";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 387d14c..6db91be 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3580,7 +3580,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
@@ -4370,7 +4370,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public android.app.ActionBar getActionBar();
method public final android.content.Context getContext();
method public android.view.View getCurrentFocus();
@@ -7074,6 +7074,7 @@
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();
@@ -21026,6 +21027,7 @@
method public int getContentType();
method public int getFlags();
method public int getUsage();
+ method public static deprecated int getVolumeControlStream(android.media.AudioAttributes);
method public int getVolumeControlStream();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
@@ -24668,85 +24670,6 @@
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
- public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
- field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
- field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
- field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
- field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
- 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_BROWSABLE = "browsable";
- field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
- field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
- field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
- 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_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_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_PREVIEW_VIDEO_URI = "preview_video_uri";
- 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_STARTING_PRICE = "starting_price";
- field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
- field public static final java.lang.String COLUMN_TRANSIENT = "transient";
- field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
- field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
- field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
- field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
- field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
- field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
- field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
- field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
- field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
- field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
- field public static final int TYPE_ALBUM = 8; // 0x8
- field public static final int TYPE_ARTIST = 9; // 0x9
- field public static final int TYPE_CHANNEL = 6; // 0x6
- field public static final int TYPE_CLIP = 4; // 0x4
- field public static final int TYPE_EVENT = 5; // 0x5
- field public static final int TYPE_MOVIE = 0; // 0x0
- field public static final int TYPE_PLAYLIST = 10; // 0xa
- field public static final int TYPE_STATION = 11; // 0xb
- field public static final int TYPE_TRACK = 7; // 0x7
- field public static final int TYPE_TV_EPISODE = 3; // 0x3
- field public static final int TYPE_TV_SEASON = 2; // 0x2
- field public static final int TYPE_TV_SERIES = 1; // 0x1
- }
-
- 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_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";
}
@@ -24833,22 +24756,116 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ 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_BROWSABLE = "browsable";
+ 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_ID = "content_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_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_INTENT_URI = "intent_uri";
+ 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_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 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_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_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.Programs 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_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 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_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_PROHIBITED = "recording_prohibited";
+ 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_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/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -24877,28 +24894,122 @@
field public static final java.lang.String TRAVEL = "TRAVEL";
}
- public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.RecordedPrograms 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_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;
}
- public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
ctor public TvContract.WatchNextPrograms();
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ 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_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CONTENT_ID = "content_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_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_INTENT_URI = "intent_uri";
+ 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_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+ 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_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 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_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 CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
@@ -34550,14 +34661,15 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final java.lang.String WEIGHT = "font_weight";
}
public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -38843,6 +38955,7 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public final long getConnectTimeMillis();
+ method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
method public android.telecom.GatewayInfo getGatewayInfo();
@@ -41420,6 +41533,8 @@
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
public static final class Layout.Alignment extends java.lang.Enum {
@@ -41621,7 +41736,7 @@
method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
method public android.text.StaticLayout.Builder setIncludePad(boolean);
method public android.text.StaticLayout.Builder setIndents(int[], int[]);
- method public android.text.StaticLayout.Builder setJustify(boolean);
+ method public android.text.StaticLayout.Builder setJustificationMode(int);
method public android.text.StaticLayout.Builder setLineSpacing(float, float);
method public android.text.StaticLayout.Builder setMaxLines(int);
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46874,7 +46989,7 @@
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public boolean getAllowEnterTransitionOverlap();
method public boolean getAllowReturnTransitionOverlap();
method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -49001,7 +49116,7 @@
method public abstract boolean getOffscreenPreRaster();
method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
method public abstract java.lang.String getSansSerifFontFamily();
- method public abstract boolean getSaveFormData();
+ method public abstract deprecated boolean getSaveFormData();
method public abstract deprecated boolean getSavePassword();
method public abstract java.lang.String getSerifFontFamily();
method public abstract java.lang.String getStandardFontFamily();
@@ -49050,7 +49165,7 @@
method public abstract deprecated void setPluginState(android.webkit.WebSettings.PluginState);
method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
method public abstract void setSansSerifFontFamily(java.lang.String);
- method public abstract void setSaveFormData(boolean);
+ method public abstract deprecated void setSaveFormData(boolean);
method public abstract deprecated void setSavePassword(boolean);
method public abstract void setSerifFontFamily(java.lang.String);
method public abstract void setStandardFontFamily(java.lang.String);
@@ -49341,12 +49456,12 @@
public abstract class WebViewDatabase {
ctor public WebViewDatabase();
- method public abstract void clearFormData();
+ method public abstract deprecated void clearFormData();
method public abstract void clearHttpAuthUsernamePassword();
method public abstract deprecated void clearUsernamePassword();
method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
- method public abstract boolean hasFormData();
+ method public abstract deprecated boolean hasFormData();
method public abstract boolean hasHttpAuthUsernamePassword();
method public abstract deprecated boolean hasUsernamePassword();
method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -51614,7 +51729,7 @@
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
method public int getInputType();
- method public boolean getJustify();
+ method public int getJustificationMode();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
@@ -51727,7 +51842,7 @@
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
- method public void setJustify(boolean);
+ method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
method public void setLetterSpacing(float);
method public void setLineSpacing(float, float);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 42b2ae6..d20c08c 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -296,6 +296,10 @@
field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
}
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field public static final java.lang.String STYLE = "font_style";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 2435ffa..7394490 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -370,7 +370,8 @@
bool BootAnimation::android()
{
- ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
+ ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
@@ -896,7 +897,8 @@
const int animationX = (mWidth - animation.width) / 2;
const int animationY = (mHeight - animation.height) / 2;
- ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
+ ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ 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/app/Activity.java b/core/java/android/app/Activity.java
index d432160..c0505eb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2443,13 +2443,20 @@
}
/**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link #onCreate}.
+ * Finds a view that was identified by the {@code android:id} XML attribute
+ * that was processed in {@link #onCreate}.
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @return The view if found or null otherwise.
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
@Nullable
- public View findViewById(@IdRes int id) {
+ public <T extends View> T findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d1d462c..7299d6b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.AssetManager;
@@ -869,16 +870,20 @@
sendMessage(H.UNBIND_SERVICE, s);
}
- public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
- int flags ,Intent args) {
- ServiceArgsData s = new ServiceArgsData();
- s.token = token;
- s.taskRemoved = taskRemoved;
- s.startId = startId;
- s.flags = flags;
- s.args = args;
+ public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
+ List<ServiceStartArgs> list = args.getList();
- sendMessage(H.SERVICE_ARGS, s);
+ for (int i = 0; i < list.size(); i++) {
+ ServiceStartArgs ssa = list.get(i);
+ ServiceArgsData s = new ServiceArgsData();
+ s.token = token;
+ s.taskRemoved = ssa.taskRemoved;
+ s.startId = ssa.startId;
+ s.flags = ssa.flags;
+ s.args = ssa.args;
+
+ sendMessage(H.SERVICE_ARGS, s);
+ }
}
public final void scheduleStopService(IBinder token) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 72ccf72..943c572 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -498,14 +498,22 @@
}
/**
- * Finds a child view with the given identifier. Returns null if the
- * specified child view does not exist or the dialog has not yet been fully
- * created (for example, via {@link #show()} or {@link #create()}).
+ * Finds the first descendant view with the given ID or {@code null} if the
+ * ID is invalid (< 0), there is no matching view in the hierarchy, or the
+ * dialog has not yet been fully created (for example, via {@link #show()}
+ * or {@link #create()}).
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @param id the identifier of the view to find
- * @return The view with the given id or null.
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
- public @Nullable View findViewById(@IdRes int id) {
+ @Nullable
+ public <T extends View> T findViewById(@IdRes int id) {
return mWindow.findViewById(id);
}
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 462f66f..b89c165 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -321,6 +322,11 @@
*/
public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
+ /** {@hide} */
+ @SystemApi
+ public static final String ACTION_DOWNLOAD_COMPLETED =
+ "android.intent.action.DOWNLOAD_COMPLETED";
+
/**
* columns to request from DownloadProvider.
* @hide
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 279b900..399987f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1128,8 +1128,13 @@
newState = Fragment.CREATED;
}
if (f.mRemoving && newState > f.mState) {
- // While removing a fragment, we can't change it to a higher state.
- newState = f.mState;
+ if (f.mState == Fragment.INITIALIZING && f.isInBackStack()) {
+ // Allow the fragment to be created so that it can be saved later.
+ newState = Fragment.CREATED;
+ } else {
+ // While removing a fragment, we can't change it to a higher state.
+ newState = f.mState;
+ }
}
// Defer start if requested; don't allow it to move to STARTED or higher
// if it's not already started.
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f4d26fd..079bbcd 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -635,6 +635,11 @@
*/
int getLastResumedActivityUserId();
+ /**
+ * Add a bare uid to the background restrictions whitelist. Only the system uid may call this.
+ */
+ void backgroundWhitelistUid(int uid);
+
// WARNING: when these transactions are updated, check if they are any callers on the native
// side. If so, make sure they are using the correct transaction ids and arguments.
// If a transaction which will also be used on the native side is being inserted, add it
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 6c43fe3..1b3c00b 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -25,6 +25,7 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
@@ -86,8 +87,7 @@
in Bundle coreSettings, in String buildSerial);
void scheduleExit();
void scheduleConfigurationChanged(in Configuration config);
- void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
- int flags, in Intent args);
+ void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
void updateTimeZone();
void processInBackground();
void scheduleBindService(IBinder token,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3d66135..161dd25 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3793,9 +3793,9 @@
// Ambient view does not have these
bindHeaderText(contentView);
bindHeaderChronometerAndTime(contentView);
- bindExpandButton(contentView);
bindProfileBadge(contentView);
}
+ bindExpandButton(contentView);
}
private void bindExpandButton(RemoteViews contentView) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 489a0f0..d620a81 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -945,7 +945,7 @@
final ResourcesKey key = mResourceImpls.keyAt(i);
final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
- if (impl != null && key.mResDir.equals(assetPath)) {
+ if (impl != null && Objects.equals(key.mResDir, assetPath)) {
if (!ArrayUtils.contains(key.mLibDirs, libAsset)) {
final int newLibAssetCount = 1 +
(key.mLibDirs != null ? key.mLibDirs.length : 0);
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/app/ServiceStartArgs.aidl
similarity index 68%
rename from core/java/android/service/autofill/AutoFillService.java
rename to core/java/android/app/ServiceStartArgs.aidl
index c26f679..fd2cf0f 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/app/ServiceStartArgs.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.autofill;
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use AutofillService
- */
-@Deprecated
-public abstract class AutoFillService extends AutofillService {
-}
+package android.app;
+
+/** @hide */
+parcelable ServiceStartArgs;
diff --git a/core/java/android/app/ServiceStartArgs.java b/core/java/android/app/ServiceStartArgs.java
new file mode 100644
index 0000000..f030cba
--- /dev/null
+++ b/core/java/android/app/ServiceStartArgs.java
@@ -0,0 +1,82 @@
+/*
+ * 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.app;
+
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Describes a Service.onStartCommand() request from the system.
+ * @hide
+ */
+public class ServiceStartArgs implements Parcelable {
+ final public boolean taskRemoved;
+ final public int startId;
+ final public int flags;
+ final public Intent args;
+
+ public ServiceStartArgs(boolean _taskRemoved, int _startId, int _flags, Intent _args) {
+ taskRemoved = _taskRemoved;
+ startId = _startId;
+ flags = _flags;
+ args = _args;
+ }
+
+ public String toString() {
+ return "ServiceStartArgs{taskRemoved=" + taskRemoved + ", startId=" + startId
+ + ", flags=0x" + Integer.toHexString(flags) + ", args=" + args + "}";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(taskRemoved ? 1 : 0);
+ out.writeInt(startId);
+ out.writeInt(flags);
+ if (args != null) {
+ out.writeInt(1);
+ args.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
+ public static final Parcelable.Creator<ServiceStartArgs> CREATOR
+ = new Parcelable.Creator<ServiceStartArgs>() {
+ public ServiceStartArgs createFromParcel(Parcel in) {
+ return new ServiceStartArgs(in);
+ }
+
+ public ServiceStartArgs[] newArray(int size) {
+ return new ServiceStartArgs[size];
+ }
+ };
+
+ public ServiceStartArgs(Parcel in) {
+ taskRemoved = in.readInt() != 0;
+ startId = in.readInt();
+ flags = in.readInt();
+ if (in.readInt() != 0) {
+ args = Intent.CREATOR.createFromParcel(in);
+ } else {
+ args = null;
+ }
+ }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2f0a630..82ad825 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -697,8 +697,8 @@
"android.app.extra.PROVISIONING_ORGANIZATION_NAME";
/**
- * A String extra holding a url to the website of the device's provider. The website can be
- * opened in a browser during provisioning.
+ * A String extra holding a url to the website of the device provider so the user can open it
+ * during provisioning. If the url is not HTTPS, an error will be shown.
*
* <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}
*
@@ -2768,9 +2768,11 @@
* or clears the lockscreen password.
* <p>
* <em>This token is highly sensitive and should be treated at the same level as user
- * credentials. In particular, NEVER store this token on device in plaintext, especially in
- * Device-Encrypted storage if the token will be used to reset password on FBE devices before
- * user unlocks.
+ * credentials. In particular, NEVER store this token on device in plaintext. Do not store
+ * the plaintext token in device-encrypted storage if it will be needed to reset password on
+ * file-based encryption devices before user unlocks. Consider carefully how any password token
+ * will be stored on your server and who will need access to them. Tokens may be the subject of
+ * legal access requests.
* </em>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 7d2db5c..fe51633 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -27,9 +27,6 @@
import android.view.ViewStructure.HtmlInfo.Builder;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -920,15 +917,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
- @Deprecated
- public AutoFillId getAutoFillId() {
- return AutoFillId.forDaRealId(mAutofillId);
- }
-
- /**
* Gets the id that can be used to autofill the view contents.
*
* <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
@@ -939,26 +927,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
- */
- @Deprecated
- public AutoFillType getAutoFillType() {
- switch (getAutofillType()) {
- case View.AUTOFILL_TYPE_TEXT:
- return AutoFillType.forText();
- case View.AUTOFILL_TYPE_TOGGLE:
- return AutoFillType.forToggle();
- case View.AUTOFILL_TYPE_LIST:
- return AutoFillType.forList();
- case View.AUTOFILL_TYPE_DATE:
- return AutoFillType.forDate();
- default:
- return null;
- }
- }
-
- /**
* Gets the the type of value that can be used to autofill the view contents.
*
* <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
@@ -982,15 +950,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
- @Deprecated
- public AutoFillValue getAutoFillValue() {
- return AutoFillValue.forDaRealValue(mAutofillValue);
- }
-
- /**
* Gets the the value of this view.
*
* <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 74a39e8..9f35e85 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -710,9 +710,9 @@
* user may have a corporate profile. In this case the parent user profile has a
* child profile, the corporate one.
*
- * @param profile The profile for which to get providers. Passing null is equivaled
- * to passing only the current user handle.
- * @return The intalled providers.
+ * @param profile The profile for which to get providers. Passing null is equivalent
+ * to querying for only the calling user.
+ * @return The installed providers.
*
* @see android.os.Process#myUserHandle()
* @see android.os.UserManager#getUserProfiles()
@@ -722,7 +722,31 @@
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
- profile);
+ profile, null);
+ }
+
+ /**
+ * Gets the AppWidget providers for the given package and user profile. User
+ * profile can only be the current user or a profile of the current user. For
+ * example, the current user may have a corporate profile. In this case the
+ * parent user profile has a child profile, the corporate one.
+ *
+ * @param packageName The package for which to get providers. If null, this method is
+ * equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}.
+ * @param profile The profile for which to get providers. Passing null is equivalent
+ * to querying for only the calling user.
+ * @return The installed providers.
+ *
+ * @see android.os.Process#myUserHandle()
+ * @see android.os.UserManager#getUserProfiles()
+ */
+ public List<AppWidgetProviderInfo> getInstalledProvidersForPackage(@Nullable String packageName,
+ @Nullable UserHandle profile) {
+ if (mService == null) {
+ return Collections.emptyList();
+ }
+ return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+ profile, packageName);
}
/**
@@ -733,7 +757,7 @@
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
- null);
+ null, null);
}
/**
@@ -752,7 +776,7 @@
if (mService == null) {
return Collections.emptyList();
}
- return getInstalledProvidersForProfile(categoryFilter, null);
+ return getInstalledProvidersForProfile(categoryFilter, null, null);
}
/**
@@ -766,6 +790,7 @@
* @param profile A profile of the current user which to be queried. The user
* is itself also a profile. If null, the providers only for the current user
* are returned.
+ * @param packageName If specified, will only return providers from the given package.
* @return The intalled providers.
*
* @see android.os.Process#myUserHandle()
@@ -774,7 +799,7 @@
* @hide
*/
public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
- UserHandle profile) {
+ @Nullable UserHandle profile, @Nullable String packageName) {
if (mService == null) {
return Collections.emptyList();
}
@@ -785,7 +810,7 @@
try {
ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
- categoryFilter, profile.getIdentifier());
+ categoryFilter, profile.getIdentifier(), packageName);
if (providers == null) {
return Collections.emptyList();
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index da887af..5415eb5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1505,22 +1505,38 @@
public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
/**
- * Activity Action: Launch ephemeral installer.
- * <p>
- * Input: The data must be a http: URI that the ephemeral application is registered
- * to handle.
+ * @hide
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_INSTALL_INSTANT_APP_PACKAGE}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
+ = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ /**
+ * Activity Action: Launch instant application installer.
* <p class="note">
* This is a protected intent that can only be sent by the system.
* </p>
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
- = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ public static final String ACTION_INSTALL_INSTANT_APP_PACKAGE
+ = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
/**
- * Service Action: Resolve ephemeral application.
+ * @hide
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_RESOLVE_INSTANT_APP_PACKAGE}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
+ = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ /**
+ * Service Action: Resolve instant application.
* <p>
* The system will have a persistent connection to this service.
* This is a protected intent that can only be sent by the system.
@@ -1528,12 +1544,22 @@
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.SERVICE_ACTION)
- public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
- = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE
+ = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
/**
- * Activity Action: Launch ephemeral settings.
+ * @hide
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_INSTANT_APP_RESOLVER_SETTINGS}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
+ = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+ /**
+ * Activity Action: Launch instant app settings.
*
* <p class="note">
* This is a protected intent that can only be sent by the system.
@@ -1541,9 +1567,10 @@
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
- = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+ public static final String ACTION_INSTANT_APP_RESOLVER_SETTINGS
+ = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
/**
* Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
@@ -3479,6 +3506,261 @@
public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
/**
+ * Broadcast Action: indicate that the phone service state has changed.
+ * The intent will have the following extra values:</p>
+ * <p>
+ * @see #EXTRA_VOICE_REG_STATE
+ * @see #EXTRA_DATA_REG_STATE
+ * @see #EXTRA_VOICE_ROAMING_TYPE
+ * @see #EXTRA_DATA_ROAMING_TYPE
+ * @see #EXTRA_OPERATOR_ALPHA_LONG
+ * @see #EXTRA_OPERATOR_ALPHA_SHORT
+ * @see #EXTRA_OPERATOR_NUMERIC
+ * @see #EXTRA_DATA_OPERATOR_ALPHA_LONG
+ * @see #EXTRA_DATA_OPERATOR_ALPHA_SHORT
+ * @see #EXTRA_DATA_OPERATOR_NUMERIC
+ * @see #EXTRA_MANUAL
+ * @see #EXTRA_VOICE_RADIO_TECH
+ * @see #EXTRA_DATA_RADIO_TECH
+ * @see #EXTRA_CSS_INDICATOR
+ * @see #EXTRA_NETWORK_ID
+ * @see #EXTRA_SYSTEM_ID
+ * @see #EXTRA_CDMA_ROAMING_INDICATOR
+ * @see #EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR
+ * @see #EXTRA_EMERGENCY_ONLY
+ * @see #EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION
+ * @see #EXTRA_IS_USING_CARRIER_AGGREGATION
+ * @see #EXTRA_LTE_EARFCN_RSRP_BOOST
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
+
+ /**
+ * An int extra used with {@link #ACTION_SERVICE_STATE} which indicates voice registration
+ * state.
+ * @see android.telephony.ServiceState#STATE_EMERGENCY_ONLY
+ * @see android.telephony.ServiceState#STATE_IN_SERVICE
+ * @see android.telephony.ServiceState#STATE_OUT_OF_SERVICE
+ * @see android.telephony.ServiceState#STATE_POWER_OFF
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_VOICE_REG_STATE = "voiceRegState";
+
+ /**
+ * An int extra used with {@link #ACTION_SERVICE_STATE} which indicates data registration state.
+ * @see android.telephony.ServiceState#STATE_EMERGENCY_ONLY
+ * @see android.telephony.ServiceState#STATE_IN_SERVICE
+ * @see android.telephony.ServiceState#STATE_OUT_OF_SERVICE
+ * @see android.telephony.ServiceState#STATE_POWER_OFF
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_REG_STATE = "dataRegState";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which indicates the voice roaming
+ * type.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_VOICE_ROAMING_TYPE = "voiceRoamingType";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which indicates the data roaming
+ * type.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_ROAMING_TYPE = "dataRoamingType";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered voice operator name in long alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_OPERATOR_ALPHA_LONG = "operator-alpha-long";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered voice operator name in short alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_OPERATOR_ALPHA_SHORT = "operator-alpha-short";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} containing the MCC
+ * (Mobile Country Code, 3 digits) and MNC (Mobile Network code, 2-3 digits) for the mobile
+ * network.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_OPERATOR_NUMERIC = "operator-numeric";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered data operator name in long alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered data operator name in short alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_OPERATOR_ALPHA_SHORT = "data-operator-alpha-short";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} containing the MCC
+ * (Mobile Country Code, 3 digits) and MNC (Mobile Network code, 2-3 digits) for the
+ * data operator.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_OPERATOR_NUMERIC = "data-operator-numeric";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates whether the current
+ * network selection mode is manual.
+ * Will be {@code true} if manual mode, {@code false} if automatic mode.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_MANUAL = "manual";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the current voice
+ * radio technology.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_VOICE_RADIO_TECH = "radioTechnology";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the current data
+ * radio technology.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_RADIO_TECH = "dataRadioTechnology";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which represents concurrent service
+ * support on CDMA network.
+ * Will be {@code true} if support, {@code false} otherwise.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_CSS_INDICATOR = "cssIndicator";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the CDMA network
+ * id. {@code Integer.MAX_VALUE} if unknown.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_NETWORK_ID = "networkId";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the CDMA system id.
+ * {@code Integer.MAX_VALUE} if unknown.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_SYSTEM_ID = "systemId";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} represents the TSB-58 roaming
+ * indicator if registered on a CDMA or EVDO system or {@code -1} if not.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} represents the default roaming
+ * indicator from the PRL if registered on a CDMA or EVDO system {@code -1} if not.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates if under emergency
+ * only mode.
+ * {@code true} if in emergency only mode, {@code false} otherwise.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates whether data network
+ * registration state is roaming.
+ * {@code true} if registration indicates roaming, {@code false} otherwise
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION =
+ "isDataRoamingFromRegistration";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates if carrier
+ * aggregation is in use.
+ * {@code true} if carrier aggregation is in use, {@code false} otherwise.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_IS_USING_CARRIER_AGGREGATION = "isUsingCarrierAggregation";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} representing the offset which
+ * is reduced from the rsrp threshold while calculating signal strength level.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
+
+ /**
* The name of the extra used to define the text to be processed, as a
* CharSequence. Note that this may be a styled CharSequence, so you must use
* {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to retrieve it.
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
index c4e4e06..aaa5f19c 100644
--- a/core/java/android/content/pm/BaseParceledListSlice.java
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -50,6 +50,8 @@
private final List<T> mList;
+ private int mInlineCountLimit = Integer.MAX_VALUE;
+
public BaseParceledListSlice(List<T> list) {
mList = list;
}
@@ -135,6 +137,14 @@
}
/**
+ * Set a limit on the maximum number of entries in the array that will be included
+ * inline in the initial parcelling of this object.
+ */
+ public void setInlineCountLimit(int maxCount) {
+ mInlineCountLimit = maxCount;
+ }
+
+ /**
* Write this to another Parcel. Note that this discards the internal Parcel
* and should not be used anymore. This is so we can pass this to a Binder
* where we won't have a chance to call recycle on this.
@@ -149,7 +159,7 @@
final Class<?> listElementClass = mList.get(0).getClass();
writeParcelableCreator(mList.get(0), dest);
int i = 0;
- while (i < N && dest.dataSize() < MAX_IPC_SIZE) {
+ while (i < N && i < mInlineCountLimit && dest.dataSize() < MAX_IPC_SIZE) {
dest.writeInt(1);
final T parcelable = mList.get(i);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a493f33..50e3e68 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1688,6 +1688,10 @@
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
+ /** {@hide} */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CTS = "android.software.cts";
+
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports one or more methods of
@@ -6243,7 +6247,7 @@
* Return the {@link ComponentName} of the activity providing Settings for the Instant App
* resolver.
*
- * @see {@link android.content.intent#ACTION_EPHEMERAL_RESOLVER_SETTINGS}
+ * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
* @hide
*/
@SystemApi
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index e5d73e0..b5af766 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -59,19 +59,14 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.FuseAppLoop;
-import com.android.internal.os.FuseAppLoop.UnmountedException;
import com.android.internal.os.FuseUnavailableMountException;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -84,7 +79,6 @@
import java.util.Objects;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
-import libcore.io.IoUtils;
/**
* StorageManager is the interface to the systems storage service. The storage
@@ -186,15 +180,6 @@
private static volatile IStorageManager sStorageManager = null;
- // TODO: the location of the primary storage block varies from device to device, so we need to
- // try the most likely candidates - a long-term solution would be a device-specific vold
- // function that returns the calculated size.
- private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
- "/sys/block/mmcblk0/size",
- "/sys/block/sda/size"
- };
- private static final int INTERNAL_STORAGE_SECTOR_SIZE = 512;
-
private final Context mContext;
private final ContentResolver mResolver;
@@ -1011,38 +996,13 @@
/** {@hide} */
public static Pair<String, Long> getPrimaryStoragePathAndSize() {
- for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
- final long numberBlocks = readLong(path);
- if (numberBlocks > 0) {
- return new Pair<>(path,
- FileUtils.roundStorageSize(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
- }
- }
- return null;
+ return Pair.create(null,
+ FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace()));
}
-
/** {@hide} */
public long getPrimaryStorageSize() {
- final Pair<String, Long> pair = getPrimaryStoragePathAndSize();
- return pair == null ? 0 : pair.second.longValue();
- }
-
- private static long readLong(String path) {
- try (final FileInputStream fis = new FileInputStream(path);
- final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
- return Long.parseLong(reader.readLine());
- } catch (FileNotFoundException e) {
- // This is expected since we are trying to parse multiple paths.
- Slog.i(TAG, "readLong(): Path doesn't exist: " + path + ": " + e);
- return 0;
- } catch (NumberFormatException e) {
- Slog.e(TAG, "readLong(): Could not parse " + path + ": " + e);
- return 0;
- } catch (Exception e) {
- Slog.e(TAG, "readLong(): Unknown exception while opening " + path + ": " + e);
- return 0;
- }
+ return FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace());
}
/** @removed */
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index a280e59..9d83bd7 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -114,7 +114,7 @@
* download's content: uri is specified in the intent's data.
*/
public static final String ACTION_DOWNLOAD_COMPLETED =
- "android.intent.action.DOWNLOAD_COMPLETED";
+ DownloadManager.ACTION_DOWNLOAD_COMPLETED;
/**
* Broadcast Action: this is sent by the download manager to the app
@@ -127,7 +127,7 @@
* successfully.
*/
public static final String ACTION_NOTIFICATION_CLICKED =
- "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
+ DownloadManager.ACTION_NOTIFICATION_CLICKED;
/**
* The name of the column containing the URI of the data being downloaded.
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index fd9d4db..4deb4ab 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -72,15 +72,28 @@
*/
public static final String VARIATION_SETTINGS = "font_variation_settings";
/**
- * Constant used to request data from a font provider. The cursor returned from the query
- * should have this column populated with the int style for the resulting font. This should
- * be one of {@link android.graphics.Typeface#NORMAL},
- * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC} or
- * {@link android.graphics.Typeface#BOLD_ITALIC}
+ * DO NOT USE THIS COLUMN.
+ * This column is kept for preventing demo apps.
+ * TODO: Remove once nobody uses this column.
+ * @hide
+ * @removed
*/
public static final String STYLE = "font_style";
/**
* Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated with the int weight for the resulting font. This value
+ * should be between 100 and 900. The most common values are 400 for regular weight and 700
+ * for bold weight.
+ */
+ public static final String WEIGHT = "font_weight";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated with the int italic for the resulting font. This should
+ * be 0 for regular style and 1 for italic.
+ */
+ public static final String ITALIC = "font_italic";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
* should have this column populated to indicate the result status of the
* query. This will be checked before any other data in the cursor. Possible values are
* {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND},
@@ -274,7 +287,7 @@
.build();
try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE,
- Columns.RESULT_CODE },
+ Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
"query = ?", new String[] { request.getQuery() }, null);) {
// TODO: Should we restrict the amount of fonts that can be returned?
// TODO: Write documentation explaining that all results should be from the same family.
@@ -285,6 +298,8 @@
final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID);
final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX);
final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
+ final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT);
+ final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC);
final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
while (cursor.moveToNext()) {
resultCode = resultCodeColumnIndex != -1
@@ -313,9 +328,22 @@
? cursor.getInt(ttcIndexColumnIndex) : 0;
final String variationSettings = vsColumnIndex != -1
? cursor.getString(vsColumnIndex) : null;
- final int style = styleColumnIndex != -1
- ? cursor.getInt(styleColumnIndex) : Typeface.NORMAL;
- result.add(new FontResult(pfd, ttcIndex, variationSettings, style));
+ // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
+ int weight;
+ boolean italic;
+ if (weightColumnIndex != -1 && italicColumnIndex != -1) {
+ weight = cursor.getInt(weightColumnIndex);
+ italic = cursor.getInt(italicColumnIndex) == 1;
+ } else if (styleColumnIndex != -1) {
+ final int style = cursor.getInt(styleColumnIndex);
+ weight = (style & Typeface.BOLD) != 0 ? 700 : 400;
+ italic = (style & Typeface.ITALIC) != 0;
+ } else {
+ weight = 400;
+ italic = false;
+ }
+ result.add(
+ new FontResult(pfd, ttcIndex, variationSettings, weight, italic));
} catch (FileNotFoundException e) {
Log.e(TAG, "FileNotFoundException raised when interacting with content "
+ "provider " + authority, e);
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 6f17d0e..9f8a621 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -71,7 +71,7 @@
* Name under which a AutoFillService component publishes information about itself.
* This meta-data should reference an XML resource containing a
* <code><{@link
- * android.R.styleable#AutoFillService autofill-service}></code> tag.
+ * android.R.styleable#AutofillService autofill-service}></code> tag.
* This is a a sample XML file configuring an AutoFillService:
* <pre> <autofill-service
* android:settingsActivity="foo.bar.SettingsActivity"
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index f6d40db..0f4824e 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -36,7 +36,6 @@
import java.io.IOException;
-// TODO(b/33197203 , b/33802548): add CTS tests
/**
* {@link ServiceInfo} and meta-data about an {@link AutofillService}.
*
@@ -75,15 +74,8 @@
mServiceInfo = si;
final TypedArray metaDataArray = getMetaDataArray(pm, si);
if (metaDataArray != null) {
- // TODO(b/35956626): inline newSettingsActivity once clients migrate
- final String newSettingsActivity =
- metaDataArray.getString(R.styleable.AutofillService_settingsActivity);
- if (newSettingsActivity != null) {
- mSettingsActivity = newSettingsActivity;
- } else {
- mSettingsActivity =
- metaDataArray.getString(R.styleable.AutoFillService_settingsActivity);
- }
+ mSettingsActivity = metaDataArray
+ .getString(R.styleable.AutofillService_settingsActivity);
metaDataArray.recycle();
} else {
mSettingsActivity = null;
@@ -96,16 +88,11 @@
@Nullable
private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) {
// Check for permissions.
- // TODO(b/35956626): remove check for BIND_AUTO_FILL once clients migrate
- if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)
- && !Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
+ if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)) {
Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTOFILL);
return null;
}
- // TODO(b/35956626): remove once clients migrate
- final boolean oldStyle = !Manifest.permission.BIND_AUTOFILL.equals(si.permission);
-
// Get the AutoFill metadata, if declared.
XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA);
if (parser == null) {
@@ -141,8 +128,7 @@
return null;
}
- return oldStyle ? res.obtainAttributes(attrs, R.styleable.AutoFillService)
- : res.obtainAttributes(attrs, R.styleable.AutofillService);
+ return res.obtainAttributes(attrs, R.styleable.AutofillService);
} finally {
parser.close();
}
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index e27fa06..e77bd0d 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -23,8 +23,6 @@
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;
@@ -78,11 +76,6 @@
}
/** @hide */
- public @Nullable RemoteViews getPresentation() {
- return mPresentation;
- }
-
- /** @hide */
public @Nullable IntentSender getAuthentication() {
return mAuthentication;
}
@@ -180,15 +173,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use other setValue()
- */
- @Deprecated
- public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
- return setValue(id.getDaRealId(), value.getDaRealValue());
- }
-
- /**
* Sets the value of a field.
*
* @param id id returned by {@link
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 6213d27..95608a5 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -25,7 +25,6 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -269,26 +268,6 @@
return this;
}
-
- /**
- * @hide
- */
- // TODO(b/33197203): temporary fix to runtime crash
- public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
- throwIfDestroyed();
-
- if (ids == null || ids.length == 0) {
- return this;
- }
- if (mRequiredIds == null) {
- mRequiredIds = new AutofillId[ids.length];
- }
- for (int i = 0; i < ids.length; i++) {
- mRequiredIds[i] = ids[i].getDaRealId();
- }
- return this;
- }
-
/**
* Sets an optional description to be shown in the UI when the user is asked to save.
*
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 1e9deeb..6208c53 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -85,7 +85,7 @@
this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
spacingmult, spacingadd, includepad,
StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE,
- false /* justify */, ellipsize, ellipsizedWidth);
+ Layout.JUSTIFICATION_MODE_NONE, ellipsize, ellipsizedWidth);
}
/**
@@ -102,7 +102,7 @@
int width, Alignment align, TextDirectionHeuristic textDir,
float spacingmult, float spacingadd,
boolean includepad, int breakStrategy, int hyphenationFrequency,
- boolean justify, TextUtils.TruncateAt ellipsize,
+ int justificationMode, TextUtils.TruncateAt ellipsize,
int ellipsizedWidth) {
super((ellipsize == null)
? display
@@ -128,7 +128,7 @@
mIncludePad = includepad;
mBreakStrategy = breakStrategy;
- mJustify = justify;
+ mJustificationMode = justificationMode;
mHyphenationFrequency = hyphenationFrequency;
/*
@@ -303,7 +303,7 @@
.setEllipsize(mEllipsizeAt)
.setBreakStrategy(mBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency)
- .setJustify(mJustify);
+ .setJustificationMode(mJustificationMode);
reflowed.generate(b, false, true);
int n = reflowed.getLineCount();
// If the new layout has a blank line at the end, but it is not
@@ -811,7 +811,7 @@
private TextUtils.TruncateAt mEllipsizeAt;
private int mBreakStrategy;
private int mHyphenationFrequency;
- private boolean mJustify;
+ private int mJustificationMode;
private PackedIntVector mInts;
private PackedObjectVector<Directions> mObjects;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 53564f0..b47fce8 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -103,6 +103,21 @@
private static final ParagraphStyle[] NO_PARA_SPANS =
ArrayUtils.emptyArray(ParagraphStyle.class);
+ /** @hide */
+ @IntDef({JUSTIFICATION_MODE_NONE, JUSTIFICATION_MODE_INTER_WORD})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface JustificationMode {}
+
+ /**
+ * Value for justification mode indicating no justification.
+ */
+ public static final int JUSTIFICATION_MODE_NONE = 0;
+
+ /**
+ * Value for justification mode indicating the text is justified by stretching word spacing.
+ */
+ public static final int JUSTIFICATION_MODE_INTER_WORD = 1;
+
/**
* Return how wide a layout must be in order to display the specified text with one line per
* paragraph.
@@ -219,8 +234,8 @@
}
/** @hide */
- protected void setJustify(boolean justify) {
- mJustify = justify;
+ protected void setJustificationMode(@JustificationMode int justificationMode) {
+ mJustificationMode = justificationMode;
}
/**
@@ -272,7 +287,7 @@
}
private boolean isJustificationRequired(int lineNum) {
- if (!mJustify) return false;
+ if (mJustificationMode == JUSTIFICATION_MODE_NONE) return false;
final int lineEnd = getLineEnd(lineNum);
return lineEnd < mText.length() && mText.charAt(lineEnd - 1) != '\n';
}
@@ -2229,7 +2244,7 @@
private boolean mSpannedText;
private TextDirectionHeuristic mTextDir;
private SpanSet<LineBackgroundSpan> mLineBackgroundSpans;
- private boolean mJustify;
+ private int mJustificationMode;
public static final int DIR_LEFT_TO_RIGHT = 1;
public static final int DIR_RIGHT_TO_LEFT = -1;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 9a2e0bb..74ff6dc 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -94,7 +94,7 @@
b.mMaxLines = Integer.MAX_VALUE;
b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
- b.mJustify = false;
+ b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
b.mMeasuredText = MeasuredText.obtain();
return b;
@@ -321,15 +321,15 @@
}
/**
- * Enables or disables paragraph justification. The default value is disabled (false).
- * If the last line is too short for justification, the last line will be displayed with
- * the alignment set by {@link #setAlignment}.
+ * Set paragraph justification mode. The default value is
+ * {@link Layout#JUSTIFICATION_MODE_NONE}. If the last line is too short for justification,
+ * the last line will be displayed with the alignment set by {@link #setAlignment}.
*
- * @param justify true for enabling and false for disabling paragraph justification.
+ * @param justificationMode justification mode for the paragraph.
* @return this builder, useful for chaining.
*/
- public Builder setJustify(boolean justify) {
- mJustify = justify;
+ public Builder setJustificationMode(@JustificationMode int justificationMode) {
+ mJustificationMode = justificationMode;
return this;
}
@@ -418,7 +418,7 @@
int mHyphenationFrequency;
int[] mLeftIndents;
int[] mRightIndents;
- boolean mJustify;
+ int mJustificationMode;
Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
@@ -572,7 +572,7 @@
mLeftIndents = b.mLeftIndents;
mRightIndents = b.mRightIndents;
- setJustify(b.mJustify);
+ setJustificationMode(b.mJustificationMode);
generate(b, b.mIncludePad, b.mIncludePad);
}
@@ -693,7 +693,8 @@
nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart,
firstWidth, firstWidthLineCount, restWidth,
variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency,
- b.mJustify);
+ // TODO: Support more justification mode, e.g. letter spacing, stretching.
+ b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE);
if (mLeftIndents != null || mRightIndents != null) {
// TODO(raph) performance: it would be better to do this once per layout rather
// than once per paragraph, but that would require a change to the native
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index d25e5f0..f3c2421 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -54,7 +54,9 @@
final Rect mOtherRect = new Rect();
final Rect mBestCandidateRect = new Rect();
private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator =
- new UserSpecifiedFocusComparator();
+ new UserSpecifiedFocusComparator((v) -> v.getNextFocusForwardId());
+ private final UserSpecifiedFocusComparator mUserSpecifiedClusterComparator =
+ new UserSpecifiedFocusComparator((v) -> v.getNextClusterForwardId());
private final FocusComparator mFocusComparator = new FocusComparator();
private final ArrayList<View> mTempList = new ArrayList<View>();
@@ -150,6 +152,12 @@
@Nullable View currentCluster,
@View.FocusDirection int direction) {
View next = null;
+ if (currentCluster != null) {
+ next = findNextUserSpecifiedKeyboardNavigationCluster(root, currentCluster, direction);
+ if (next != null) {
+ return next;
+ }
+ }
final ArrayList<View> clusters = mTempList;
try {
@@ -165,6 +173,16 @@
return next;
}
+ private View findNextUserSpecifiedKeyboardNavigationCluster(View root, View currentCluster,
+ int direction) {
+ View userSetNextCluster =
+ currentCluster.findUserSetNextKeyboardNavigationCluster(root, direction);
+ if (userSetNextCluster != null && userSetNextCluster.hasFocusable()) {
+ return userSetNextCluster;
+ }
+ return null;
+ }
+
private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
// check for user specified next focus
View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
@@ -238,6 +256,13 @@
View currentCluster,
List<View> clusters,
@View.FocusDirection int direction) {
+ try {
+ // Note: This sort is stable.
+ mUserSpecifiedClusterComparator.setFocusables(clusters);
+ Collections.sort(clusters, mUserSpecifiedClusterComparator);
+ } finally {
+ mUserSpecifiedClusterComparator.recycle();
+ }
final int count = clusters.size();
switch (direction) {
@@ -802,6 +827,15 @@
private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
+ private final NextIdGetter mNextIdGetter;
+
+ public interface NextIdGetter {
+ int get(View view);
+ }
+
+ UserSpecifiedFocusComparator(NextIdGetter nextIdGetter) {
+ mNextIdGetter = nextIdGetter;
+ }
public void recycle() {
mFocusables.clear();
@@ -810,14 +844,14 @@
mOriginalOrdinal.clear();
}
- public void setFocusables(ArrayList<View> focusables) {
+ public void setFocusables(List<View> focusables) {
for (int i = focusables.size() - 1; i >= 0; i--) {
final View view = focusables.get(i);
final int id = view.getId();
if (isValidId(id)) {
mFocusables.put(id, view);
}
- final int nextId = view.getNextFocusForwardId();
+ final int nextId = mNextIdGetter.get(view);
if (isValidId(nextId)) {
mIsConnectedTo.put(nextId, true);
}
@@ -825,7 +859,7 @@
for (int i = focusables.size() - 1; i >= 0; i--) {
final View view = focusables.get(i);
- final int nextId = view.getNextFocusForwardId();
+ final int nextId = mNextIdGetter.get(view);
if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
setHeadOfChain(view);
}
@@ -838,7 +872,7 @@
private void setHeadOfChain(View head) {
for (View view = head; view != null;
- view = mFocusables.get(view.getNextFocusForwardId())) {
+ view = mFocusables.get(mNextIdGetter.get(view))) {
final View otherHead = mHeadsOfChains.get(view);
if (otherHead != null) {
if (otherHead == head) {
@@ -866,7 +900,7 @@
return -1; // first is the head, it should be first
} else if (second == firstHead) {
return 1; // second is the head, it should be first
- } else if (isValidId(first.getNextFocusForwardId())) {
+ } else if (isValidId(mNextIdGetter.get(first))) {
return -1; // first is not the end of the chain
} else {
return 1; // first is end of chain
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b12a767..4ffcd95 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -707,13 +707,16 @@
* @attr ref android.R.styleable#View_isScrollContainer
* @attr ref android.R.styleable#View_focusable
* @attr ref android.R.styleable#View_focusableInTouchMode
+ * @attr ref android.R.styleable#View_focusedByDefault
* @attr ref android.R.styleable#View_hapticFeedbackEnabled
* @attr ref android.R.styleable#View_keepScreenOn
+ * @attr ref android.R.styleable#View_keyboardNavigationCluster
* @attr ref android.R.styleable#View_layerType
* @attr ref android.R.styleable#View_layoutDirection
* @attr ref android.R.styleable#View_longClickable
* @attr ref android.R.styleable#View_minHeight
* @attr ref android.R.styleable#View_minWidth
+ * @attr ref android.R.styleable#View_nextClusterForward
* @attr ref android.R.styleable#View_nextFocusDown
* @attr ref android.R.styleable#View_nextFocusLeft
* @attr ref android.R.styleable#View_nextFocusRight
@@ -4076,7 +4079,9 @@
int mNextFocusForwardId = View.NO_ID;
/**
- * User-specified next keyboard navigation cluster.
+ * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
+ *
+ * @see #findUserSetNextKeyboardNavigationCluster(View, int)
*/
int mNextClusterForwardId = View.NO_ID;
@@ -9968,6 +9973,29 @@
return null;
}
+ /**
+ * If a user manually specified the next keyboard-navigation cluster for a particular direction,
+ * use the root to look up the view.
+ *
+ * @param root the root view of the hierarchy containing this view
+ * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
+ * @return the user-specified next cluster, or {@code null} if there is none
+ */
+ View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
+ switch (direction) {
+ case FOCUS_FORWARD:
+ if (mNextClusterForwardId == View.NO_ID) return null;
+ return findViewInsideOutShouldExist(root, mNextClusterForwardId);
+ case FOCUS_BACKWARD: {
+ if (mID == View.NO_ID) return null;
+ final int id = mID;
+ return root.findViewByPredicateInsideOut(this,
+ (Predicate<View>) t -> t.mNextClusterForwardId == id);
+ }
+ }
+ return null;
+ }
+
private View findViewInsideOutShouldExist(View root, int id) {
if (mMatchIdPredicate == null) {
mMatchIdPredicate = new MatchIdPredicate();
@@ -20780,11 +20808,18 @@
}
/**
- * Look for a child view with the given id. If this view has the given
- * id, return this view.
+ * Finds the first descendant view with the given ID, the view itself if
+ * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
+ * (< 0) or there is no matching view in the hierarchy.
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @param id The id to search for.
- * @return The view that has the given id in the hierarchy or null
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c250226..9e1ceee 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1258,15 +1258,18 @@
return;
}
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
+ int count = 0;
+ final View[] visibleChildren = new View[mChildrenCount];
+ for (int i = 0; i < mChildrenCount; ++i) {
+ final View child = mChildren[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.addKeyboardNavigationClusters(views, direction);
+ visibleChildren[count++] = child;
}
}
+ Arrays.sort(visibleChildren, 0, count, FocusFinder.getFocusComparator(this, false));
+ for (int i = 0; i < count; ++i) {
+ visibleChildren[i].addKeyboardNavigationClusters(views, direction);
+ }
}
/**
@@ -7344,6 +7347,7 @@
/** @hide */
protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
+ requestLayout();
}
/** @hide */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2e201bf..58ef0af 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4660,6 +4660,7 @@
if (cluster != null && cluster.isRootNamespace()) {
// the default cluster. Try to find a non-clustered view to focus.
if (cluster.restoreFocusNotInCluster()) {
+ playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
return true;
}
// otherwise skip to next actual cluster
@@ -4667,6 +4668,7 @@
}
if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
+ playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
return true;
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0053caa..6dd8ecf 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1308,15 +1308,22 @@
}
/**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link android.app.Activity#onCreate}. This will
- * implicitly call {@link #getDecorView} for you, with all of the
- * associated side-effects.
+ * Finds a view that was identified by the {@code android:id} XML attribute
+ * that was processed in {@link android.app.Activity#onCreate}. This will
+ * implicitly call {@link #getDecorView} with all of the associated
+ * side-effects.
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @return The view if found or null otherwise.
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
@Nullable
- public View findViewById(@IdRes int id) {
+ public <T extends View> T findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
diff --git a/core/java/android/view/autofill/AutoFillId.aidl b/core/java/android/view/autofill/AutoFillId.aidl
deleted file mode 100644
index fc57ce7..0000000
--- a/core/java/android/view/autofill/AutoFillId.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-// @deprecated TODO(b/35956626): remove once clients use AutofillId
-parcelable AutoFillId;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillId.java b/core/java/android/view/autofill/AutoFillId.java
deleted file mode 100644
index 081fb02..0000000
--- a/core/java/android/view/autofill/AutoFillId.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.view.autofill;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
-@Deprecated
-public final class AutoFillId implements Parcelable {
-
- private final AutofillId mRealId;
-
- /** @hide */
- public AutoFillId(AutofillId daRealId) {
- this.mRealId = daRealId;
- }
-
- @Override
- public int hashCode() {
- return mRealId.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- final AutoFillId other = (AutoFillId) obj;
- return mRealId.equals(other.mRealId);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mRealId, 0);
- }
-
- private AutoFillId(Parcel parcel) {
- mRealId = parcel.readParcelable(null);
- }
-
- /** @hide */
- public AutofillId getDaRealId() {
- return mRealId;
- }
-
- /** @hide */
- public static AutoFillId forDaRealId(AutofillId id) {
- return id == null ? null : new AutoFillId(id);
- }
-
- public static final Parcelable.Creator<AutoFillId> CREATOR =
- new Parcelable.Creator<AutoFillId>() {
- @Override
- public AutoFillId createFromParcel(Parcel source) {
- return new AutoFillId(source);
- }
-
- @Override
- public AutoFillId[] newArray(int size) {
- return new AutoFillId[size];
- }
- };
-}
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
deleted file mode 100644
index c508ba4..0000000
--- a/core/java/android/view/autofill/AutoFillType.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * Defines the type of a object that can be used to autofill a {@link View} so the
- * {@link android.service.autofill.AutofillService} can use the proper {@link AutofillValue} to
- * fill it.
- *
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
-@Deprecated
-public final class AutoFillType implements Parcelable {
-
- // Cached instance for types that don't have subtype; it uses the "lazy initialization holder
- // class idiom" (Effective Java, Item 71) to avoid memory utilization when autofill is not
- // enabled.
- private static class DefaultTypesHolder {
- static final AutoFillType TEXT = new AutoFillType(TYPE_TEXT);
- static final AutoFillType TOGGLE = new AutoFillType(TYPE_TOGGLE);
- static final AutoFillType LIST = new AutoFillType(TYPE_LIST);
- static final AutoFillType DATE = new AutoFillType(TYPE_DATE);
- }
-
- private static final int TYPE_TEXT = 1;
- private static final int TYPE_TOGGLE = 2;
- private static final int TYPE_LIST = 3;
- private static final int TYPE_DATE = 4;
-
- private final int mType;
-
- private AutoFillType(int type) {
- mType = type;
- }
-
- /**
- * Checks if this is a type for a text field, which is filled by a {@link CharSequence}.
- */
- public boolean isText() {
- return mType == TYPE_TEXT;
- }
-
- /**
- * Checks if this is a a type for a togglable field, which is filled by a {@code boolean}.
- */
- public boolean isToggle() {
- return mType == TYPE_TOGGLE;
- }
-
- /**
- * Checks if this is a type for a selection list field, which is filled by a {@code integer}
- * representing the element index inside the list (starting at {@code 0}.
- */
- public boolean isList() {
- return mType == TYPE_LIST;
- }
-
- /**
- * Checks if this is a type for a date and time, which is represented by a long representing
- * the number of milliseconds since the standard base time known as "the epoch", namely
- * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
- */
- public boolean isDate() {
- return mType == TYPE_DATE;
- }
-
- /////////////////////////////////////
- // Object "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- return "AutoFillType [type=" + mType + "]";
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + mType;
- 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 AutoFillType other = (AutoFillType) obj;
- if (mType != other.mType) return false;
- return true;
- }
-
- /////////////////////////////////////
- // Parcelable "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(mType);
- }
-
- private AutoFillType(Parcel parcel) {
- mType = parcel.readInt();
- }
-
- public static final Parcelable.Creator<AutoFillType> CREATOR =
- new Parcelable.Creator<AutoFillType>() {
- @Override
- public AutoFillType createFromParcel(Parcel source) {
- return new AutoFillType(source);
- }
-
- @Override
- public AutoFillType[] newArray(int size) {
- return new AutoFillType[size];
- }
- };
-
- ////////////////////
- // Factory methods //
- ////////////////////
-
- /**
- * Creates a text field type, which is filled by a {@link CharSequence}.
- *
- * <p>See {@link #isText()} for more info.
- */
- public static AutoFillType forText() {
- return DefaultTypesHolder.TEXT;
- }
-
- /**
- * Creates a type that can be toggled which is filled by a {@code boolean}.
- *
- * <p>See {@link #isToggle()} for more info.
- */
- public static AutoFillType forToggle() {
- return DefaultTypesHolder.TOGGLE;
- }
-
- /**
- * Creates a selection list, which is filled by a {@code integer} representing the element index
- * inside the list (starting at {@code 0}.
- *
- * <p>See {@link #isList()} for more info.
- */
- public static AutoFillType forList() {
- return DefaultTypesHolder.LIST;
- }
-
- /**
- * Creates a type that represents a date.
- *
- * <p>See {@link #isDate()} for more info.
- */
- public static AutoFillType forDate() {
- return DefaultTypesHolder.DATE;
- }
-}
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
deleted file mode 100644
index 4774d8f..0000000
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use AutofillValue
- */
-@Deprecated
-public final class AutoFillValue implements Parcelable {
- private final AutofillValue mRealValue;
-
- private AutoFillValue(AutofillValue daRealValue) {
- this.mRealValue = daRealValue;
- }
-
- /**
- * Gets the value to autofill a text field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
- */
- public CharSequence getTextValue() {
- return mRealValue.getTextValue();
- }
-
- /**
- * Gets the value to autofill a toggable field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
- */
- public boolean getToggleValue() {
- return mRealValue.getToggleValue();
- }
-
- /**
- * Gets the value to autofill a selection list field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
- */
- public int getListValue() {
- return mRealValue.getListValue();
- }
-
- /**
- * Gets the value to autofill a date field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
- */
- public long getDateValue() {
- return mRealValue.getDateValue();
- }
-
- /////////////////////////////////////
- // Object "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public int hashCode() {
- return mRealValue.hashCode();
- }
-
- @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;
- return mRealValue.equals(other.mRealValue);
- }
-
- @Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- return mRealValue.toString();
- }
-
- /////////////////////////////////////
- // Parcelable "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mRealValue, 0);
- }
-
- private AutoFillValue(Parcel parcel) {
- mRealValue = parcel.readParcelable(null);
- }
-
- public static final Parcelable.Creator<AutoFillValue> CREATOR =
- new Parcelable.Creator<AutoFillValue>() {
- @Override
- public AutoFillValue createFromParcel(Parcel source) {
- return new AutoFillValue(source);
- }
-
- @Override
- public AutoFillValue[] newArray(int size) {
- return new AutoFillValue[size];
- }
- };
-
- ////////////////////
- // Factory methods //
- ////////////////////
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
- */
- @Nullable
- public static AutoFillValue forText(@Nullable CharSequence value) {
- return value == null ? null : new AutoFillValue(AutofillValue.forText(value));
- }
-
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a toggable
- * field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
- */
- public static AutoFillValue forToggle(boolean value) {
- return new AutoFillValue(AutofillValue.forToggle(value));
- }
-
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a selection
- * list.
- *
- * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
- */
- public static AutoFillValue forList(int value) {
- return new AutoFillValue(AutofillValue.forList(value));
- }
-
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a date.
- *
- * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
- */
- public static AutoFillValue forDate(long date) {
- return new AutoFillValue(AutofillValue.forDate(date));
- }
-
- /** @hide */
- public static AutoFillValue forDaRealValue(AutofillValue daRealValue) {
- return new AutoFillValue(daRealValue);
- }
-
- /** @hide */
- public AutofillValue getDaRealValue() {
- return mRealValue;
- }
-}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 636fa7d..61920bd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -411,8 +411,16 @@
public abstract boolean getUseWebViewBackgroundForOverscrollBackground();
/**
- * Sets whether the WebView should save form data. The default is true.
+ * Sets whether the WebView should save form data. In Android O, the
+ * platform has implemented a fully functional Autofill feature to store
+ * form data. Therefore, the Webview form data save feature is disabled.
+ *
+ * Note that the feature will continue to be supported on older versions of
+ * Android as before.
+ *
+ * This function does not have any effect.
*/
+ @Deprecated
public abstract void setSaveFormData(boolean save);
/**
@@ -421,6 +429,7 @@
* @return whether the WebView saves form data
* @see #setSaveFormData
*/
+ @Deprecated
public abstract boolean getSaveFormData();
/**
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 87d3c7b..982c57b 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -143,6 +143,7 @@
* @return whether there is any saved data for web forms
* @see #clearFormData
*/
+ @Deprecated
public abstract boolean hasFormData();
/**
@@ -150,5 +151,6 @@
*
* @see #hasFormData
*/
+ @Deprecated
public abstract void clearFormData();
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index da00d9c..0bf2460 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1443,7 +1443,7 @@
@Override
public void requestChildFocus(View child, View focused) {
- if (focused.getRevealOnFocusHint()) {
+ if (focused != null && focused.getRevealOnFocusHint()) {
if (!mIsLayoutDirty) {
scrollToChild(focused);
} else {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 0a9e361..8fc4f50 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1468,7 +1468,7 @@
@Override
public void requestChildFocus(View child, View focused) {
- if (focused.getRevealOnFocusHint()) {
+ if (focused != null && focused.getRevealOnFocusHint()) {
if (!mIsLayoutDirty) {
scrollToChild(focused);
} else {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b383663..1b60ebc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -610,7 +610,7 @@
private int mBreakStrategy;
private int mHyphenationFrequency;
- private boolean mJustify;
+ private int mJustificationMode;
private int mMaximum = Integer.MAX_VALUE;
private int mMaxMode = LINES;
@@ -821,7 +821,7 @@
String fontFeatureSettings = null;
mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
- mJustify = false;
+ mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
final Resources.Theme theme = context.getTheme();
@@ -3738,14 +3738,15 @@
}
/**
- * Enables or disables full justification. The default value is false. If the last line is too
- * short for justification, the last line will be displayed with the alignment set by
- * {@link android.view.View#setTextAlignment}.
+ * Set justification mode. The default value is {@link Layout#JUSTIFICATION_MODE_NONE}. If the
+ * last line is too short for justification, the last line will be displayed with the
+ * alignment set by {@link android.view.View#setTextAlignment}.
*
- * @see #getJustify()
+ * @see #getJustificationMode()
*/
- public void setJustify(boolean justify) {
- mJustify = justify;
+ @Layout.JustificationMode
+ public void setJustificationMode(@Layout.JustificationMode int justificationMode) {
+ mJustificationMode = justificationMode;
if (mLayout != null) {
nullLayouts();
requestLayout();
@@ -3754,12 +3755,12 @@
}
/**
- * @return true if currently paragraph justification is enabled.
+ * @return true if currently paragraph justification mode.
*
- * @see #setJustify(boolean)
+ * @see #setJustificationMode(int)
*/
- public boolean getJustify() {
- return mJustify;
+ public @Layout.JustificationMode int getJustificationMode() {
+ return mJustificationMode;
}
/**
@@ -7683,7 +7684,7 @@
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency)
- .setJustify(mJustify)
+ .setJustificationMode(mJustificationMode)
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
if (shouldEllipsize) {
builder.setEllipsize(mEllipsize)
@@ -7725,7 +7726,7 @@
if (mText instanceof Spannable) {
result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth,
alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad,
- mBreakStrategy, mHyphenationFrequency, mJustify,
+ mBreakStrategy, mHyphenationFrequency, mJustificationMode,
getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth);
} else {
if (boring == UNKNOWN_BORING) {
@@ -7775,7 +7776,7 @@
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency)
- .setJustify(mJustify)
+ .setJustificationMode(mJustificationMode)
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
if (shouldEllipsize) {
builder.setEllipsize(effectiveEllipsize)
@@ -8115,7 +8116,7 @@
.setIncludePad(getIncludeFontPadding())
.setBreakStrategy(getBreakStrategy())
.setHyphenationFrequency(getHyphenationFrequency())
- .setJustify(getJustify())
+ .setJustificationMode(getJustificationMode())
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
.setTextDirection(getTextDirectionHeuristic());
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index f987a9f..caf35b3 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -55,8 +55,8 @@
in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
- ParceledListSlice getInstalledProvidersForProfile(int categoryFilter,
- int profileId);
+ ParceledListSlice getInstalledProvidersForProfile(int categoryFilter, int profileId,
+ String packageName);
AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
boolean hasBindAppWidgetPermission(in String packageName, int userId);
void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 4e68602..3010dc1 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -245,8 +245,7 @@
}
sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
- addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
- return true;
+ return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
}
static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index a77ed62..214d97c 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -10,6 +10,14 @@
using namespace android::uirenderer;
+/**
+ * By default Skia gradients will interpolate their colors in unpremul space
+ * and then premultiply each of the results. We must set this flag to preserve
+ * backwards compatiblity by premultiplying the colors of the gradient first,
+ * and then interpolating between them.
+ */
+static const uint32_t sGradientShaderFlags = SkGradientShader::kInterpolateColorsInPremul_Flag;
+
static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
if (NULL == ptr) {
doThrowIAE(env);
@@ -60,11 +68,18 @@
}
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
- sk_sp<SkShader> shader = image->makeShader(
- (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY, matrix);
+ sk_sp<SkShader> baseShader = image->makeShader(
+ (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY);
- ThrowIAE_IfNull(env, shader.get());
- return reinterpret_cast<jlong>(shader.release());
+ SkShader* shader;
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
+
+ ThrowIAE_IfNull(env, shader);
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -87,9 +102,16 @@
#error Need to convert float array to SkScalar array before calling the following function.
#endif
- SkShader* shader = SkGradientShader::MakeLinear(pts,
+ sk_sp<SkShader> baseShader(SkGradientShader::MakeLinear(pts,
reinterpret_cast<const SkColor*>(colorValues), pos, count,
- static_cast<SkShader::TileMode>(tileMode), /* flags */ 0, matrix).release();
+ static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL));
+
+ SkShader* shader;
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
ThrowIAE_IfNull(env, shader);
@@ -108,8 +130,15 @@
colors[0] = color0;
colors[1] = color1;
- SkShader* s = SkGradientShader::MakeLinear(pts, colors, NULL, 2,
- (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
+ sk_sp<SkShader> baseShader(SkGradientShader::MakeLinear(pts, colors, NULL, 2,
+ static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL));
+
+ SkShader* s;
+ if (matrix) {
+ s = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ s = baseShader.release();
+ }
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
@@ -133,9 +162,17 @@
#error Need to convert float array to SkScalar array before calling the following function.
#endif
- SkShader* shader = SkGradientShader::MakeRadial(center, radius,
+ sk_sp<SkShader> baseShader = SkGradientShader::MakeRadial(center, radius,
reinterpret_cast<const SkColor*>(colorValues), pos, count,
- static_cast<SkShader::TileMode>(tileMode), /* flags */ 0, matrix).release();
+ static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL);
+
+ SkShader* shader;
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
+
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
JNI_ABORT);
@@ -153,10 +190,17 @@
colors[0] = color0;
colors[1] = color1;
- SkShader* s = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2,
- (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
- ThrowIAE_IfNull(env, s);
- return reinterpret_cast<jlong>(s);
+ sk_sp<SkShader> baseShader = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2,
+ static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL);
+
+ SkShader* shader;
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
+ ThrowIAE_IfNull(env, shader);
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////
@@ -174,8 +218,17 @@
#error Need to convert float array to SkScalar array before calling the following function.
#endif
- SkShader* shader = SkGradientShader::MakeSweep(x, y,
- reinterpret_cast<const SkColor*>(colors), pos, count, /* flags */ 0, matrix).release();
+ sk_sp<SkShader> baseShader = SkGradientShader::MakeSweep(x, y,
+ reinterpret_cast<const SkColor*>(colors), pos, count,
+ sGradientShaderFlags, NULL);
+
+ SkShader* shader;
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
+
env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
JNI_ABORT);
ThrowIAE_IfNull(env, shader);
@@ -188,10 +241,18 @@
SkColor colors[2];
colors[0] = color0;
colors[1] = color1;
- SkShader* s = SkGradientShader::MakeSweep(x, y, colors, NULL, 2,
- /* flags */ 0, matrix).release();
- ThrowIAE_IfNull(env, s);
- return reinterpret_cast<jlong>(s);
+
+ sk_sp<SkShader> baseShader = SkGradientShader::MakeSweep(x, y, colors,
+ NULL, 2, sGradientShaderFlags, NULL);
+
+ SkShader* shader;
+ if (matrix) {
+ shader = baseShader->makeWithLocalMatrix(*matrix).release();
+ } else {
+ shader = baseShader.release();
+ }
+ ThrowIAE_IfNull(env, shader);
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 80f9d57..7121194 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -182,7 +182,7 @@
err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
if (err != NO_ERROR) return err;
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
uint32_t grallocBufWidth = buf->getWidth();
uint32_t grallocBufHeight = buf->getHeight();
uint32_t grallocBufStride = buf->getStride();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e7a447c..7922250 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -528,6 +528,7 @@
<protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
<protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
<protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
+ <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
<protected-broadcast android:name="android.content.pm.action.SESSION_COMMITTED" />
<protected-broadcast android:name="android.os.action.USER_RESTRICTIONS_CHANGED" />
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index a165621..5a2bf4e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -17,27 +17,24 @@
<NotificationHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:theme="@style/Theme.Material.Notification"
android:id="@+id/notification_header"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="@dimen/notification_header_height"
android:clipChildren="false"
- android:paddingTop="@dimen/notification_header_padding_top"
- android:paddingBottom="@dimen/notification_header_padding_bottom"
- android:layout_marginBottom="5dp"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="16dp">
+ style="?attr/notificationHeaderStyle">
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
- android:layout_width="@dimen/notification_header_icon_size"
- android:layout_height="@dimen/notification_header_icon_size"
+ android:layout_width="?attr/notificationHeaderIconSize"
+ android:layout_height="?attr/notificationHeaderIconSize"
android:layout_marginEnd="3dp"
/>
<TextView
android:id="@+id/app_name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="3dp"
android:layout_marginEnd="2dp"
android:singleLine="true"
@@ -46,7 +43,7 @@
android:id="@+id/header_text_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/notification_header_divider_symbol"
@@ -55,7 +52,7 @@
android:id="@+id/header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:visibility="gone"
@@ -64,7 +61,7 @@
android:id="@+id/time_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/notification_header_divider_symbol"
diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml
index e2c68b5..026bc6e 100644
--- a/core/res/res/layout/notification_template_material_ambient.xml
+++ b/core/res/res/layout/notification_template_material_ambient.xml
@@ -20,8 +20,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="ambient"
+ android:paddingStart="@dimen/notification_extra_margin_ambient"
+ android:paddingEnd="@dimen/notification_extra_margin_ambient"
>
- <include layout="@layout/notification_template_header" />
+ <include layout="@layout/notification_template_header"
+ android:theme="@style/Theme.Material.Notification.Ambient" />
<LinearLayout
android:id="@+id/notification_action_list_margin_target"
@@ -52,7 +55,7 @@
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:textSize="20sp"
- android:textColor="#e6fafafa"
+ android:textColor="#ffffffff"
/>
<TextView android:id="@+id/text"
android:layout_width="match_parent"
@@ -63,7 +66,7 @@
android:gravity="top"
android:visibility="gone"
android:textSize="16sp"
- android:textColor="#ccfafafa"
+ android:textColor="#eeffffff"
android:layout_marginTop="4dp"
/>
</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ee73b69..d26d952 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7739,13 +7739,6 @@
<attr name="settingsActivity" />
</declare-styleable>
- <!-- TODO(b/35956626): temporary until clients change to AutofillService -->
- <declare-styleable name="AutoFillService">
- <!-- Fully qualified class name of an activity that allows the user to modify
- the settings for this service. -->
- <attr name="settingsActivity" />
- </declare-styleable>
-
<!-- =============================== -->
<!-- Contacts meta-data attributes -->
<!-- =============================== -->
@@ -8635,5 +8628,12 @@
<attr name="stackFromEnd" format="boolean" />
</declare-styleable>
+ <!-- @hide -->
+ <declare-styleable name="NotificationTheme">
+ <attr name="notificationHeaderStyle" format="reference" />
+ <attr name="notificationHeaderTextAppearance" format="reference" />
+ <attr name="notificationHeaderIconSize" format="dimension" />
+ </declare-styleable>
+
<attr name="lockPatternStyle" format="reference" />
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 85ecaff..221e308 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2822,4 +2822,11 @@
<!-- Whether the device supports quick settings and its associated APIs -->
<bool name="config_quickSettingsSupported">true</bool>
+
+ <!-- The component name, flattened to a string, for the default autofill service
+ to enabled for an user. This service must be trusted, as it can be activated
+ without explicit consent of the user. If no autofill service with the
+ specified name exists on the device, autofill will be disabled by default.
+ -->
+ <string name="config_defaultAutofillService" translatable="false"></string>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 1129647..c5316c6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -165,6 +165,9 @@
-->
<dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
+ <!-- The additional margin on the sides of the ambient view. -->
+ <dimen name="notification_extra_margin_ambient">16dp</dimen>
+
<!-- The height of the notification action list -->
<dimen name="notification_action_list_height">56dp</dimen>
@@ -188,6 +191,9 @@
<!-- size (width and height) of the icon in the notification header -->
<dimen name="notification_header_icon_size">18dp</dimen>
+ <!-- size (width and height) of the icon in the notification header -->
+ <dimen name="notification_header_icon_size_ambient">20dp</dimen>
+
<!-- Height of a small notification in the status bar -->
<dimen name="notification_min_height">92dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 831cf89..11286f3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3172,7 +3172,7 @@
<string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
<!-- Notification title when an application is displaying ui on-top of other apps
[CHAR LIMIT=30] -->
- <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps.</string>
+ <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
<!-- Notification body when an application is displaying ui on-top of other apps
[CHAR LIMIT=NONE] -->
<string name="alert_windows_notification_message">If you don’t want <xliff:g id="name" example="Google Maps">%s</xliff:g> to use this feature, tap to open settings and turn it off.</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8f061a3..ec16611 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -488,6 +488,10 @@
<style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />
+ <style name="TextAppearance.Material.Notification.Info.Ambient">
+ <item name="textSize">@dimen/notification_text_size</item>
+ </style>
+
<style name="TextAppearance.Material.Notification.Emphasis">
<item name="textColor">#66000000</item>
</style>
@@ -1283,4 +1287,12 @@
<style name="DialogWindowTitle.Material.Light" />
+ <style name="Notification.Header" parent="">
+ <item name="paddingTop">@dimen/notification_header_padding_top</item>
+ <item name="paddingBottom">@dimen/notification_header_padding_bottom</item>
+ <item name="layout_marginBottom">5dp</item>
+ <item name="paddingStart">@dimen/notification_content_margin_start</item>
+ <item name="paddingEnd">16dp</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ae05a69..c12116a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2944,6 +2944,7 @@
<java-symbol type="string" name="notification_channel_alerts" />
<java-symbol type="string" name="notification_channel_retail_mode" />
<java-symbol type="string" name="notification_channel_usb" />
+ <java-symbol type="string" name="config_defaultAutofillService" />
<!-- ETWS primary messages -->
<java-symbol type="string" name="etws_primary_default_message_earthquake" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 008c817..9dafa7a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1321,6 +1321,19 @@
<item name="windowNoTitle">true</item>
</style>
+ <!-- Theme for inflating notifications -->
+ <style name="Theme.Material.Notification" parent="">
+ <item name="notificationHeaderStyle">@style/Notification.Header</item>
+ <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info</item>
+ <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size</item>
+ </style>
+
+ <!-- Theme for inflating ambient notification -->
+ <style name="Theme.Material.Notification.Ambient">
+ <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info.Ambient</item>
+ <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size_ambient</item>
+ </style>
+
<!-- Default theme for Settings and activities launched from Settings. -->
<style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar">
<item name="colorPrimary">@color/primary_material_settings_light</item>
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
index 6c1ce44..22bfea1 100644
--- a/core/res/res/xml/time_zones_by_country.xml
+++ b/core/res/res/xml/time_zones_by_country.xml
@@ -31,11 +31,11 @@
<!-- ANTIGUA AND BARBUDA, -4:00 -->
- <timezone code="ag">America/Port_of_Spain</timezone>
+ <timezone code="ag">America/Antigua</timezone>
<!-- ANGUILLA, -4:00 -->
- <timezone code="ai">America/Port_of_Spain</timezone>
+ <timezone code="ai">America/Anguilla</timezone>
<!-- ALBANIA, 1:00 -->
@@ -47,11 +47,11 @@
<!-- ANGOLA, 1:00 -->
- <timezone code="ao">Africa/Lagos</timezone>
+ <timezone code="ao">Africa/Luanda</timezone>
<!-- ANTARCTICA, 12:00 -->
- <timezone code="aq">Pacific/Auckland</timezone>
+ <timezone code="aq">Antarctica/McMurdo</timezone>
<!-- ANTARCTICA, 10:00 -->
@@ -144,11 +144,11 @@
<!-- ARUBA, -4:00 -->
- <timezone code="aw">America/Curacao</timezone>
+ <timezone code="aw">America/Aruba</timezone>
<!-- ALAND ISLANDS, 2:00 -->
- <timezone code="ax">Europe/Helsinki</timezone>
+ <timezone code="ax">Europe/Mariehamn</timezone>
<!-- AZERBAIJAN, 4:00 -->
@@ -156,7 +156,7 @@
<!-- BOSNIA AND HERZEGOVINA, 1:00 -->
- <timezone code="ba">Europe/Belgrade</timezone>
+ <timezone code="ba">Europe/Sarajevo</timezone>
<!-- BARBADOS, -4:00 -->
@@ -172,7 +172,7 @@
<!-- BURKINA FASO, 0:00 -->
- <timezone code="bf">Africa/Abidjan</timezone>
+ <timezone code="bf">Africa/Ouagadougou</timezone>
<!-- BULGARIA, 2:00 -->
@@ -180,19 +180,19 @@
<!-- BAHRAIN, 3:00 -->
- <timezone code="bh">Asia/Qatar</timezone>
+ <timezone code="bh">Asia/Bahrain</timezone>
<!-- BURUNDI, 2:00 -->
- <timezone code="bi">Africa/Maputo</timezone>
+ <timezone code="bi">Africa/Bujumbura</timezone>
<!-- BENIN, 1:00 -->
- <timezone code="bj">Africa/Lagos</timezone>
+ <timezone code="bj">Africa/Porto-Novo</timezone>
<!-- Saint Barthélemy, -4:00 -->
- <timezone code="bl">America/Port_of_Spain</timezone>
+ <timezone code="bl">America/St_Barthelemy</timezone>
<!-- BERMUDA, -4:00 -->
@@ -208,7 +208,7 @@
<!-- Caribbean Netherlands, -4:00 -->
- <timezone code="bq">America/Curacao</timezone>
+ <timezone code="bq">America/Kralendijk</timezone>
<!-- BRAZIL, -2:00 -->
@@ -248,7 +248,7 @@
<!-- BOTSWANA, 2:00 -->
- <timezone code="bw">Africa/Maputo</timezone>
+ <timezone code="bw">Africa/Gaborone</timezone>
<!-- BELARUS, 3:00 -->
@@ -310,19 +310,19 @@
<!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 2:00 -->
- <timezone code="cd">Africa/Maputo</timezone>
+ <timezone code="cd">Africa/Lubumbashi</timezone>
<!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 1:00 -->
- <timezone code="cd">Africa/Lagos</timezone>
+ <timezone code="cd">Africa/Kinshasa</timezone>
<!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
- <timezone code="cf">Africa/Lagos</timezone>
+ <timezone code="cf">Africa/Bangui</timezone>
<!-- CONGO, 1:00 -->
- <timezone code="cg">Africa/Lagos</timezone>
+ <timezone code="cg">Africa/Brazzaville</timezone>
<!-- SWITZERLAND, 1:00 -->
@@ -350,7 +350,7 @@
<!-- CAMEROON, 1:00 -->
- <timezone code="cm">Africa/Lagos</timezone>
+ <timezone code="cm">Africa/Douala</timezone>
<!-- CHINA, 8:00 -->
@@ -388,6 +388,10 @@
<timezone code="cy">Asia/Nicosia</timezone>
+ <!-- CYPRUS, 3:00 -->
+
+ <timezone code="cy">Asia/Famagusta</timezone>
+
<!-- CZECH REPUBLIC, 1:00 -->
<timezone code="cz">Europe/Prague</timezone>
@@ -395,11 +399,11 @@
<!-- GERMANY, 1:00 -->
<timezone code="de">Europe/Berlin</timezone>
- <timezone code="de">Europe/Zurich</timezone>
+ <timezone code="de">Europe/Busingen</timezone>
<!-- DJIBOUTI, 3:00 -->
- <timezone code="dj">Africa/Nairobi</timezone>
+ <timezone code="dj">Africa/Djibouti</timezone>
<!-- DENMARK, 1:00 -->
@@ -407,7 +411,7 @@
<!-- DOMINICA, -4:00 -->
- <timezone code="dm">America/Port_of_Spain</timezone>
+ <timezone code="dm">America/Dominica</timezone>
<!-- DOMINICAN REPUBLIC, -4:00 -->
@@ -439,7 +443,7 @@
<!-- ERITREA, 3:00 -->
- <timezone code="er">Africa/Nairobi</timezone>
+ <timezone code="er">Africa/Asmara</timezone>
<!-- SPAIN, 1:00 -->
@@ -452,7 +456,7 @@
<!-- ETHIOPIA, 3:00 -->
- <timezone code="et">Africa/Nairobi</timezone>
+ <timezone code="et">Africa/Addis_Ababa</timezone>
<!-- FINLAND, 2:00 -->
@@ -468,7 +472,7 @@
<!-- MICRONESIA, FEDERATED STATES OF, 11:00 -->
- <timezone code="fm">Pacific/Ponape</timezone>
+ <timezone code="fm">Pacific/Pohnpei</timezone>
<timezone code="fm">Pacific/Kosrae</timezone>
<!-- MICRONESIA, FEDERATED STATES OF, 10:00 -->
@@ -485,7 +489,7 @@
<!-- GABON, 1:00 -->
- <timezone code="ga">Africa/Lagos</timezone>
+ <timezone code="ga">Africa/Libreville</timezone>
<!-- UNITED KINGDOM, 0:00 -->
@@ -493,7 +497,7 @@
<!-- GRENADA, -4:00 -->
- <timezone code="gd">America/Port_of_Spain</timezone>
+ <timezone code="gd">America/Grenada</timezone>
<!-- GEORGIA, 4:00 -->
@@ -505,7 +509,7 @@
<!-- GUERNSEY, 0:00 -->
- <timezone code="gg">Europe/London</timezone>
+ <timezone code="gg">Europe/Guernsey</timezone>
<!-- GHANA, 0:00 -->
@@ -533,19 +537,19 @@
<!-- GAMBIA, 0:00 -->
- <timezone code="gm">Africa/Abidjan</timezone>
+ <timezone code="gm">Africa/Banjul</timezone>
<!-- GUINEA, 0:00 -->
- <timezone code="gn">Africa/Abidjan</timezone>
+ <timezone code="gn">Africa/Conakry</timezone>
<!-- GUADELOUPE, -4:00 -->
- <timezone code="gp">America/Port_of_Spain</timezone>
+ <timezone code="gp">America/Guadeloupe</timezone>
<!-- EQUATORIAL GUINEA, 1:00 -->
- <timezone code="gq">Africa/Lagos</timezone>
+ <timezone code="gq">Africa/Malabo</timezone>
<!-- GREECE, 2:00 -->
@@ -581,7 +585,7 @@
<!-- CROATIA, 1:00 -->
- <timezone code="hr">Europe/Belgrade</timezone>
+ <timezone code="hr">Europe/Zagreb</timezone>
<!-- HAITI, -5:00 -->
@@ -614,7 +618,7 @@
<!-- ISLE OF MAN, 0:00 -->
- <timezone code="im">Europe/London</timezone>
+ <timezone code="im">Europe/Isle_of_Man</timezone>
<!-- INDIA, 5:30 -->
@@ -642,7 +646,7 @@
<!-- JERSEY, 0:00 -->
- <timezone code="je">Europe/London</timezone>
+ <timezone code="je">Europe/Jersey</timezone>
<!-- JAMAICA, -5:00 -->
@@ -666,7 +670,7 @@
<!-- CAMBODIA, 7:00 -->
- <timezone code="kh">Asia/Bangkok</timezone>
+ <timezone code="kh">Asia/Phnom_Penh</timezone>
<!-- KIRIBATI, 14:00 -->
@@ -682,11 +686,11 @@
<!-- COMOROS, 3:00 -->
- <timezone code="km">Africa/Nairobi</timezone>
+ <timezone code="km">Indian/Comoro</timezone>
<!-- SAINT KITTS AND NEVIS, -4:00 -->
- <timezone code="kn">America/Port_of_Spain</timezone>
+ <timezone code="kn">America/St_Kitts</timezone>
<!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
@@ -698,11 +702,11 @@
<!-- KUWAIT, 3:00 -->
- <timezone code="kw">Asia/Riyadh</timezone>
+ <timezone code="kw">Asia/Kuwait</timezone>
<!-- CAYMAN ISLANDS, -5:00 -->
- <timezone code="ky">America/Panama</timezone>
+ <timezone code="ky">America/Cayman</timezone>
<!-- KAZAKHSTAN, 6:00 -->
@@ -714,10 +718,11 @@
<timezone code="kz">Asia/Aqtau</timezone>
<timezone code="kz">Asia/Oral</timezone>
<timezone code="kz">Asia/Aqtobe</timezone>
+ <timezone code="kz">Asia/Atyrau</timezone>
<!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
- <timezone code="la">Asia/Bangkok</timezone>
+ <timezone code="la">Asia/Vientiane</timezone>
<!-- LEBANON, 2:00 -->
@@ -725,11 +730,11 @@
<!-- SAINT LUCIA, -4:00 -->
- <timezone code="lc">America/Port_of_Spain</timezone>
+ <timezone code="lc">America/St_Lucia</timezone>
<!-- LIECHTENSTEIN, 1:00 -->
- <timezone code="li">Europe/Zurich</timezone>
+ <timezone code="li">Europe/Vaduz</timezone>
<!-- SRI LANKA, 5:30 -->
@@ -741,7 +746,7 @@
<!-- LESOTHO, 2:00 -->
- <timezone code="ls">Africa/Johannesburg</timezone>
+ <timezone code="ls">Africa/Maseru</timezone>
<!-- LITHUANIA, 2:00 -->
@@ -773,15 +778,15 @@
<!-- MONTENEGRO, 1:00 -->
- <timezone code="me">Europe/Belgrade</timezone>
+ <timezone code="me">Europe/Podgorica</timezone>
<!-- Collectivity of Saint Martin, -4:00 -->
- <timezone code="mf">America/Port_of_Spain</timezone>
+ <timezone code="mf">America/Marigot</timezone>
<!-- MADAGASCAR, 3:00 -->
- <timezone code="mg">Africa/Nairobi</timezone>
+ <timezone code="mg">Indian/Antananarivo</timezone>
<!-- MARSHALL ISLANDS, 12:00 -->
@@ -790,11 +795,11 @@
<!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
- <timezone code="mk">Europe/Belgrade</timezone>
+ <timezone code="mk">Europe/Skopje</timezone>
<!-- MALI, 0:00 -->
- <timezone code="ml">Africa/Abidjan</timezone>
+ <timezone code="ml">Africa/Bamako</timezone>
<!-- MYANMAR, 6:30 -->
@@ -815,7 +820,7 @@
<!-- NORTHERN MARIANA ISLANDS, 10:00 -->
- <timezone code="mp">Pacific/Guam</timezone>
+ <timezone code="mp">Pacific/Saipan</timezone>
<!-- MARTINIQUE, -4:00 -->
@@ -823,11 +828,11 @@
<!-- MAURITANIA, 0:00 -->
- <timezone code="mr">Africa/Abidjan</timezone>
+ <timezone code="mr">Africa/Nouakchott</timezone>
<!-- MONTSERRAT, -4:00 -->
- <timezone code="ms">America/Port_of_Spain</timezone>
+ <timezone code="ms">America/Montserrat</timezone>
<!-- MALTA, 1:00 -->
@@ -843,7 +848,7 @@
<!-- MALAWI, 2:00 -->
- <timezone code="mw">Africa/Maputo</timezone>
+ <timezone code="mw">Africa/Blantyre</timezone>
<!-- MEXICO, -6:00 -->
@@ -887,7 +892,7 @@
<!-- NIGER, 1:00 -->
- <timezone code="ne">Africa/Lagos</timezone>
+ <timezone code="ne">Africa/Niamey</timezone>
<!-- NORFOLK ISLAND, 11:30 -->
@@ -911,7 +916,7 @@
<!-- NEPAL, 5:45 -->
- <timezone code="np">Asia/Katmandu</timezone>
+ <timezone code="np">Asia/Kathmandu</timezone>
<!-- NAURU, 12:00 -->
@@ -931,7 +936,7 @@
<!-- OMAN, 4:00 -->
- <timezone code="om">Asia/Dubai</timezone>
+ <timezone code="om">Asia/Muscat</timezone>
<!-- PANAMA, -5:00 -->
@@ -1070,6 +1075,7 @@
<timezone code="ru">Europe/Samara</timezone>
<timezone code="ru">Europe/Astrakhan</timezone>
<timezone code="ru">Europe/Ulyanovsk</timezone>
+ <timezone code="ru">Europe/Saratov</timezone>
<!-- RUSSIAN FEDERATION, 3:00 -->
@@ -1084,7 +1090,7 @@
<!-- RWANDA, 2:00 -->
- <timezone code="rw">Africa/Maputo</timezone>
+ <timezone code="rw">Africa/Kigali</timezone>
<!-- SAUDI ARABIA, 3:00 -->
@@ -1112,35 +1118,35 @@
<!-- SAINT HELENA, 0:00 -->
- <timezone code="sh">Africa/Abidjan</timezone>
+ <timezone code="sh">Atlantic/St_Helena</timezone>
<!-- SLOVENIA, 1:00 -->
- <timezone code="si">Europe/Belgrade</timezone>
+ <timezone code="si">Europe/Ljubljana</timezone>
<!-- SVALBARD AND JAN MAYEN, 1:00 -->
- <timezone code="sj">Europe/Oslo</timezone>
+ <timezone code="sj">Arctic/Longyearbyen</timezone>
<!-- SLOVAKIA, 1:00 -->
- <timezone code="sk">Europe/Prague</timezone>
+ <timezone code="sk">Europe/Bratislava</timezone>
<!-- SIERRA LEONE, 0:00 -->
- <timezone code="sl">Africa/Abidjan</timezone>
+ <timezone code="sl">Africa/Freetown</timezone>
<!-- SAN MARINO, 1:00 -->
- <timezone code="sm">Europe/Rome</timezone>
+ <timezone code="sm">Europe/San_Marino</timezone>
<!-- SENEGAL, 0:00 -->
- <timezone code="sn">Africa/Abidjan</timezone>
+ <timezone code="sn">Africa/Dakar</timezone>
<!-- SOMALIA, 3:00 -->
- <timezone code="so">Africa/Nairobi</timezone>
+ <timezone code="so">Africa/Mogadishu</timezone>
<!-- SURINAME, -3:00 -->
@@ -1148,11 +1154,11 @@
<!-- South Sudan, 3:00 -->
- <timezone code="ss">Africa/Khartoum</timezone>
+ <timezone code="ss">Africa/Juba</timezone>
<!-- SAO TOME AND PRINCIPE, 0:00 -->
- <timezone code="st">Africa/Abidjan</timezone>
+ <timezone code="st">Africa/Sao_Tome</timezone>
<!-- EL SALVADOR, -6:00 -->
@@ -1160,7 +1166,7 @@
<!-- Sint Maarten, -4:00 -->
- <timezone code="sx">America/Curacao</timezone>
+ <timezone code="sx">America/Lower_Princes</timezone>
<!-- SYRIAN ARAB REPUBLIC, 2:00 -->
@@ -1168,7 +1174,7 @@
<!-- SWAZILAND, 2:00 -->
- <timezone code="sz">Africa/Johannesburg</timezone>
+ <timezone code="sz">Africa/Mbabane</timezone>
<!-- TURKS AND CAICOS ISLANDS, -4:00 -->
@@ -1182,13 +1188,9 @@
<timezone code="tf">Indian/Kerguelen</timezone>
- <!-- FRENCH SOUTHERN TERRITORIES, 4:00 -->
-
- <timezone code="tf">Indian/Reunion</timezone>
-
<!-- TOGO, 0:00 -->
- <timezone code="tg">Africa/Abidjan</timezone>
+ <timezone code="tg">Africa/Lome</timezone>
<!-- THAILAND, 7:00 -->
@@ -1236,7 +1238,7 @@
<!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
- <timezone code="tz">Africa/Nairobi</timezone>
+ <timezone code="tz">Africa/Dar_es_Salaam</timezone>
<!-- UKRAINE, 2:00 -->
@@ -1246,19 +1248,15 @@
<!-- UGANDA, 3:00 -->
- <timezone code="ug">Africa/Nairobi</timezone>
+ <timezone code="ug">Africa/Kampala</timezone>
<!-- UNITED STATES MINOR OUTLYING ISLANDS, 12:00 -->
<timezone code="um">Pacific/Wake</timezone>
- <!-- UNITED STATES MINOR OUTLYING ISLANDS, -10:00 -->
-
- <timezone code="um">Pacific/Honolulu</timezone>
-
<!-- UNITED STATES MINOR OUTLYING ISLANDS, -11:00 -->
- <timezone code="um">Pacific/Pago_Pago</timezone>
+ <timezone code="um">Pacific/Midway</timezone>
<!-- UNITED STATES, -5:00 -->
@@ -1318,11 +1316,11 @@
<!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
- <timezone code="va">Europe/Rome</timezone>
+ <timezone code="va">Europe/Vatican</timezone>
<!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
- <timezone code="vc">America/Port_of_Spain</timezone>
+ <timezone code="vc">America/St_Vincent</timezone>
<!-- VENEZUELA, -4:00 -->
@@ -1330,16 +1328,15 @@
<!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
- <timezone code="vg">America/Port_of_Spain</timezone>
+ <timezone code="vg">America/Tortola</timezone>
<!-- VIRGIN ISLANDS, U.S., -4:00 -->
- <timezone code="vi">America/Port_of_Spain</timezone>
+ <timezone code="vi">America/St_Thomas</timezone>
<!-- VIET NAM, 7:00 -->
<timezone code="vn">Asia/Ho_Chi_Minh</timezone>
- <timezone code="vn">Asia/Bangkok</timezone>
<!-- VANUATU, 11:00 -->
@@ -1355,11 +1352,11 @@
<!-- YEMEN, 3:00 -->
- <timezone code="ye">Asia/Riyadh</timezone>
+ <timezone code="ye">Asia/Aden</timezone>
<!-- MAYOTTE, 3:00 -->
- <timezone code="yt">Africa/Nairobi</timezone>
+ <timezone code="yt">Indian/Mayotte</timezone>
<!-- SOUTH AFRICA, 2:00 -->
@@ -1367,9 +1364,9 @@
<!-- ZAMBIA, 2:00 -->
- <timezone code="zm">Africa/Maputo</timezone>
+ <timezone code="zm">Africa/Lusaka</timezone>
<!-- ZIMBABWE, 2:00 -->
- <timezone code="zw">Africa/Maputo</timezone>
+ <timezone code="zw">Africa/Harare</timezone>
</timezones>
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index 6820e92..1dd3ef6 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -94,7 +94,8 @@
FontResult fontResult = resultList.get(0);
assertEquals(TestFontsProvider.TTC_INDEX, fontResult.getTtcIndex());
assertEquals(TestFontsProvider.VARIATION_SETTINGS, fontResult.getFontVariationSettings());
- assertEquals(TestFontsProvider.STYLE, fontResult.getStyle());
+ assertEquals(TestFontsProvider.NORMAL_WEIGHT, fontResult.getWeight());
+ assertEquals(TestFontsProvider.ITALIC, fontResult.getItalic());
assertNotNull(fontResult.getFileDescriptor());
}
@@ -115,7 +116,8 @@
FontResult fontResult = resultList.get(0);
assertEquals(0, fontResult.getTtcIndex());
assertNull(fontResult.getFontVariationSettings());
- assertEquals(Typeface.NORMAL, fontResult.getStyle());
+ assertEquals(400, fontResult.getWeight());
+ assertFalse(fontResult.getItalic());
assertNotNull(fontResult.getFileDescriptor());
}
@@ -146,10 +148,10 @@
public void testGetFontFromProvider_resultFontNotFoundSecondRow() {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0,
FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
mProvider.setCustomCursor(cursor);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
@@ -160,13 +162,12 @@
public void testGetFontFromProvider_resultFontNotFoundOtherRow() {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0,
FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
mProvider.setCustomCursor(cursor);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
@@ -176,10 +177,10 @@
public void testGetFontFromProvider_resultCodeIsNegativeNumber() {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL, -5});
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, -5});
mProvider.setCustomCursor(cursor);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
diff --git a/core/tests/coretests/src/android/provider/TestFontsProvider.java b/core/tests/coretests/src/android/provider/TestFontsProvider.java
index 13f5318..46906df 100644
--- a/core/tests/coretests/src/android/provider/TestFontsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestFontsProvider.java
@@ -37,7 +37,8 @@
static final String AUTHORITY = "android.provider.TestFontsProvider";
static final int TTC_INDEX = 2;
static final String VARIATION_SETTINGS = "'wdth' 1";
- static final int STYLE = Typeface.BOLD;
+ static final int NORMAL_WEIGHT = 400;
+ static final boolean ITALIC = false;
private ParcelFileDescriptor mPfd;
private boolean mReturnAllFields = true;
@@ -81,8 +82,9 @@
if (mReturnAllFields) {
cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, STYLE, mResultCode });
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, 400, 0, mResultCode });
} else {
cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID });
cursor.addRow(new Object[] { 1 });
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 560d29f..5afe5e9 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -357,8 +357,8 @@
long fontSize = fileChannel.size();
ByteBuffer fontBuffer = fileChannel.map(
FileChannel.MapMode.READ_ONLY, 0, fontSize);
- int style = result.getStyle();
- int weight = (style & BOLD) != 0 ? 700 : 400;
+ int weight = result.getWeight();
+ int italic = result.getItalic() ? Builder.ITALIC : Builder.NORMAL;
FontVariationAxis[] axes = null;
try {
axes = FontVariationAxis.fromFontVariationSettings(
@@ -366,8 +366,8 @@
} catch (FontVariationAxis.InvalidFormatException e) {
// TODO: Nice to pass FontVariationAxis[] directly instead of string.
}
- if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(), axes, weight,
- (style & ITALIC) == 0 ? Builder.NORMAL : Builder.ITALIC)) {
+ if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(),
+ axes, weight, italic)) {
Log.e(TAG, "Error creating font " + request.getQuery());
callback.onTypefaceRequestFailed(
FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index d88aee9..a491d7e 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -210,6 +210,7 @@
/**
* Change the global fade duration when a new drawable is entering
* the scene.
+ *
* @param ms The amount of time to fade in milliseconds.
*/
public void setEnterFadeDuration(int ms) {
@@ -219,6 +220,7 @@
/**
* Change the global fade duration when a new drawable is leaving
* the scene.
+ *
* @param ms The amount of time to fade in milliseconds.
*/
public void setExitFadeDuration(int ms) {
@@ -375,6 +377,13 @@
@Override
public void invalidateDrawable(@NonNull Drawable who) {
+ // This may have been called as the result of a tint changing, in
+ // which case we may need to refresh the cached statefulness or
+ // opacity.
+ if (mDrawableContainerState != null) {
+ mDrawableContainerState.invalidateCache();
+ }
+
if (who == mCurrDrawable && getCallback() != null) {
getCallback().invalidateDrawable(this);
}
@@ -822,8 +831,8 @@
mDrawables[pos] = dr;
mNumChildren++;
mChildrenChangingConfigurations |= dr.getChangingConfigurations();
- mCheckedStateful = false;
- mCheckedOpacity = false;
+
+ invalidateCache();
mConstantPadding = null;
mCheckedPadding = false;
@@ -833,6 +842,14 @@
return pos;
}
+ /**
+ * Invalidates the cached opacity and statefulness.
+ */
+ void invalidateCache() {
+ mCheckedOpacity = false;
+ mCheckedStateful = false;
+ }
+
final int getCapacity() {
return mDrawables.length;
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 355e45e..b159f0f 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -32,6 +32,7 @@
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
+import android.util.Log;
import android.view.Gravity;
import android.view.View;
@@ -66,6 +67,8 @@
* @attr ref android.R.styleable#LayerDrawableItem_id
*/
public class LayerDrawable extends Drawable implements Drawable.Callback {
+ private static final String LOG_TAG = "LayerDrawable";
+
/**
* Padding mode used to nest each layer inside the padding of the previous
* layer.
@@ -89,6 +92,7 @@
*/
public static final int INSET_UNDEFINED = Integer.MIN_VALUE;
+ @NonNull
LayerState mLayerState;
private int[] mPaddingL;
@@ -170,13 +174,9 @@
throws XmlPullParserException, IOException {
super.inflate(r, parser, attrs, theme);
- final LayerState state = mLayerState;
- if (state == null) {
- return;
- }
-
// The density may have changed since the last update. This will
// apply scaling to any existing constant state properties.
+ final LayerState state = mLayerState;
final int density = Drawable.resolveDensity(r, 0);
state.setDensity(density);
@@ -202,10 +202,6 @@
super.applyTheme(t);
final LayerState state = mLayerState;
- if (state == null) {
- return;
- }
-
final int density = Drawable.resolveDensity(t.getResources(), 0);
state.setDensity(density);
@@ -403,7 +399,7 @@
@Override
public boolean canApplyTheme() {
- return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme();
+ return mLayerState.canApplyTheme() || super.canApplyTheme();
}
/**
@@ -986,6 +982,11 @@
if (mSuspendChildInvalidation) {
mChildRequestedInvalidation = true;
} else {
+ // This may have been called as the result of a tint changing, in
+ // which case we may need to refresh the cached statefulness or
+ // opacity.
+ mLayerState.invalidateCache();
+
invalidateSelf();
}
}
@@ -1836,15 +1837,24 @@
final ConstantState cs = dr.getConstantState();
if (cs == null) {
clone = dr;
+ if (dr.getCallback() != null) {
+ // This drawable already has an owner.
+ Log.w(LOG_TAG, "Invalid drawable added to LayerDrawable! Drawable already "
+ + "belongs to another owner but does not expose a constant state.",
+ new RuntimeException());
+ }
} else if (res != null) {
clone = cs.newDrawable(res);
} else {
clone = cs.newDrawable();
}
- clone.setCallback(owner);
clone.setLayoutDirection(dr.getLayoutDirection());
clone.setBounds(dr.getBounds());
clone.setLevel(dr.getLevel());
+
+ // Set the callback last to prevent invalidation from
+ // propagating before the constant state has been set.
+ clone.setCallback(owner);
} else {
clone = null;
}
@@ -2121,7 +2131,10 @@
return true;
}
- public void invalidateCache() {
+ /**
+ * Invalidates the cached opacity and statefulness.
+ */
+ void invalidateCache() {
mCheckedOpacity = false;
mCheckedStateful = false;
}
diff --git a/graphics/java/android/graphics/fonts/FontResult.java b/graphics/java/android/graphics/fonts/FontResult.java
index 3ef99fd..20e736e 100644
--- a/graphics/java/android/graphics/fonts/FontResult.java
+++ b/graphics/java/android/graphics/fonts/FontResult.java
@@ -35,7 +35,8 @@
private final ParcelFileDescriptor mFileDescriptor;
private final int mTtcIndex;
private final String mFontVariationSettings;
- private final int mStyle;
+ private final int mWeight;
+ private final boolean mItalic;
/**
* Creates a FontResult with all the information needed about a provided font.
@@ -45,16 +46,16 @@
* will fail to load in the client application.
* @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
* @param fontVariationSettings If providing a variation font, the settings for it. May be null.
- * @param style One of {@link android.graphics.Typeface#NORMAL},
- * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC}
- * or {@link android.graphics.Typeface#BOLD_ITALIC}
+ * @param weight An integer that indicates the font weight.
+ * @param italic A boolean that indicates the font is italic style or not.
*/
public FontResult(@NonNull ParcelFileDescriptor fileDescriptor, int ttcIndex,
- @Nullable String fontVariationSettings, int style) {
+ @Nullable String fontVariationSettings, int weight, boolean italic) {
mFileDescriptor = Preconditions.checkNotNull(fileDescriptor);
mTtcIndex = ttcIndex;
mFontVariationSettings = fontVariationSettings;
- mStyle = style;
+ mWeight = weight;
+ mItalic = italic;
}
public ParcelFileDescriptor getFileDescriptor() {
@@ -69,8 +70,12 @@
return mFontVariationSettings;
}
- public int getStyle() {
- return mStyle;
+ public int getWeight() {
+ return mWeight;
+ }
+
+ public boolean getItalic() {
+ return mItalic;
}
@Override
@@ -83,14 +88,16 @@
dest.writeParcelable(mFileDescriptor, flags);
dest.writeInt(mTtcIndex);
dest.writeString(mFontVariationSettings);
- dest.writeInt(mStyle);
+ dest.writeInt(mWeight);
+ dest.writeBoolean(mItalic);
}
private FontResult(Parcel in) {
mFileDescriptor = in.readParcelable(null);
mTtcIndex = in.readInt();
mFontVariationSettings = in.readString();
- mStyle = in.readInt();
+ mWeight = in.readInt();
+ mItalic = in.readBoolean();
}
public static final Parcelable.Creator<FontResult> CREATOR =
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index dceb285..d4d0c99 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -189,9 +189,9 @@
float amount, uint8_t*& dst) const {
float oppAmount = 1.0f - amount;
float a = start.a * oppAmount + end.a * amount;
- *dst++ = uint8_t(a * OECF(start.r * oppAmount + end.r * amount) * 255.0f);
- *dst++ = uint8_t(a * OECF(start.g * oppAmount + end.g * amount) * 255.0f);
- *dst++ = uint8_t(a * OECF(start.b * oppAmount + end.b * amount) * 255.0f);
+ *dst++ = uint8_t(OECF(start.r * oppAmount + end.r * amount) * 255.0f);
+ *dst++ = uint8_t(OECF(start.g * oppAmount + end.g * amount) * 255.0f);
+ *dst++ = uint8_t(OECF(start.b * oppAmount + end.b * amount) * 255.0f);
*dst++ = uint8_t(a * 255.0f);
}
@@ -202,13 +202,13 @@
float* d = (float*) dst;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
// We want to stay linear
- *d++ = a * (start.r * oppAmount + end.r * amount);
- *d++ = a * (start.g * oppAmount + end.g * amount);
- *d++ = a * (start.b * oppAmount + end.b * amount);
+ *d++ = (start.r * oppAmount + end.r * amount);
+ *d++ = (start.g * oppAmount + end.g * amount);
+ *d++ = (start.b * oppAmount + end.b * amount);
#else
- *d++ = a * OECF(start.r * oppAmount + end.r * amount);
- *d++ = a * OECF(start.g * oppAmount + end.g * amount);
- *d++ = a * OECF(start.b * oppAmount + end.b * amount);
+ *d++ = OECF(start.r * oppAmount + end.r * amount);
+ *d++ = OECF(start.g * oppAmount + end.g * amount);
+ *d++ = OECF(start.b * oppAmount + end.b * amount);
#endif
*d++ = a;
dst += 4 * sizeof(float);
@@ -229,10 +229,10 @@
ChannelMixer mix = gMixers[mUseFloatTexture];
FloatColor start;
- start.setUnPreMultiplied(colors[0]);
+ start.set(colors[0]);
FloatColor end;
- end.setUnPreMultiplied(colors[1]);
+ end.set(colors[1]);
int currentPos = 1;
float startPos = positions[0];
@@ -247,7 +247,7 @@
currentPos++;
- end.setUnPreMultiplied(colors[currentPos]);
+ end.set(colors[currentPos]);
distance = positions[currentPos] - startPos;
}
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 1f78e09..d0f0949 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -295,10 +295,6 @@
vec4 dither(const vec4 color) {
return color + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
}
- vec4 gradientMix(const vec4 a, const vec4 b, float v) {
- vec4 c = mix(a, b, v);
- return vec4(c.rgb * c.a, c.a);
- }
)__SHADER__",
// sRGB framebuffer
R"__SHADER__(
@@ -306,10 +302,6 @@
vec3 dithered = sqrt(color.rgb) + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
return vec4(dithered * dithered, color.a);
}
- vec4 gradientMixMix(const vec4 a, const vec4 b, float v) {
- vec4 c = mix(a, b, v);
- return vec4(c.rgb * c.a, c.a);
- }
)__SHADER__",
};
@@ -364,19 +356,19 @@
// Linear
" vec4 gradientColor = texture2D(gradientSampler, linear);\n",
- " vec4 gradientColor = gradientMix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+ " vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
// Circular
" vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
- " vec4 gradientColor = gradientMix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+ " vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
// Sweep
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
" vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = gradientMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
+ " vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
};
const char* gFS_Main_FetchBitmap =
" vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, outBitmapTexCoords));\n";
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 8a504d4..5c5378b 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -173,8 +173,8 @@
outData->gradientSampler = 0;
outData->gradientTexture = nullptr;
- outData->startColor.setUnPreMultiplied(gradInfo.fColors[0]);
- outData->endColor.setUnPreMultiplied(gradInfo.fColors[1]);
+ outData->startColor.set(gradInfo.fColors[0]);
+ outData->endColor.set(gradInfo.fColors[1]);
}
return true;
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index 7f06421..8826cfc 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -27,5 +27,7 @@
libft2 \
libminikin \
libandroidfw \
- libRScpp \
+ libRScpp
+
+LOCAL_STATIC_LIBRARIES += \
libplatformprotos
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 2ead5c5..d26eb59 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -162,7 +162,7 @@
SkAutoCanvasRestore acr(canvas, true);
SkMatrix shadowMatrix;
- mat4 hwuiMatrix(caster->getRecordedMatrix());
+ mat4 hwuiMatrix;
// TODO we don't pass the optional boolean to treat it as a 4x4 matrix
caster->getRenderNode()->applyViewPropertyTransforms(hwuiMatrix);
hwuiMatrix.copyTo(shadowMatrix);
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 652954b..686d06f 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -941,3 +941,67 @@
EXPECT_EQ(2, canvas.mDrawCounter);
}
+
+TEST(ReorderBarrierDrawable, testShadowMatrix) {
+ static const int CANVAS_WIDTH = 100;
+ static const int CANVAS_HEIGHT = 100;
+ static const float TRANSLATE_X = 11.0f;
+ static const float TRANSLATE_Y = 22.0f;
+ static const float CASTER_X = 40.0f;
+ static const float CASTER_Y = 40.0f;
+ static const float CASTER_WIDTH = 20.0f;
+ static const float CASTER_HEIGHT = 20.0f;
+
+
+ class ShadowTestCanvas : public SkCanvas {
+ public:
+ ShadowTestCanvas(int width, int height) : SkCanvas(width, height) {}
+ int getIndex() { return mDrawCounter; }
+
+ virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
+ // expect to draw 2 RenderNodeDrawable, 1 StartReorderBarrierDrawable,
+ // 1 EndReorderBarrierDrawable
+ mDrawCounter++;
+ SkCanvas::onDrawDrawable(drawable, matrix);
+ }
+
+ virtual void didTranslate(SkScalar dx, SkScalar dy) override {
+ mDrawCounter++;
+ EXPECT_EQ(dx, TRANSLATE_X);
+ EXPECT_EQ(dy, TRANSLATE_Y);
+ }
+
+ virtual void didConcat(const SkMatrix& matrix) override {
+ // This function is invoked by EndReorderBarrierDrawable::drawShadow to apply shadow
+ // matrix.
+ mDrawCounter++;
+ EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X, CASTER_Y), matrix);
+ EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X+TRANSLATE_X, CASTER_Y+TRANSLATE_Y),
+ getTotalMatrix());
+ }
+ protected:
+ int mDrawCounter = 0;
+ };
+
+ auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.translate(TRANSLATE_X, TRANSLATE_Y);
+ canvas.insertReorderBarrier(true);
+
+ auto node = TestUtils::createSkiaNode(CASTER_X, CASTER_Y, CASTER_X + CASTER_WIDTH,
+ CASTER_Y + CASTER_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ props.setElevation(42);
+ props.mutableOutline().setRoundRect(0, 0, 20, 20, 5, 1);
+ props.mutableOutline().setShouldClip(true);
+ });
+ canvas.drawRenderNode(node.get());
+ canvas.insertReorderBarrier(false);
+ });
+
+ //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
+ RenderNodeDrawable drawable(parent.get(), &canvas, false);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(6, canvas.getIndex());
+}
\ No newline at end of file
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e36ceb8..77a82ec 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -913,6 +913,29 @@
}
}
+ // TODO remove, replaced by non-static API getVolumeControlStream()
+ /**
+ * Returns the stream type matching the given attributes for volume control.
+ * Use this method to derive the stream type needed to configure the volume
+ * control slider in an {@link android.app.Activity} with
+ * {@link android.app.Activity#setVolumeControlStream(int)}.
+ * <BR>Do not use this method to set the stream type on an audio player object
+ * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
+ * use <code>AudioAttributes</code> instead.
+ * @param aa non-null AudioAttributes.
+ * @return a valid stream type for <code>Activity</code> or stream volume control that matches
+ * the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
+ * match. Note that <code>USE_DEFAULT_STREAM_TYPE</code> is not a valid value
+ * for {@link AudioManager#setStreamVolume(int, int, int)}.
+ * @deprecated use {@link #getVolumeControlStream()}
+ */
+ public static int getVolumeControlStream(@NonNull AudioAttributes aa) {
+ if (aa == null) {
+ throw new IllegalArgumentException("Invalid null audio attributes");
+ }
+ return toVolumeStreamType(true /*fromGetVolumeControlStream*/, aa);
+ }
+
/**
* Returns the stream type matching this {@code AudioAttributes} instance for volume control.
* Use this method to derive the stream type needed to configure the volume
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index d8c3eca..0b27d18 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -568,9 +568,10 @@
}
/**
- * Common base for the tables of TV programs.
+ * Common columns for the tables of TV programs.
+ * @hide
*/
- public interface BaseProgramColumns extends BaseTvColumns {
+ interface ProgramColumns {
/**
* The title of this TV program.
*
@@ -836,9 +837,10 @@
}
/**
- * Common base for the tables of preview programs.
+ * Common columns for the tables of preview programs.
+ * @hide
*/
- public interface BasePreviewProgramColumns extends BaseProgramColumns {
+ interface PreviewProgramColumns {
/** @hide */
@IntDef({
@@ -2227,7 +2229,7 @@
* <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 BaseProgramColumns {
+ public static final class Programs implements BaseTvColumns, ProgramColumns {
/** The content:// style URI for this table. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2541,7 +2543,7 @@
* <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 BaseProgramColumns {
+ public static final class RecordedPrograms implements BaseTvColumns, ProgramColumns {
/** The content:// style URI for this table. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2663,7 +2665,8 @@
/**
* Column definitions for the preview TV programs table.
*/
- public static final class PreviewPrograms implements BasePreviewProgramColumns {
+ public static final class PreviewPrograms implements BaseTvColumns, ProgramColumns,
+ PreviewProgramColumns {
/** The content:// style URI for this table. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2709,7 +2712,8 @@
/**
* Column definitions for the "watch next" TV programs table.
*/
- public static final class WatchNextPrograms implements BasePreviewProgramColumns {
+ public static final class WatchNextPrograms implements BaseTvColumns, ProgramColumns,
+ PreviewProgramColumns {
/** The content:// style URI for this table. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index d5d9fc9..0149d76 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -342,7 +342,7 @@
}
// New GraphicBuffer object doesn't own the handle, thus the native buffer
// won't be freed when this object is destroyed.
- sp<GraphicBuffer> buffer(new GraphicBuffer(anb, /*keepOwnership*/false));
+ sp<GraphicBuffer> buffer(GraphicBuffer::from(anb));
// Note that:
// 1. No need to lock buffer now, will only lock it when the first getPlanes() is called.
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index f9342b7..fa5c3ff 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -6,6 +6,7 @@
<string name="no_data_notification_id">Your mobile data has been deactivated</string>
<string name="portal_notification_detail">Tap to visit the %s website</string>
<string name="no_data_notification_detail">Please contact your service provider %s</string>
+ <string name="mobile_data_status_notification_channel_name">Mobile data status</string>
<string name="action_bar_label">Sign in to mobile network</string>
<string name="ssl_error_warning">The network you’re trying to join has security issues.</string>
<string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 73ff3a9..7fd1601 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -16,6 +16,7 @@
package com.android.carrierdefaultapp;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -35,6 +36,7 @@
private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
+ private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status";
private static final int PORTAL_NOTIFICATION_ID = 0;
private static final int NO_DATA_NOTIFICATION_ID = 1;
private static boolean ENABLE = true;
@@ -150,9 +152,18 @@
private static Notification getNotification(Context context, int titleId, int textId,
PendingIntent pendingIntent) {
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ final NotificationManager notificationManager = context.getSystemService(
+ NotificationManager.class);
final Resources resources = context.getResources();
final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
resources.getString(R.string.android_system_label));
+ /* Creates the notification channel and registers it with NotificationManager. If a channel
+ * with the same ID is already registered, NotificationManager will ignore this call.
+ */
+ notificationManager.createNotificationChannel(new NotificationChannel(
+ NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
+ resources.getString(R.string.mobile_data_status_notification_channel_name),
+ NotificationManager.IMPORTANCE_DEFAULT));
Notification.Builder builder = new Notification.Builder(context)
.setContentTitle(resources.getString(titleId))
.setContentText(String.format(resources.getString(textId),
@@ -167,7 +178,8 @@
.setLocalOnly(true)
.setWhen(System.currentTimeMillis())
.setShowWhen(false)
- .setExtras(extras);
+ .setExtras(extras)
+ .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS);
if (pendingIntent != null) {
builder.setContentIntent(pendingIntent);
diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk
index 67ef40a..1ad4fea 100644
--- a/packages/SettingsLib/Android.mk
+++ b/packages/SettingsLib/Android.mk
@@ -6,6 +6,7 @@
LOCAL_MODULE := SettingsLib
LOCAL_SHARED_ANDROID_LIBRARIES := \
+ android-support-annotations \
android-support-v4 \
android-support-v7-recyclerview \
android-support-v7-preference \
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f14d0d1..ad985c7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -928,4 +928,18 @@
[CHAR LIMIT=35] -->
<string name="use_system_language_to_select_input_method_subtypes">Use system languages</string>
+ <!-- Toast that settings for an application is failed to open. -->
+ <string name="failed_to_open_app_settings_toast">Failed to open settings for <xliff:g id="spell_application_name">%1$s</xliff:g></string>
+
+ <!-- Warning message about security implications of enabling an input method, displayed as a dialog
+ message when the user selects to enable an IME. -->
+ <string name="ime_security_warning">This input method may be able to collect
+ all the text you type, including personal data like passwords and credit
+ card numbers. It comes from the app
+ <xliff:g id="ime_application_name">%1$s</xliff:g>.
+ Use this input method?</string>
+
+ <!-- [CHAR LIMIT=NONE] Dialog body explaining that the app just selected by the user will not work after a reboot until until after the user enters their credentials, such as a PIN or password. -->
+ <string name="direct_boot_unaware_dialog_message">Note: After a reboot, this app can\'t start until you unlock your phone</string>
+
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index 40abb6c..88f133c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -41,8 +41,8 @@
long privateTotalBytes = 0;
for (VolumeInfo info : sm.getVolumes()) {
if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
- privateTotalBytes += stats.getTotalBytes(info.getFsUuid());
- privateFreeBytes += stats.getFreeBytes(info.getFsUuid());
+ privateTotalBytes += sm.getTotalBytes(stats, info);
+ privateFreeBytes += sm.getFreeBytes(stats, info);
}
}
return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
index 320494c..11060e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -16,6 +16,7 @@
package com.android.settingslib.deviceinfo;
+import android.app.usage.StorageStatsManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
@@ -46,4 +47,14 @@
public VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume) {
return mStorageManager.findEmulatedForPrivate(privateVolume);
}
+
+ @Override
+ public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) {
+ return stats.getTotalBytes(volume.getFsUuid());
+ }
+
+ @Override
+ public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) {
+ return stats.getFreeBytes(volume.getFsUuid());
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
index 646c42f..e5d85d1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -16,6 +16,7 @@
package com.android.settingslib.deviceinfo;
+import android.app.usage.StorageStatsManager;
import android.os.storage.VolumeInfo;
import java.util.List;
@@ -39,4 +40,18 @@
* Returns the emulated volume for a given private volume.
*/
VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume);
+
+ /**
+ * Returns the total bytes for a given storage volume.
+ *
+ * @pre The volume is a private volume and is readable.
+ */
+ long getTotalBytes(StorageStatsManager stats, VolumeInfo volume);
+
+ /**
+ * Returns the free bytes for a given storage volume.
+ *
+ * @pre The volume is a private volume and is readable.
+ */
+ long getFreeBytes(StorageStatsManager stats, VolumeInfo volume);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
new file mode 100755
index 0000000..1bbc878b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -0,0 +1,300 @@
+/*
+ * 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.inputmethod;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.Toast;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.settingslib.R;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import java.text.Collator;
+import java.util.List;
+
+/**
+ * Input method preference.
+ *
+ * This preference represents an IME. It is used for two purposes. 1) An instance with a switch
+ * is used to enable or disable the IME. 2) An instance without a switch is used to invoke the
+ * setting activity of the IME.
+ */
+public class InputMethodPreference extends RestrictedSwitchPreference implements OnPreferenceClickListener,
+ OnPreferenceChangeListener {
+ private static final String TAG = InputMethodPreference.class.getSimpleName();
+ private static final String EMPTY_TEXT = "";
+ private static final int NO_WIDGET = 0;
+
+ public interface OnSavePreferenceListener {
+ /**
+ * Called when this preference needs to be saved its state.
+ *
+ * Note that this preference is non-persistent and needs explicitly to be saved its state.
+ * Because changing one IME state may change other IMEs' state, this is a place to update
+ * other IMEs' state as well.
+ *
+ * @param pref This preference.
+ */
+ void onSaveInputMethodPreference(InputMethodPreference pref);
+ }
+
+ private final InputMethodInfo mImi;
+ private final boolean mHasPriorityInSorting;
+ private final OnSavePreferenceListener mOnSaveListener;
+ private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
+ private final boolean mIsAllowedByOrganization;
+
+ private AlertDialog mDialog = null;
+
+ /**
+ * A preference entry of an input method.
+ *
+ * @param context The Context this is associated with.
+ * @param imi The {@link InputMethodInfo} of this preference.
+ * @param isImeEnabler true if this preference is the IME enabler that has enable/disable
+ * switches for all available IMEs, not the list of enabled IMEs.
+ * @param isAllowedByOrganization false if the IME has been disabled by a device or profile
+ * owner.
+ * @param onSaveListener The listener called when this preference has been changed and needs
+ * to save the state to shared preference.
+ */
+ public InputMethodPreference(final Context context, final InputMethodInfo imi,
+ final boolean isImeEnabler, final boolean isAllowedByOrganization,
+ final OnSavePreferenceListener onSaveListener) {
+ super(context);
+ setPersistent(false);
+ mImi = imi;
+ mIsAllowedByOrganization = isAllowedByOrganization;
+ mOnSaveListener = onSaveListener;
+ if (!isImeEnabler) {
+ // Remove switch widget.
+ setWidgetLayoutResource(NO_WIDGET);
+ }
+ // Disable on/off switch texts.
+ setSwitchTextOn(EMPTY_TEXT);
+ setSwitchTextOff(EMPTY_TEXT);
+ setKey(imi.getId());
+ setTitle(imi.loadLabel(context.getPackageManager()));
+ final String settingsActivity = imi.getSettingsActivity();
+ if (TextUtils.isEmpty(settingsActivity)) {
+ setIntent(null);
+ } else {
+ // Set an intent to invoke settings activity of an input method.
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(imi.getPackageName(), settingsActivity);
+ setIntent(intent);
+ }
+ mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(context);
+ mHasPriorityInSorting = InputMethodUtils.isSystemIme(imi)
+ && mInputMethodSettingValues.isValidSystemNonAuxAsciiCapableIme(imi, context);
+ setOnPreferenceClickListener(this);
+ setOnPreferenceChangeListener(this);
+ }
+
+ public InputMethodInfo getInputMethodInfo() {
+ return mImi;
+ }
+
+ private boolean isImeEnabler() {
+ // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the
+ // switch widget at constructor.
+ return getWidgetLayoutResource() != NO_WIDGET;
+ }
+
+ @Override
+ public boolean onPreferenceChange(final Preference preference, final Object newValue) {
+ // Always returns false to prevent default behavior.
+ // See {@link TwoStatePreference#onClick()}.
+ if (!isImeEnabler()) {
+ // Prevent disabling an IME because this preference is for invoking a settings activity.
+ return false;
+ }
+ if (isChecked()) {
+ // Disable this IME.
+ setCheckedInternal(false);
+ return false;
+ }
+ if (InputMethodUtils.isSystemIme(mImi)) {
+ // Enable a system IME. No need to show a security warning dialog,
+ // but we might need to prompt if it's not Direct Boot aware.
+ // TV doesn't doesn't need to worry about this, but other platforms should show
+ // a warning.
+ if (mImi.getServiceInfo().directBootAware || isTv()) {
+ setCheckedInternal(true);
+ } else if (!isTv()){
+ showDirectBootWarnDialog();
+ }
+ } else {
+ // Once security is confirmed, we might prompt if the IME isn't
+ // Direct Boot aware.
+ showSecurityWarnDialog();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ // Always returns true to prevent invoking an intent without catching exceptions.
+ // See {@link Preference#performClick(PreferenceScreen)}/
+ if (isImeEnabler()) {
+ // Prevent invoking a settings activity because this preference is for enabling and
+ // disabling an input method.
+ return true;
+ }
+ final Context context = getContext();
+ try {
+ final Intent intent = getIntent();
+ if (intent != null) {
+ // Invoke a settings activity of an input method.
+ context.startActivity(intent);
+ }
+ } catch (final ActivityNotFoundException e) {
+ Log.d(TAG, "IME's Settings Activity Not Found", e);
+ final String message = context.getString(
+ R.string.failed_to_open_app_settings_toast,
+ mImi.loadLabel(context.getPackageManager()));
+ Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+ }
+ return true;
+ }
+
+ public void updatePreferenceViews() {
+ final boolean isAlwaysChecked = mInputMethodSettingValues.isAlwaysCheckedIme(
+ mImi, getContext());
+ // When this preference has a switch and an input method should be always enabled,
+ // this preference should be disabled to prevent accidentally disabling an input method.
+ // This preference should also be disabled in case the admin does not allow this input
+ // method.
+ if (isAlwaysChecked && isImeEnabler()) {
+ setDisabledByAdmin(null);
+ setEnabled(false);
+ } else if (!mIsAllowedByOrganization) {
+ EnforcedAdmin admin =
+ RestrictedLockUtils.checkIfInputMethodDisallowed(getContext(),
+ mImi.getPackageName(), UserHandle.myUserId());
+ setDisabledByAdmin(admin);
+ } else {
+ setEnabled(true);
+ }
+ setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
+ if (!isDisabledByAdmin()) {
+ setSummary(getSummaryString());
+ }
+ }
+
+ private InputMethodManager getInputMethodManager() {
+ return (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+
+ private String getSummaryString() {
+ final InputMethodManager imm = getInputMethodManager();
+ final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
+ return InputMethodAndSubtypeUtil.getSubtypeLocaleNameListAsSentence(
+ subtypes, getContext(), mImi);
+ }
+
+ private void setCheckedInternal(boolean checked) {
+ super.setChecked(checked);
+ mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
+ notifyChanged();
+ }
+
+ private void showSecurityWarnDialog() {
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ final Context context = getContext();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setCancelable(true /* cancelable */);
+ builder.setTitle(android.R.string.dialog_alert_title);
+ final CharSequence label = mImi.getServiceInfo().applicationInfo.loadLabel(
+ context.getPackageManager());
+ builder.setMessage(context.getString(R.string.ime_security_warning, label));
+ builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
+ // The user confirmed to enable a 3rd party IME, but we might
+ // need to prompt if it's not Direct Boot aware.
+ // TV doesn't doesn't need to worry about this, but other platforms should show
+ // a warning.
+ if (mImi.getServiceInfo().directBootAware || isTv()) {
+ setCheckedInternal(true);
+ } else {
+ showDirectBootWarnDialog();
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+ // The user canceled to enable a 3rd party IME.
+ setCheckedInternal(false);
+ });
+ mDialog = builder.create();
+ mDialog.show();
+ }
+
+ private boolean isTv() {
+ return (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION;
+ }
+
+ private void showDirectBootWarnDialog() {
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ final Context context = getContext();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setCancelable(true /* cancelable */);
+ builder.setMessage(context.getText(R.string.direct_boot_unaware_dialog_message));
+ builder.setPositiveButton(android.R.string.ok, (dialog, which) -> setCheckedInternal(true));
+ builder.setNegativeButton(android.R.string.cancel,
+ (dialog, which) -> setCheckedInternal(false));
+ mDialog = builder.create();
+ mDialog.show();
+ }
+
+ public int compareTo(final InputMethodPreference rhs, final Collator collator) {
+ if (this == rhs) {
+ return 0;
+ }
+ if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
+ final CharSequence t0 = getTitle();
+ final CharSequence t1 = rhs.getTitle();
+ if (TextUtils.isEmpty(t0)) {
+ return 1;
+ }
+ if (TextUtils.isEmpty(t1)) {
+ return -1;
+ }
+ return collator.compare(t0.toString(), t1.toString());
+ }
+ // Prefer always checked system IMEs
+ return mHasPriorityInSorting ? -1 : 1;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
index d3bdeb7..ab7c6d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.os.Looper;
+import android.support.annotation.Keep;
/**
* Factory method used to inject WifiTracker instances.
@@ -26,14 +27,7 @@
private static WifiTracker sTestingWifiTracker;
- public static void enableTestingMode() {
- sTestingMode = true;
- }
-
- public static void disableTestingMode() {
- sTestingMode = false;
- }
-
+ @Keep
public static void setTestingWifiTracker(WifiTracker tracker) {
sTestingWifiTracker = tracker;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 0d0ddf2..1f559e4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2798,7 +2798,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 143;
+ private static final int SETTINGS_VERSION = 144;
private final int mUserId;
@@ -3324,7 +3324,7 @@
}
if (currentVersion == 141) {
- // Version 141: We added the notion of a default and whether the system set
+ // Version 142: We added the notion of a default and whether the system set
// the setting. This is used for resetting the internal state and we need
// to make sure this value is updated for the existing settings, otherwise
// we would delete system set settings while they should stay unmodified.
@@ -3344,7 +3344,7 @@
}
if (currentVersion == 142) {
- // Version 142: Set a default value for Wi-Fi wakeup feature.
+ // Version 143: Set a default value for Wi-Fi wakeup feature.
if (userId == UserHandle.USER_SYSTEM) {
final SettingsState globalSettings = getGlobalSettingsLocked();
Setting currentSetting = globalSettings.getSettingLocked(
@@ -3361,6 +3361,27 @@
currentVersion = 143;
}
+ if (currentVersion == 143) {
+ // Version 144: Set a default value for Autofill service.
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting currentSetting = secureSettings
+ .getSettingLocked(Settings.Secure.AUTOFILL_SERVICE);
+ if (currentSetting.isNull()) {
+ final String defaultValue = getContext().getResources().getString(
+ com.android.internal.R.string.config_defaultAutofillService);
+ if (defaultValue != null) {
+ Slog.d(LOG_TAG, "Setting [" + defaultValue + "] as Autofill Service "
+ + "for user " + userId);
+ secureSettings.insertSettingLocked(Settings.Secure.AUTOFILL_SERVICE,
+ defaultValue, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
+ currentVersion = 144;
+ }
+
+ // vXXX: Add new settings above this point.
+
if (currentVersion != newVersion) {
Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
+ newVersion + " left it at "
@@ -3372,8 +3393,6 @@
}
}
- // vXXX: Add new settings above this point.
-
// Return the current version.
return currentVersion;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 2655837..80b4da8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -34,9 +34,11 @@
import android.widget.TextClock;
import android.widget.TextView;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ChargingView;
+import java.util.Arrays;
import java.util.Locale;
public class KeyguardStatusView extends GridLayout {
@@ -53,6 +55,10 @@
private ViewGroup mClockContainer;
private ChargingView mBatteryDoze;
+ private View[] mVisibleInDoze;
+ private boolean mPulsing;
+ private boolean mDark;
+
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -117,6 +123,7 @@
mClockView.setShowCurrentUserTime(true);
mOwnerInfo = (TextView) findViewById(R.id.owner_info);
mBatteryDoze = (ChargingView) findViewById(R.id.battery_doze);
+ mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
setEnableMarquee(shouldMarquee);
@@ -273,14 +280,28 @@
}
public void setDark(boolean dark) {
+ mDark = dark;
+
final int N = mClockContainer.getChildCount();
for (int i = 0; i < N; i++) {
View child = mClockContainer.getChildAt(i);
- if (child == mClockView || child == mBatteryDoze) {
+ if (ArrayUtils.contains(mVisibleInDoze, child)) {
continue;
}
child.setAlpha(dark ? 0 : 1);
}
+ updateDozeVisibleViews();
mBatteryDoze.setDark(dark);
}
+
+ public void setPulsing(boolean pulsing) {
+ mPulsing = pulsing;
+ updateDozeVisibleViews();
+ }
+
+ private void updateDozeVisibleViews() {
+ for (View child : mVisibleInDoze) {
+ child.setAlpha(mDark && mPulsing ? 0.5f : 1);
+ }
+ }
}
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 bcf1957..fbd9f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -86,6 +86,7 @@
private static final float DISABLED_ACTION_ALPHA = 0.54f;
private boolean mMenuVisible;
+ private boolean mAllowMenuTimeout = true;
private final List<RemoteAction> mActions = new ArrayList<>();
private View mViewRoot;
private Drawable mBackgroundDrawable;
@@ -190,7 +191,9 @@
@Override
public void onUserInteraction() {
- repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+ if (mAllowMenuTimeout) {
+ repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+ }
}
@Override
@@ -255,6 +258,7 @@
}
private void showMenu(Rect stackBounds, Rect movementBounds, boolean allowMenuTimeout) {
+ mAllowMenuTimeout = allowMenuTimeout;
if (!mMenuVisible) {
updateActionViews(stackBounds);
if (mMenuContainerAnimator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 9efe224..d2a2919 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -242,7 +242,7 @@
mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
mDetailSettingsButton.setOnClickListener(v -> {
Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
- mDetailAdapter.getMetricsCategory());
+ adapter.getMetricsCategory());
Dependency.get(ActivityStarter.class)
.postStartActivityDismissingKeyguard(settingsIntent, 0);
});
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 dc666e9..311f8ff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -524,7 +524,7 @@
* changes.
*/
public void onTaskDataLoaded() {
- if (mTask.icon != null) {
+ if (mTask != null && mTask.icon != null) {
mIconView.setImageDrawable(mTask.icon);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 21a0dc9..8298f35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -228,6 +228,7 @@
// Settings button.
final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
if (mAppUid >= 0 && onSettingsClick != null) {
+ settingsButton.setVisibility(View.VISIBLE);
final int appUidF = mAppUid;
settingsButton.setOnClickListener(
(View view) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 5055dda..bb82b60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -120,6 +120,9 @@
@Override
public void createMenu(ViewGroup parent) {
mParent = (ExpandableNotificationRow) parent;
+ if (mMenuContainer != null) {
+ mMenuContainer.removeAllViews();
+ }
mMenuContainer = new FrameLayout(mContext);
for (int i = 0; i < mMenuItems.size(); i++) {
addMenuView(mMenuItems.get(i), mMenuContainer);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8da17fa..8042321 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -23,7 +23,6 @@
import android.view.View;
import android.view.ViewGroup;
-import com.android.internal.widget.CachingIconView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
@@ -127,12 +126,8 @@
super.setDark(dark, fade, delay);
if (mDark == dark) return;
mDark = dark;
- if (fade) {
- mViewInvertHelper.fade(dark, delay);
- } else {
- mViewInvertHelper.update(dark);
- }
- mShelfIcons.setAmbient(dark);
+ mShelfIcons.setDark(dark, fade, delay);
+ updateInteractiveness();
}
@Override
@@ -167,7 +162,7 @@
openedAmount = Math.min(1.0f, openedAmount);
mShelfState.openedAmount = openedAmount;
mShelfState.clipTopAmount = 0;
- mShelfState.alpha = 1.0f;
+ mShelfState.alpha = mAmbientState.isPulsing() ? 0 : 1;
mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
mShelfState.shadowAlpha = 1.0f;
mShelfState.hideSensitive = false;
@@ -576,7 +571,8 @@
}
private void updateInteractiveness() {
- mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf;
+ mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf
+ && !mDark;
setClickable(mInteractive);
setFocusable(mInteractive);
setImportantForAccessibility(mInteractive ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
@@ -602,6 +598,11 @@
}
@Override
+ public boolean hasOverlappingRendering() {
+ return false; // Shelf only uses alpha for transitions where the difference can't be seen.
+ }
+
+ @Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
updateRelativeOffset();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index b9c8a78..92bfae9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -27,6 +27,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -46,6 +47,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
import com.android.systemui.statusbar.notification.NotificationUtils;
import java.text.NumberFormat;
@@ -99,7 +101,6 @@
private int mDensity;
private float mIconScale = 1.0f;
private final Paint mDotPaint = new Paint();
- private boolean mDotVisible;
private float mDotRadius;
private int mStaticDotRadius;
private int mVisibleState = STATE_ICON;
@@ -110,6 +111,8 @@
private OnVisibilityChangedListener mOnVisibilityChangedListener;
private int mDrawableColor;
private int mIconColor;
+ private int mDecorColor;
+ private float mDarkAmount;
private ValueAnimator mColorAnimator;
private int mCurrentSetColor = NO_COLOR;
private int mAnimationStartColor = NO_COLOR;
@@ -119,6 +122,7 @@
animation.getAnimatedFraction());
setColorInternal(newColor);
};
+ private final NotificationIconDozeHelper mDozer;
public StatusBarIconView(Context context, String slot, Notification notification) {
this(context, slot, notification, false);
@@ -127,6 +131,7 @@
public StatusBarIconView(Context context, String slot, Notification notification,
boolean blocked) {
super(context);
+ mDozer = new NotificationIconDozeHelper(context);
mBlocked = blocked;
mSlot = slot;
mNumberPain = new Paint();
@@ -190,6 +195,7 @@
public StatusBarIconView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mDozer = new NotificationIconDozeHelper(context);
mBlocked = false;
mAlwaysScaleIcon = true;
updateIconScale();
@@ -466,7 +472,19 @@
* to the drawable.
*/
public void setDecorColor(int iconTint) {
- mDotPaint.setColor(iconTint);
+ mDecorColor = iconTint;
+ updateDecorColor();
+ }
+
+ private void updateDecorColor() {
+ int color = NotificationUtils.interpolateColors(mDecorColor, Color.WHITE, mDarkAmount);
+ if (mDotPaint.getColor() != color) {
+ mDotPaint.setColor(color);
+
+ if (mDotAppearAmount != 0) {
+ invalidate();
+ }
+ }
}
/**
@@ -477,6 +495,7 @@
mDrawableColor = color;
setColorInternal(color);
mIconColor = color;
+ mDozer.setColor(color);
}
private void setColorInternal(int color) {
@@ -649,6 +668,14 @@
mOnVisibilityChangedListener = listener;
}
+ public void setDark(boolean dark, boolean fade, long delay) {
+ mDozer.setImageDark(this, dark, fade, delay, mIconColor == NO_COLOR);
+ mDozer.setIntensityDark(f -> {
+ mDarkAmount = f;
+ updateDecorColor();
+ }, dark, fade, delay);
+ }
+
public interface OnVisibilityChangedListener {
void onVisibilityChanged(int newVisibility);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 3efa29f..bca4b43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -18,7 +18,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
+import android.content.Context;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
@@ -38,8 +38,8 @@
private boolean mIsLegacy;
private int mLegacyColor;
- protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
- super(view, row);
+ protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+ super(ctx, view, row);
mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
}
@@ -67,13 +67,11 @@
}
protected void fadeGrayscale(final boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateGrayscaleMatrix((float) animation.getAnimatedValue());
- mGreyPaint.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
- mView.setLayerPaint(mGreyPaint);
- }
+ getDozer().startIntensityAnimation(animation -> {
+ getDozer().updateGrayscaleMatrix((float) animation.getAnimatedValue());
+ mGreyPaint.setColorFilter(
+ new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
+ mView.setLayerPaint(mGreyPaint);
}, dark, delay, new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -86,9 +84,9 @@
protected void updateGrayscale(boolean dark) {
if (dark) {
- updateGrayscaleMatrix(1f);
+ getDozer().updateGrayscaleMatrix(1f);
mGreyPaint.setColorFilter(
- new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
mView.setLayerPaint(mGreyPaint);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
new file mode 100644
index 0000000..d592c5f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.widget.ImageView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+
+import java.util.function.Consumer;
+
+public class NotificationDozeHelper {
+ private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
+
+ public void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
+ startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateGrayscaleMatrix((float) animation.getAnimatedValue());
+ target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ }
+ }, dark, delay, new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!dark) {
+ target.setColorFilter(null);
+ }
+ }
+ });
+ }
+
+ public void updateGrayscale(ImageView target, boolean dark) {
+ if (dark) {
+ updateGrayscaleMatrix(1f);
+ target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ } else {
+ target.setColorFilter(null);
+ }
+ }
+
+ public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
+ boolean dark, long delay, Animator.AnimatorListener listener) {
+ float startIntensity = dark ? 0f : 1f;
+ float endIntensity = dark ? 1f : 0f;
+ ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
+ animator.addUpdateListener(updateListener);
+ animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+ animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ animator.setStartDelay(delay);
+ if (listener != null) {
+ animator.addListener(listener);
+ }
+ animator.start();
+ }
+
+ public void setIntensityDark(Consumer<Float> listener, boolean dark,
+ boolean animate, long delay) {
+ if (animate) {
+ startIntensityAnimation(a -> listener.accept((Float) a.getAnimatedValue()), dark, delay,
+ null /* listener */);
+ } else {
+ listener.accept(dark ? 1f : 0f);
+ }
+ }
+
+ public void updateGrayscaleMatrix(float intensity) {
+ mGrayscaleColorMatrix.setSaturation(1 - intensity);
+ }
+
+ public ColorMatrix getGrayscaleColorMatrix() {
+ return mGrayscaleColorMatrix;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 38e4ec1..1ffc944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -16,17 +16,10 @@
package com.android.systemui.statusbar.notification;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.app.Notification;
import android.content.Context;
-import android.graphics.Color;
import android.graphics.ColorFilter;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Drawable;
import android.util.ArraySet;
import android.view.NotificationHeaderView;
import android.view.View;
@@ -37,7 +30,6 @@
import android.widget.TextView;
import com.android.systemui.Interpolators;
-import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
@@ -55,10 +47,6 @@
private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
= new PathInterpolator(0.4f, 0f, 0.7f, 1f);
- private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
- 0, PorterDuff.Mode.SRC_ATOP);
- private final int mIconDarkAlpha;
- private final int mIconDarkColor = 0xffffffff;
protected final ViewInvertHelper mInvertHelper;
protected final ViewTransformationHelper mTransformationHelper;
@@ -74,8 +62,7 @@
private boolean mTransformLowPriorityTitle;
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
- super(view, row);
- mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+ super(ctx, view, row);
mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION);
mTransformationHelper = new ViewTransformationHelper();
@@ -108,6 +95,16 @@
updateInvertHelper();
}
+ @Override
+ protected NotificationDozeHelper createDozer(Context ctx) {
+ return new NotificationIconDozeHelper(ctx);
+ }
+
+ @Override
+ protected NotificationIconDozeHelper getDozer() {
+ return (NotificationIconDozeHelper) super.getDozer();
+ }
+
protected void resolveHeaderViews() {
mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text);
@@ -116,6 +113,7 @@
mColor = resolveColor(mExpandButton);
mNotificationHeader = (NotificationHeaderView) mView.findViewById(
com.android.internal.R.id.notification_header);
+ getDozer().setColor(mColor);
}
private int resolveColor(ImageView icon) {
@@ -223,90 +221,8 @@
// It also may lead to bugs where the icon isn't correctly greyed out.
boolean hadColorFilter = mNotificationHeader.getOriginalIconColor()
!= NotificationHeaderView.NO_COLOR;
- if (fade) {
- if (hadColorFilter) {
- fadeIconColorFilter(mIcon, dark, delay);
- fadeIconAlpha(mIcon, dark, delay);
- } else {
- fadeGrayscale(mIcon, dark, delay);
- }
- } else {
- if (hadColorFilter) {
- updateIconColorFilter(mIcon, dark);
- updateIconAlpha(mIcon, dark);
- } else {
- updateGrayscale(mIcon, dark);
- }
- }
- }
- }
- private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateIconColorFilter(target, (Float) animation.getAnimatedValue());
- }
- }, dark, delay, null /* listener */);
- }
-
- private void fadeIconAlpha(final ImageView target, boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (float) animation.getAnimatedValue();
- target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t));
- }
- }, dark, delay, null /* listener */);
- }
-
- protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateGrayscaleMatrix((float) animation.getAnimatedValue());
- target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
- }
- }, dark, delay, new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!dark) {
- target.setColorFilter(null);
- }
- }
- });
- }
-
- private void updateIconColorFilter(ImageView target, boolean dark) {
- updateIconColorFilter(target, dark ? 1f : 0f);
- }
-
- private void updateIconColorFilter(ImageView target, float intensity) {
- int color = interpolateColor(mColor, mIconDarkColor, intensity);
- mIconColorFilter.setColor(color);
- Drawable iconDrawable = target.getDrawable();
-
- // Also, the notification might have been modified during the animation, so background
- // might be null here.
- if (iconDrawable != null) {
- Drawable d = iconDrawable.mutate();
- // DrawableContainer ignores the color filter if it's already set, so clear it first to
- // get it set and invalidated properly.
- d.setColorFilter(null);
- d.setColorFilter(mIconColorFilter);
- }
- }
-
- private void updateIconAlpha(ImageView target, boolean dark) {
- target.setImageAlpha(dark ? mIconDarkAlpha : 255);
- }
-
- protected void updateGrayscale(ImageView target, boolean dark) {
- if (dark) {
- updateGrayscaleMatrix(1f);
- target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
- } else {
- target.setColorFilter(null);
+ getDozer().setImageDark(mIcon, dark, fade, delay, !hadColorFilter);
}
}
@@ -316,22 +232,6 @@
mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
}
- private static int interpolateColor(int source, int target, float t) {
- int aSource = Color.alpha(source);
- int rSource = Color.red(source);
- int gSource = Color.green(source);
- int bSource = Color.blue(source);
- int aTarget = Color.alpha(target);
- int rTarget = Color.red(target);
- int gTarget = Color.green(target);
- int bTarget = Color.blue(target);
- return Color.argb(
- (int) (aSource * (1f - t) + aTarget * t),
- (int) (rSource * (1f - t) + rTarget * t),
- (int) (gSource * (1f - t) + gTarget * t),
- (int) (bSource * (1f - t) + bTarget * t));
- }
-
@Override
public NotificationHeaderView getNotificationHeader() {
return mNotificationHeader;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java
new file mode 100644
index 0000000..9f79ef2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+public class NotificationIconDozeHelper extends NotificationDozeHelper {
+
+ private final int mImageDarkAlpha;
+ private final int mImageDarkColor = 0xffffffff;
+ private final PorterDuffColorFilter mImageColorFilter = new PorterDuffColorFilter(
+ 0, PorterDuff.Mode.SRC_ATOP);
+
+ private int mColor = Color.BLACK;
+
+ public NotificationIconDozeHelper(Context ctx) {
+ mImageDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+ }
+
+ public void setColor(int color) {
+ mColor = color;
+ }
+
+ public void setImageDark(ImageView target, boolean dark, boolean fade, long delay,
+ boolean useGrayscale) {
+ if (fade) {
+ if (!useGrayscale) {
+ fadeImageColorFilter(target, dark, delay);
+ fadeImageAlpha(target, dark, delay);
+ } else {
+ fadeGrayscale(target, dark, delay);
+ }
+ } else {
+ if (!useGrayscale) {
+ updateImageColorFilter(target, dark);
+ updateImageAlpha(target, dark);
+ } else {
+ updateGrayscale(target, dark);
+ }
+ }
+ }
+
+ private void fadeImageColorFilter(final ImageView target, boolean dark, long delay) {
+ startIntensityAnimation(animation -> {
+ updateImageColorFilter(target, (Float) animation.getAnimatedValue());
+ }, dark, delay, null /* listener */);
+ }
+
+ private void fadeImageAlpha(final ImageView target, boolean dark, long delay) {
+ startIntensityAnimation(animation -> {
+ float t = (float) animation.getAnimatedValue();
+ target.setImageAlpha((int) (255 * (1f - t) + mImageDarkAlpha * t));
+ }, dark, delay, null /* listener */);
+ }
+
+ private void updateImageColorFilter(ImageView target, boolean dark) {
+ updateImageColorFilter(target, dark ? 1f : 0f);
+ }
+
+ private void updateImageColorFilter(ImageView target, float intensity) {
+ int color = NotificationUtils.interpolateColors(mColor, mImageDarkColor, intensity);
+ mImageColorFilter.setColor(color);
+ Drawable imageDrawable = target.getDrawable();
+
+ // Also, the notification might have been modified during the animation, so background
+ // might be null here.
+ if (imageDrawable != null) {
+ Drawable d = imageDrawable.mutate();
+ // DrawableContainer ignores the color filter if it's already set, so clear it first to
+ // get it set and invalidated properly.
+ d.setColorFilter(null);
+ d.setColorFilter(mImageColorFilter);
+ }
+ }
+
+ private void updateImageAlpha(ImageView target, boolean dark) {
+ target.setImageAlpha(dark ? mImageDarkAlpha : 255);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 846d03a..f0b6b2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.service.notification.StatusBarNotification;
@@ -46,7 +45,8 @@
private int mContentHeight;
private int mMinHeightHint;
- protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+ protected NotificationTemplateViewWrapper(Context ctx, View view,
+ ExpandableNotificationRow row) {
super(ctx, view, row);
mTransformationHelper.setCustomTransformation(
new ViewTransformationHelper.CustomTransformation() {
@@ -154,16 +154,20 @@
// This also clears the existing types
super.updateTransformedTypes();
if (mTitle != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, mTitle);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
+ mTitle);
}
if (mText != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT, mText);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+ mText);
}
if (mPicture != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE, mPicture);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
+ mPicture);
}
if (mProgressBar != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS, mProgressBar);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
+ mProgressBar);
}
}
@@ -173,7 +177,7 @@
return;
}
super.setDark(dark, fade, delay);
- setPictureGrayscale(dark, fade, delay);
+ setPictureDark(dark, fade, delay);
setProgressBarDark(dark, fade, delay);
}
@@ -188,12 +192,9 @@
}
private void fadeProgressDark(final ProgressBar target, final boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (float) animation.getAnimatedValue();
- updateProgressDark(target, t);
- }
+ getDozer().startIntensityAnimation(animation -> {
+ float t = (float) animation.getAnimatedValue();
+ updateProgressDark(target, t);
}, dark, delay, null /* listener */);
}
@@ -207,13 +208,9 @@
updateProgressDark(target, dark ? 1f : 0f);
}
- protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) {
+ private void setPictureDark(boolean dark, boolean fade, long delay) {
if (mPicture != null) {
- if (fade) {
- fadeGrayscale(mPicture, grayscale, delay);
- } else {
- updateGrayscale(mPicture, grayscale);
- }
+ getDozer().setImageDark(mPicture, dark, fade, delay, true /* useGrayscale */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index c85e8d8..f4db9a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -16,24 +16,17 @@
package com.android.systemui.statusbar.notification;
-import android.animation.Animator;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.ColorMatrix;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
import android.support.v4.graphics.ColorUtils;
import android.view.NotificationHeaderView;
import android.view.View;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
/**
* Wraps the actual notification content view; used to implement behaviors which are different for
@@ -41,14 +34,14 @@
*/
public abstract class NotificationViewWrapper implements TransformableView {
- protected final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
protected final View mView;
protected final ExpandableNotificationRow mRow;
+ private final NotificationDozeHelper mDozer;
+
protected boolean mDark;
private int mBackgroundColor = 0;
protected boolean mShouldInvertDark;
protected boolean mDarkInitialized = false;
- private boolean mForcedInvisible;
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -65,13 +58,22 @@
} else if (v instanceof NotificationHeaderView) {
return new NotificationHeaderViewWrapper(ctx, v, row);
} else {
- return new NotificationCustomViewWrapper(v, row);
+ return new NotificationCustomViewWrapper(ctx, v, row);
}
}
- protected NotificationViewWrapper(View view, ExpandableNotificationRow row) {
+ protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
mView = view;
mRow = row;
+ mDozer = createDozer(ctx);
+ }
+
+ protected NotificationDozeHelper createDozer(Context ctx) {
+ return new NotificationDozeHelper();
+ }
+
+ protected NotificationDozeHelper getDozer() {
+ return mDozer;
}
/**
@@ -112,26 +114,6 @@
|| ColorUtils.calculateLuminance(backgroundColor) > 0.5;
}
-
- protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
- boolean dark, long delay, Animator.AnimatorListener listener) {
- float startIntensity = dark ? 0f : 1f;
- float endIntensity = dark ? 1f : 0f;
- ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
- animator.addUpdateListener(updateListener);
- animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
- animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- animator.setStartDelay(delay);
- if (listener != null) {
- animator.addListener(listener);
- }
- animator.start();
- }
-
- protected void updateGrayscaleMatrix(float intensity) {
- mGrayscaleColorMatrix.setSaturation(1 - intensity);
- }
-
/**
* Update the appearance of the expand button.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 3706dc8..dee15d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -95,7 +95,7 @@
private int mActualLayoutWidth = NO_VALUE;
private float mActualPaddingEnd = NO_VALUE;
private float mActualPaddingStart = NO_VALUE;
- private boolean mCentered;
+ private boolean mDark;
private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1;
private int mCannedAnimationStartIndex = -1;
@@ -183,6 +183,9 @@
mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
}
}
+ if (mDark && child instanceof StatusBarIconView) {
+ ((StatusBarIconView) child).setDark(mDark, false, 0);
+ }
}
@Override
@@ -312,7 +315,8 @@
numDots++;
}
}
- if (mCentered && translationX < getLayoutEnd()) {
+ boolean center = mDark;
+ if (center && translationX < getLayoutEnd()) {
float delta = (getLayoutEnd() - translationX) / 2;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
@@ -390,9 +394,15 @@
mChangingViewPositions = changingViewPositions;
}
- public void setAmbient(boolean ambient) {
- mCentered = ambient;
+ public void setDark(boolean dark, boolean fade, long delay) {
+ mDark = dark;
mDisallowNextAnimation = true;
+ for (int i = 0; i < getChildCount(); i++) {
+ View view = getChildAt(i);
+ if (view instanceof StatusBarIconView) {
+ ((StatusBarIconView) view).setDark(dark, fade, delay);
+ }
+ }
}
public IconState getIconState(StatusBarIconView icon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c24a2a0..307a8c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2472,4 +2472,8 @@
public void setNoVisibleNotifications(boolean noNotifications) {
mNoVisibleNotifications = noNotifications;
}
+
+ public void setPulsing(boolean pulsing) {
+ mKeyguardStatusView.setPulsing(pulsing);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9a71ed7..472af65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -89,7 +89,6 @@
import android.provider.Settings;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
-import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -242,7 +241,6 @@
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -5012,19 +5010,25 @@
@Override
public void onPulseStarted() {
callback.onPulseStarted();
- if (!mHeadsUpManager.getAllEntries().isEmpty()) {
+ Collection<HeadsUpManager.HeadsUpEntry> pulsingEntries =
+ mHeadsUpManager.getAllEntries();
+ if (!pulsingEntries.isEmpty()) {
// Only pulse the stack scroller if there's actually something to show.
// Otherwise just show the always-on screen.
- mStackScroller.setPulsing(true);
- mVisualStabilityManager.setPulsing(true);
+ setPulsing(pulsingEntries);
}
}
@Override
public void onPulseFinished() {
callback.onPulseFinished();
- mStackScroller.setPulsing(false);
- mVisualStabilityManager.setPulsing(false);
+ setPulsing(null);
+ }
+
+ private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ mStackScroller.setPulsing(pulsing);
+ mNotificationPanel.setPulsing(pulsing != null);
+ mVisualStabilityManager.setPulsing(pulsing != null);
}
}, reason);
}
@@ -5767,12 +5771,16 @@
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
final String pkg = sbn.getPackageName();
NotificationInfo info = (NotificationInfo) gutsView;
- final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
- NotificationChannel channel, int appUid) -> {
- mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
- guts.resetFalsingCheck();
- startAppNotificationSettingsActivity(pkg, appUid, channel);
- };
+ // Settings link is only valid for notifications that specify a user, unless this is the
+ // system user.
+ NotificationInfo.OnSettingsClickListener onSettingsClick = null;
+ if (!userHandle.equals(UserHandle.ALL) || mCurrentUserId == UserHandle.USER_SYSTEM) {
+ onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
+ mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
+ guts.resetFalsingCheck();
+ startAppNotificationSettingsActivity(pkg, appUid, channel);
+ };
+ }
final View.OnClickListener onDoneClick = (View v) -> {
saveAndCloseNotificationMenu(info, row, guts, v);
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index fe83dc4..b2b23a55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -59,6 +59,7 @@
private boolean mPanelTracking;
private boolean mExpansionChanging;
private boolean mPanelFullWidth;
+ private boolean mPulsing;
public AmbientState(Context context) {
reload(context);
@@ -285,6 +286,14 @@
mPanelTracking = panelTracking;
}
+ public boolean isPulsing() {
+ return mPulsing;
+ }
+
+ public void setPulsing(boolean pulsing) {
+ mPulsing = pulsing;
+ }
+
public boolean isPanelTracking() {
return mPanelTracking;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7d2d0df..15fcb38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -72,6 +72,7 @@
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationGuts;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StackScrollerDecorView;
@@ -86,6 +87,7 @@
import com.android.systemui.statusbar.policy.ScrollAdapter;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
@@ -331,7 +333,7 @@
}
};
private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
- private boolean mPulsing;
+ private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
private boolean mDrawBackgroundAsSrc;
private boolean mFadingOut;
private boolean mParentNotFullyVisible;
@@ -1917,15 +1919,19 @@
int numShownItems = 0;
boolean finish = false;
int maxDisplayedNotifications = mAmbientState.isDark()
- ? (mPulsing ? 1 : 0)
+ ? (isPulsing() ? 1 : 0)
: mMaxDisplayedNotifications;
for (int i = 0; i < getChildCount(); i++) {
ExpandableView expandableView = (ExpandableView) getChildAt(i);
if (expandableView.getVisibility() != View.GONE
&& !expandableView.hasNoContentHeight()) {
- if (maxDisplayedNotifications != -1
- && numShownItems >= maxDisplayedNotifications) {
+ boolean limitReached = maxDisplayedNotifications != -1
+ && numShownItems >= maxDisplayedNotifications;
+ boolean notificationOnAmbientThatIsNotPulsing = isPulsing()
+ && expandableView instanceof ExpandableNotificationRow
+ && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
+ if (limitReached || notificationOnAmbientThatIsNotPulsing) {
expandableView = mShelf;
finish = true;
}
@@ -1971,6 +1977,19 @@
mAmbientState.setLayoutMaxHeight(mContentHeight);
}
+ private boolean isPulsing(NotificationData.Entry entry) {
+ for (HeadsUpManager.HeadsUpEntry e : mPulsing) {
+ if (e.entry == entry) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isPulsing() {
+ return mPulsing != null;
+ }
+
private void updateScrollability() {
boolean scrollable = getScrollRange() > 0;
if (scrollable != mScrollable) {
@@ -2784,7 +2803,7 @@
}
private void updateNotificationAnimationStates() {
- boolean running = mAnimationsEnabled || mPulsing;
+ boolean running = mAnimationsEnabled || isPulsing();
mShelf.setAnimationsEnabled(running);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -2795,7 +2814,7 @@
}
private void updateAnimationState(View child) {
- updateAnimationState((mAnimationsEnabled || mPulsing)
+ updateAnimationState((mAnimationsEnabled || isPulsing())
&& (mIsExpanded || isPinnedHeadsUp(child)), child);
}
@@ -4055,14 +4074,16 @@
return mIsExpanded;
}
- public void setPulsing(boolean pulsing) {
- if (mPulsing == pulsing) {
+ public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ if (mPulsing == null && pulsing == null) {
return;
}
mPulsing = pulsing;
+ mAmbientState.setPulsing(isPulsing());
updateNotificationAnimationStates();
updateContentHeight();
notifyHeightChangeListener(mShelf);
+ requestChildrenUpdate();
}
public void setFadingOut(boolean fadingOut) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index c67cccc..8609eeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -100,4 +100,10 @@
ViewUtils.detachView(mQsDetail);
mTestableLooper.processAllMessages();
}
+
+ @Test
+ public void testNullAdapterClick() {
+ mQsDetail.setupDetailFooter(mock(DetailAdapter.class));
+ mQsDetail.findViewById(android.R.id.button2).performClick();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 21930a3..0621f4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -206,6 +206,29 @@
}
@Test
+ public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ null, null, null, null);
+ final TextView settingsButton =
+ (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ assertTrue(settingsButton.getVisibility() != View.VISIBLE);
+ }
+
+ @Test
+ public void testBindNotification_SettingsButtonReappersAfterSecondBind() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ null, null, null, null);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ (View v, NotificationChannel c, int appUid) -> {}, null, null, null);
+ final TextView settingsButton =
+ (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ assertEquals(View.VISIBLE, settingsButton.getVisibility());
+ }
+
+ @Test
public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 31b9bae..efb9fea4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -44,4 +44,11 @@
ViewUtils.detachView(row.getMenuView());
TestableLooper.get(this).processAllMessages();
}
+
+ @Test
+ public void testRecreateMenu() {
+ NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+ row.createMenu(null);
+ row.createMenu(null);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
new file mode 100644
index 0000000..a69de7a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class NotificationViewWrapperTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ @Test
+ public void constructor_doesntUseViewContext() throws Exception {
+ new TestableNotificationViewWrapper(mContext, new View(null /* context */), null /* row */);
+ }
+
+ static class TestableNotificationViewWrapper extends NotificationViewWrapper {
+ protected TestableNotificationViewWrapper(Context ctx, View view,
+ ExpandableNotificationRow row) {
+ super(ctx, view, row);
+ }
+ }
+}
\ No newline at end of file
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index c532efb..0acbb02 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1282,7 +1282,9 @@
ANativeWindow *anw = nullptr;
if (sur != 0) {
+ // Connect the native window handle to buffer queue.
anw = ANativeWindow_fromSurface(_env, sur);
+ native_window_api_connect(anw, NATIVE_WINDOW_API_CPU);
}
rsAllocationSetSurface((RsContext)con, (RsAllocation)alloc, anw);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 0482e73..ac81565 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1631,7 +1631,7 @@
@Override
public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
- int profileId) {
+ int profileId, String packageName) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -1653,8 +1653,11 @@
Provider provider = mProviders.get(i);
AppWidgetProviderInfo info = provider.info;
- // Ignore an invalid provider or one not matching the filter.
- if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
+ // Ignore an invalid provider, one not matching the filter,
+ // or one that isn't in the given package, if any.
+ boolean inPackage = packageName == null
+ || provider.id.componentName.getPackageName().equals(packageName);
+ if (provider.zombie || (info.widgetCategory & categoryFilter) == 0 || !inPackage) {
continue;
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index be14440..502b5fc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -23,7 +23,6 @@
import static com.android.server.autofill.Helper.VERBOSE;
import static com.android.server.autofill.Helper.bundleToString;
-import android.Manifest;
import android.annotation.NonNull;
import android.app.ActivityManagerInternal;
import android.content.BroadcastReceiver;
@@ -36,7 +35,6 @@
import android.database.ContentObserver;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3d1c251..15ec98f 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -57,6 +57,7 @@
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.IResultReceiver;
@@ -290,7 +291,8 @@
+ " f=" + flags;
mRequestsHistory.log(historyItem);
- // TODO(b/33197203): Handle partitioning
+ // TODO(b/33197203): Handle scenario when user forced autofill after app was already
+ // autofilled.
final Session session = mSessions.get(activityToken);
if (session != null) {
// Already started...
@@ -430,8 +432,11 @@
void dumpLocked(String prefix, PrintWriter pw) {
final String prefix2 = prefix + " ";
+ pw.print(prefix); pw.print("User :"); pw.println(mUserId);
pw.print(prefix); pw.print("Component:"); pw.println(mInfo != null
? mInfo.getServiceInfo().getComponentName() : null);
+ pw.print(prefix); pw.print("Default component: ");
+ pw.println(mContext.getString(R.string.config_defaultAutofillService));
pw.print(prefix); pw.print("Disabled:"); pw.println(mDisabled);
if (VERBOSE && mInfo != null) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index ac7d19e..801769c 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -48,6 +48,7 @@
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.util.ArrayMap;
+import android.util.DebugUtils;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
@@ -112,20 +113,19 @@
@GuardedBy("mLock")
RemoteFillService mRemoteFillService;
- // TODO(b/33197203 , b/35707731): Use List once it supports partitioning
@GuardedBy("mLock")
- private FillResponse mCurrentResponse;
+ private ArrayList<FillResponse> mResponses;
/**
- * Used to remember which {@link Dataset} filled the session.
+ * Response that requires a service authentitcation request.
*/
- // TODO(b/33197203 , b/35707731): will be removed once it supports partitioning
@GuardedBy("mLock")
- private Dataset mAutoFilledDataset;
+ private FillResponse mResponseWaitingAuth;
/**
* Dataset that when tapped launched a service authentication request.
*/
+ @GuardedBy("mLock")
private Dataset mDatasetWaitingAuth;
/**
@@ -163,8 +163,8 @@
mClient = IAutoFillManagerClient.Stub.asInterface(client);
try {
client.linkToDeath(() -> {
- if (DEBUG) {
- Slog.d(TAG, "app binder died");
+ if (VERBOSE) {
+ Slog.v(TAG, "app binder died");
}
removeSelf();
@@ -193,6 +193,10 @@
notifyUnavailableToClient();
}
synchronized (mLock) {
+ if (response.getAuthentication() != null) {
+ // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
+ mResponseWaitingAuth = response;
+ }
processResponseLocked(response);
}
@@ -318,23 +322,27 @@
}
public void setAuthenticationResultLocked(Bundle data) {
- if (mCurrentResponse == null || data == null) {
+ if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) {
removeSelf();
} else {
final Parcelable result = data.getParcelable(
AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (result instanceof FillResponse) {
mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
-
- mCurrentResponse = (FillResponse) result;
- processResponseLocked(mCurrentResponse);
+ mResponseWaitingAuth = null;
+ processResponseLocked((FillResponse) result);
} else if (result instanceof Dataset) {
final Dataset dataset = (Dataset) result;
- final int index = mCurrentResponse.getDatasets().indexOf(mDatasetWaitingAuth);
- if (index >= 0) {
- mCurrentResponse.getDatasets().set(index, dataset);
- autoFill(dataset);
- mDatasetWaitingAuth = null;
+ for (int i = 0; i < mResponses.size(); i++) {
+ final FillResponse response = mResponses.get(i);
+ final int index = response.getDatasets().indexOf(mDatasetWaitingAuth);
+ if (index >= 0) {
+ response.getDatasets().set(index, dataset);
+ mDatasetWaitingAuth = null;
+ autoFill(dataset);
+ resetViewStatesLocked(dataset, ViewState.STATE_WAITING_DATASET_AUTH);
+ return;
+ }
}
}
}
@@ -354,15 +362,19 @@
Slog.wtf(TAG, "showSaveLocked(): no mStructure");
return true;
}
- if (mCurrentResponse == null) {
+ if (mResponses == null) {
// Happens when the activity / session was finished before the service replied, or
// when the service cannot autofill it (and returned a null response).
if (DEBUG) {
- Slog.d(TAG, "showSaveLocked(): no mCurrentResponse");
+ Slog.d(TAG, "showSaveLocked(): no responses on session");
}
return true;
}
- final SaveInfo saveInfo = mCurrentResponse.getSaveInfo();
+
+ // TODO(b/33197203 , b/35707731): must iterate over all responses
+ final FillResponse response = mResponses.get(0);
+
+ final SaveInfo saveInfo = response.getSaveInfo();
if (DEBUG) {
Slog.d(TAG, "showSaveLocked(): saveInfo=" + saveInfo);
}
@@ -385,7 +397,6 @@
return true;
}
- // TODO(b/33197203 , b/35707731): refactor excessive calls to getCurrentValue()
boolean allRequiredAreNotEmpty = true;
boolean atLeastOneChanged = false;
for (int i = 0; i < requiredIds.length; i++) {
@@ -393,7 +404,8 @@
final ViewState viewState = mViewStates.get(id);
if (viewState == null) {
Slog.w(TAG, "showSaveLocked(): no ViewState for required " + id);
- continue;
+ allRequiredAreNotEmpty = false;
+ break;
}
final AutofillValue currentValue = viewState.getCurrentValue();
@@ -462,7 +474,8 @@
Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
}
- final Bundle extras = this.mCurrentResponse.getExtras();
+ // TODO(b/33197203 , b/35707731): decide how to handle bundle in multiple partitions
+ final Bundle extras = mResponses != null ? mResponses.get(0).getExtras() : null;
for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) {
final AutofillValue value = entry.getValue().getCurrentValue();
@@ -497,16 +510,21 @@
}
void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
- if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) {
- // TODO(b/33197203): ignoring because we don't support partitions yet
- Slog.d(TAG, "updateLocked(): ignoring " + id + " after app was autofilled");
- return;
- }
-
ViewState viewState = mViewStates.get(id);
+
if (viewState == null) {
- viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL);
- mViewStates.put(id, viewState);
+ if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED)) != 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags));
+ }
+ viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL);
+ mViewStates.put(id, viewState);
+ } else if ((flags & FLAG_VIEW_ENTERED) != 0) {
+ viewState = startPartitionLocked(id);
+ } else {
+ if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id);
+ return;
+ }
}
if ((flags & FLAG_START_SESSION) != 0) {
@@ -530,7 +548,8 @@
}
// Update the internal state...
viewState.setState(ViewState.STATE_CHANGED);
- // ... and the chooser UI.
+
+ //..and the UI
if (value.isText()) {
getUiForShowing().filterFillUi(value.getTextValue().toString());
} else {
@@ -551,10 +570,6 @@
// If the ViewState is ready to be displayed, onReady() will be called.
viewState.update(value, virtualBounds);
- if (mCurrentResponse != null) {
- viewState.setResponse(mCurrentResponse);
- }
-
return;
}
@@ -566,7 +581,28 @@
return;
}
- Slog.w(TAG, "updateLocked(): unknown flags " + flags);
+ Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags));
+ }
+
+ private ViewState startPartitionLocked(AutofillId id) {
+ if (DEBUG) {
+ Slog.d(TAG, "Starting partition for view id " + id);
+ }
+ final ViewState viewState =
+ new ViewState(this, id, this,ViewState.STATE_STARTED_PARTITION);
+ mViewStates.put(id, viewState);
+
+ /*
+ * TODO(b/33197203 , b/35707731): when start a new partition, it should
+ *
+ * - add autofilled fields as sanitized
+ * - set focus on ViewStructure that triggered it
+ * - pass the first onFillRequest() bundle
+ * - optional: perhaps add a new flag onFilLRequest() to indicate it's a new partition?
+ */
+ mRemoteFillService.onFillRequest(mStructure, null, 0);
+
+ return viewState;
}
@Override
@@ -580,6 +616,10 @@
getUiForShowing().showFillUi(filledId, response, filterText, mPackageName);
}
+ String getFlagAsString(int flag) {
+ return DebugUtils.flagsToString(AutofillManager.class, "FLAG_", flag);
+ }
+
private void notifyUnavailableToClient() {
if (mCurrentViewId == null) {
// TODO(b/33197203): temporary sanity check; should never happen
@@ -597,8 +637,7 @@
private void processResponseLocked(FillResponse response) {
if (DEBUG) {
- Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
- + "):" + response);
+ Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response);
}
if (mCurrentViewId == null) {
@@ -607,7 +646,10 @@
return;
}
- mCurrentResponse = response;
+ if (mResponses == null) {
+ mResponses = new ArrayList<>(4);
+ }
+ mResponses.add(response);
setViewStatesLocked(response, ViewState.STATE_FILLABLE);
@@ -669,10 +711,22 @@
}
}
+ /**
+ * Resets the given state from all existing views in the given dataset.
+ */
+ private void resetViewStatesLocked(@NonNull Dataset dataset, int state) {
+ final ArrayList<AutofillId> ids = dataset.getFieldIds();
+ for (int j = 0; j < ids.size(); j++) {
+ final AutofillId id = ids.get(j);
+ final ViewState viewState = mViewStates.get(id);
+ if (viewState != null) {
+ viewState.resetState(state);
+ }
+ }
+ }
+
void autoFill(Dataset dataset) {
synchronized (mLock) {
- mAutoFilledDataset = dataset;
-
// Autofill it directly...
if (dataset.getAuthentication() == null) {
autoFillApp(dataset);
@@ -680,7 +734,9 @@
}
// ...or handle authentication.
+ // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
mDatasetWaitingAuth = dataset;
+ setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH);
final Intent fillInIntent = createAuthFillInIntent(mStructure, null);
startAuthentication(dataset.getAuthentication(), fillInIntent);
}
@@ -690,8 +746,8 @@
return mService.getServiceName();
}
- FillResponse getCurrentResponse() {
- return mCurrentResponse;
+ FillResponse getResponseWaitingAuth() {
+ return mResponseWaitingAuth;
}
private Intent createAuthFillInIntent(AssistStructure structure, Bundle extras) {
@@ -714,8 +770,8 @@
void dumpLocked(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("mFlags: "); pw.println(mFlags);
- pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse);
- pw.print(prefix); pw.print("mAutoFilledDataset: "); pw.println(mAutoFilledDataset);
+ pw.print(prefix); pw.print("mResponses: "); pw.println(mResponses);
+ pw.print(prefix); pw.print("mResponseWaitingAuth: "); pw.println(mResponseWaitingAuth);
pw.print(prefix); pw.print("mDatasetWaitingAuth: "); pw.println(mDatasetWaitingAuth);
pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId);
pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size());
@@ -811,4 +867,4 @@
destroyLocked();
mService.removeSessionLocked(mActivityToken);
}
-}
\ No newline at end of file
+}
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 20def0c..549f231 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -16,10 +16,13 @@
package com.android.server.autofill;
+import static com.android.server.autofill.Helper.DEBUG;
+
import android.annotation.Nullable;
import android.graphics.Rect;
import android.service.autofill.FillResponse;
import android.util.DebugUtils;
+import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -40,6 +43,8 @@
@Nullable AutofillValue value);
}
+ private static final String TAG = "ViewState";
+
// NOTE: state constants must be public because of flagstoString().
public static final int STATE_UNKNOWN = 0x00;
/** Initial state. */
@@ -52,6 +57,10 @@
public static final int STATE_CHANGED = 0x08;
/** Set only in the View that started a session. */
public static final int STATE_STARTED_SESSION = 0x10;
+ /** View that started a new partition when focused on. */
+ public static final int STATE_STARTED_PARTITION = 0x20;
+ /** User select a dataset in this view, but service must authenticate first. */
+ public static final int STATE_WAITING_DATASET_AUTH = 0x40;
public final AutofillId id;
private final Listener mListener;
@@ -122,9 +131,15 @@
}
void setState(int state) {
- // TODO(b/33197203 , b/35707731): currently it's always setting one state, but once it
- // supports partitioning it will need to 'or' some of them..
- mState = state;
+ if (mState == STATE_INITIAL) {
+ mState = state;
+ } else {
+ mState |= state;
+ }
+ }
+
+ void resetState(int state) {
+ mState &= ~state;
}
// TODO(b/33197203): need to refactor / rename / document this method to make it clear that
@@ -147,6 +162,12 @@
* fill UI is ready to be displayed (i.e. when response and bounds are set).
*/
void maybeCallOnFillReady() {
+ if ((mState & (STATE_AUTOFILLED | STATE_WAITING_DATASET_AUTH)) != 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
+ }
+ return;
+ }
// First try the current response associated with this View.
if (mResponse != null) {
if (mResponse.getDatasets() != null) {
@@ -155,9 +176,9 @@
return;
}
// Then checks if the session has a response waiting authentication; if so, uses it instead.
- final FillResponse currentResponse = mSession.getCurrentResponse();
- if (currentResponse != null && currentResponse.getAuthentication() != null) {
- mListener.onFillReady(currentResponse, this.id, mCurrentValue);
+ final FillResponse responseWaitingAuth = mSession.getResponseWaitingAuth();
+ if (responseWaitingAuth != null) {
+ mListener.onFillReady(responseWaitingAuth, this.id, mCurrentValue);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d38fb96..b69d1dc 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -101,8 +101,9 @@
content.measure(widthMeasureSpec, heightMeasureSpec);
content.setOnClickListener(v -> mCallback.onResponsePicked(response));
content.setElevation(context.getResources().getDimension(R.dimen.floating_window_z));
- mContentWidth = content.getMeasuredWidth();
- mContentHeight = content.getMeasuredHeight();
+ // TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width
+ mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
+ mContentHeight = Math.min(content.getMeasuredHeight(), 500);
mWindow = new AnchoredWindow(content);
mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index a5debda..9218c25 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -280,6 +280,7 @@
if (DBG) Log.d(TAG, "refreshBinding()");
// Make sure the scorer is up-to-date
mNetworkScorerAppManager.updateState();
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
registerPackageMonitorIfNeeded();
bindToScoringServiceIfNeeded();
}
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 1a3bb35..e127eb9 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -42,7 +42,6 @@
*
* @hide
*/
-@VisibleForTesting
public class NetworkScorerAppManager {
private static final String TAG = "NetworkScorerAppManager";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -64,8 +63,7 @@
* Returns the list of available scorer apps. The list will be empty if there are
* no valid scorers.
*/
- @VisibleForTesting
- public List<NetworkScorerAppData> getAllValidScorers() {
+ List<NetworkScorerAppData> getAllValidScorers() {
if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
final PackageManager pm = mContext.getPackageManager();
final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
@@ -170,8 +168,7 @@
* it was disabled or uninstalled).
*/
@Nullable
- @VisibleForTesting
- public NetworkScorerAppData getActiveScorer() {
+ NetworkScorerAppData getActiveScorer() {
final int enabledSetting = getNetworkRecommendationsEnabledSetting();
if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
return null;
@@ -214,8 +211,7 @@
* @return true if the scorer was changed, or false if the package is not a valid scorer or
* a valid network recommendation provider exists.
*/
- @VisibleForTesting
- public boolean setActiveScorer(String packageName) {
+ boolean setActiveScorer(String packageName) {
final String oldPackageName = getNetworkRecommendationsPackage();
if (TextUtils.equals(oldPackageName, packageName)) {
@@ -250,8 +246,7 @@
* is no longer valid then {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} will be set
* to <code>0</code> (disabled).
*/
- @VisibleForTesting
- public void updateState() {
+ void updateState() {
final int enabledSetting = getNetworkRecommendationsEnabledSetting();
if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
// Don't change anything if it's forced off.
@@ -286,6 +281,56 @@
}
}
+ /**
+ * Migrates the NETWORK_SCORER_APP Setting to the USE_OPEN_WIFI_PACKAGE Setting.
+ */
+ void migrateNetworkScorerAppSettingIfNeeded() {
+ final String scorerAppPkgNameSetting =
+ mSettingsFacade.getString(mContext, Settings.Global.NETWORK_SCORER_APP);
+ if (TextUtils.isEmpty(scorerAppPkgNameSetting)) {
+ // Early exit, nothing to do.
+ return;
+ }
+
+ final NetworkScorerAppData currentAppData = getActiveScorer();
+ if (currentAppData == null) {
+ // Don't touch anything until we have an active scorer to work with.
+ return;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "Migrating Settings.Global.NETWORK_SCORER_APP "
+ + "(" + scorerAppPkgNameSetting + ")...");
+ }
+
+ // If the new (useOpenWifi) Setting isn't set and the old Setting's value matches the
+ // new metadata value then update the new Setting with the old value. Otherwise it's a
+ // mismatch so we shouldn't enable the Setting automatically.
+ final ComponentName enableUseOpenWifiActivity =
+ currentAppData.getEnableUseOpenWifiActivity();
+ final String useOpenWifiSetting =
+ mSettingsFacade.getString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE);
+ if (TextUtils.isEmpty(useOpenWifiSetting)
+ && enableUseOpenWifiActivity != null
+ && scorerAppPkgNameSetting.equals(enableUseOpenWifiActivity.getPackageName())) {
+ mSettingsFacade.putString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE,
+ scorerAppPkgNameSetting);
+ if (DEBUG) {
+ Log.d(TAG, "Settings.Global.USE_OPEN_WIFI_PACKAGE set to "
+ + "'" + scorerAppPkgNameSetting + "'.");
+ }
+ }
+
+ // Clear out the old setting so we don't run through the migration code again.
+ mSettingsFacade.putString(mContext, Settings.Global.NETWORK_SCORER_APP, null);
+ if (DEBUG) {
+ Log.d(TAG, "Settings.Global.NETWORK_SCORER_APP migration complete.");
+ final String setting =
+ mSettingsFacade.getString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE);
+ Log.d(TAG, "Settings.Global.USE_OPEN_WIFI_PACKAGE is: '" + setting + "'.");
+ }
+ }
+
private String getDefaultPackageSetting() {
return mContext.getResources().getString(
R.string.config_defaultNetworkRecommendationProviderPackage);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index e560d32..738365d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -427,14 +427,13 @@
public boolean addAccountExplicitlyWithVisibility(Account account, String password,
Bundle extras, Map packageToVisibility) {
Bundle.setDefusable(extras, true);
-
- final int callingUid = Binder.getCallingUid();
+ int callingUid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
Preconditions.checkNotNull(account, "account cannot be null");
- int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
callingUid, account.type);
@@ -461,9 +460,9 @@
public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
String accountType) {
int callingUid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
boolean isSystemUid = UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
- List<String> managedTypes =
- getTypesForCaller(callingUid, UserHandle.getUserId(callingUid), isSystemUid);
+ List<String> managedTypes = getTypesForCaller(callingUid, userId, isSystemUid);
if ((accountType != null && !managedTypes.contains(accountType))
|| (accountType == null && !isSystemUid)) {
@@ -478,8 +477,9 @@
long identityToken = clearCallingIdentity();
try {
+ UserAccounts accounts = getUserAccounts(userId);
return getAccountsAndVisibilityForPackage(packageName, managedTypes, callingUid,
- getUserAccounts(UserHandle.getUserId(callingUid)));
+ accounts);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -490,12 +490,8 @@
*/
private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
List<String> accountTypes, Integer callingUid, UserAccounts accounts) {
- int uid = 0;
- try {
- uid = mPackageManager.getPackageUidAsUser(packageName,
- UserHandle.getUserId(callingUid));
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Package not found " + e.getMessage());
+ if (!packageExistsForUser(packageName, accounts.userId)) {
+ Log.d(TAG, "Package not found " + packageName);
return new LinkedHashMap<>();
}
@@ -520,19 +516,26 @@
public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
Preconditions.checkNotNull(account, "account cannot be null");
int callingUid = Binder.getCallingUid();
- int userId = UserHandle.getUserId(callingUid);
- UserAccounts accounts = getUserAccounts(userId);
+ int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)
&& !isSystemUid(callingUid)) {
String msg =
String.format("uid %s cannot get secrets for account %s", callingUid, account);
throw new SecurityException(msg);
}
- synchronized (accounts.dbLock) {
- synchronized (accounts.cacheLock) {
- return getPackagesAndVisibilityForAccountLocked(account, accounts);
+
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ synchronized (accounts.dbLock) {
+ synchronized (accounts.cacheLock) {
+ return getPackagesAndVisibilityForAccountLocked(account, accounts);
+ }
}
+ } finally {
+ restoreCallingIdentity(identityToken);
}
+
}
/**
@@ -560,8 +563,8 @@
Preconditions.checkNotNull(account, "account cannot be null");
Preconditions.checkNotNull(packageName, "packageName cannot be null");
int callingUid = Binder.getCallingUid();
- UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
- if (!isAccountManagedByCaller(account.type, callingUid, accounts.userId)
+ int userId = UserHandle.getCallingUserId();
+ if (!isAccountManagedByCaller(account.type, callingUid, userId)
&& !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot get secrets for accounts of type: %s",
@@ -569,7 +572,13 @@
account.type);
throw new SecurityException(msg);
}
- return resolveAccountVisibility(account, packageName, accounts);
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ return resolveAccountVisibility(account, packageName, accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
}
/**
@@ -708,8 +717,8 @@
Preconditions.checkNotNull(account, "account cannot be null");
Preconditions.checkNotNull(packageName, "packageName cannot be null");
int callingUid = Binder.getCallingUid();
- UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
- if (!isAccountManagedByCaller(account.type, callingUid, accounts.userId)
+ int userId = UserHandle.getCallingUserId();
+ if (!isAccountManagedByCaller(account.type, callingUid, userId)
&& !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot get secrets for accounts of type: %s",
@@ -717,8 +726,14 @@
account.type);
throw new SecurityException(msg);
}
- return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
}
/**
@@ -805,8 +820,15 @@
public void registerAccountListener(String[] accountTypes, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
- registerAccountListener(accountTypes, opPackageName,
- getUserAccounts(UserHandle.getUserId(callingUid)));
+
+ int userId = UserHandle.getCallingUserId();
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ registerAccountListener(accountTypes, opPackageName, accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
}
private void registerAccountListener(String[] accountTypes, String opPackageName,
@@ -832,7 +854,18 @@
public void unregisterAccountListener(String[] accountTypes, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
- UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
+ int userId = UserHandle.getCallingUserId();
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ unregisterAccountListener(accountTypes, opPackageName, accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ private void unregisterAccountListener(String[] accountTypes, String opPackageName,
+ UserAccounts accounts) {
synchronized (accounts.mReceiversForType) {
if (accountTypes == null) {
// null for any type
@@ -903,7 +936,7 @@
long identityToken = clearCallingIdentity();
try {
mPackageManager.getPackageUidAsUser(packageName, userId);
- return true; // package exist
+ return true;
} finally {
restoreCallingIdentity(identityToken);
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4cbfb27..7dd75df 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -31,8 +31,10 @@
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.app.ServiceStartArgs;
import android.content.IIntentSender;
import android.content.IntentSender;
+import android.content.pm.ParceledListSlice;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
@@ -369,7 +371,8 @@
}
// This app knows it is in the new model where this operation is not
// allowed, so tell it what has happened.
- return new ComponentName("?", "app is in background");
+ UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
+ return new ComponentName("?", "app is in background uid " + uidRec);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -1956,78 +1959,86 @@
return;
}
- while (r.pendingStarts.size() > 0) {
- Exception caughtException = null;
- ServiceRecord.StartItem si = null;
- try {
- si = r.pendingStarts.remove(0);
- if (DEBUG_SERVICE) {
- Slog.v(TAG_SERVICE, "Sending arguments to: "
- + r + " " + r.intent + " args=" + si.intent);
- }
- if (si.intent == null && N > 1) {
- // If somehow we got a dummy null intent in the middle,
- // then skip it. DO NOT skip a null intent when it is
- // the only one in the list -- this is to support the
- // onStartCommand(null) case.
- continue;
- }
- si.deliveredTime = SystemClock.uptimeMillis();
- r.deliveredStarts.add(si);
- si.deliveryCount++;
- if (si.neededGrants != null) {
- mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
- si.getUriPermissionsLocked());
- }
- mAm.grantEphemeralAccessLocked(r.userId, si.intent,
- r.appInfo.uid, UserHandle.getAppId(si.callingId));
- bumpServiceExecutingLocked(r, execInFg, "start");
- if (!oomAdjusted) {
- oomAdjusted = true;
- mAm.updateOomAdjLocked(r.app);
- }
- if (r.fgRequired && !r.fgWaiting) {
- if (!r.isForeground) {
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);
- }
- scheduleServiceForegroundTransitionTimeoutLocked(r);
- } else {
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.i(TAG, "Service already foreground; no new timeout: " + r);
- }
- r.fgRequired = false;
- }
- }
- int flags = 0;
- if (si.deliveryCount > 1) {
- flags |= Service.START_FLAG_RETRY;
- }
- if (si.doneExecutingCount > 0) {
- flags |= Service.START_FLAG_REDELIVERY;
- }
- r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
- } catch (TransactionTooLargeException e) {
- if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large: intent="
- + si.intent);
- caughtException = e;
- } catch (RemoteException e) {
- // Remote process gone... we'll let the normal cleanup take care of this.
- if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
- caughtException = e;
- } catch (Exception e) {
- Slog.w(TAG, "Unexpected exception", e);
- caughtException = e;
- }
+ ArrayList<ServiceStartArgs> args = new ArrayList<>();
- if (caughtException != null) {
- // Keep nesting count correct
- final boolean inDestroying = mDestroyingServices.contains(r);
- serviceDoneExecutingLocked(r, inDestroying, inDestroying);
- if (caughtException instanceof TransactionTooLargeException) {
- throw (TransactionTooLargeException)caughtException;
+ while (r.pendingStarts.size() > 0) {
+ ServiceRecord.StartItem si = r.pendingStarts.remove(0);
+ if (DEBUG_SERVICE) {
+ Slog.v(TAG_SERVICE, "Sending arguments to: "
+ + r + " " + r.intent + " args=" + si.intent);
+ }
+ if (si.intent == null && N > 1) {
+ // If somehow we got a dummy null intent in the middle,
+ // then skip it. DO NOT skip a null intent when it is
+ // the only one in the list -- this is to support the
+ // onStartCommand(null) case.
+ continue;
+ }
+ si.deliveredTime = SystemClock.uptimeMillis();
+ r.deliveredStarts.add(si);
+ si.deliveryCount++;
+ if (si.neededGrants != null) {
+ mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
+ si.getUriPermissionsLocked());
+ }
+ mAm.grantEphemeralAccessLocked(r.userId, si.intent,
+ r.appInfo.uid, UserHandle.getAppId(si.callingId));
+ bumpServiceExecutingLocked(r, execInFg, "start");
+ if (!oomAdjusted) {
+ oomAdjusted = true;
+ mAm.updateOomAdjLocked(r.app);
+ }
+ if (r.fgRequired && !r.fgWaiting) {
+ if (!r.isForeground) {
+ if (DEBUG_BACKGROUND_CHECK) {
+ Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);
+ }
+ scheduleServiceForegroundTransitionTimeoutLocked(r);
+ } else {
+ if (DEBUG_BACKGROUND_CHECK) {
+ Slog.i(TAG, "Service already foreground; no new timeout: " + r);
+ }
+ r.fgRequired = false;
}
- break;
+ }
+ int flags = 0;
+ if (si.deliveryCount > 1) {
+ flags |= Service.START_FLAG_RETRY;
+ }
+ if (si.doneExecutingCount > 0) {
+ flags |= Service.START_FLAG_REDELIVERY;
+ }
+ args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
+ }
+
+ ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
+ slice.setInlineCountLimit(4);
+ Exception caughtException = null;
+ try {
+ r.app.thread.scheduleServiceArgs(r, slice);
+ } catch (TransactionTooLargeException e) {
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size()
+ + " args, first: " + args.get(0).args);
+ Slog.w(TAG, "Failed delivering service starts", e);
+ caughtException = e;
+ } catch (RemoteException e) {
+ // Remote process gone... we'll let the normal cleanup take care of this.
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
+ Slog.w(TAG, "Failed delivering service starts", e);
+ caughtException = e;
+ } catch (Exception e) {
+ Slog.w(TAG, "Unexpected exception", e);
+ caughtException = e;
+ }
+
+ if (caughtException != null) {
+ // Keep nesting count correct
+ final boolean inDestroying = mDestroyingServices.contains(r);
+ for (int i = 0; i < args.size(); i++) {
+ serviceDoneExecutingLocked(r, inDestroying, inDestroying);
+ }
+ if (caughtException instanceof TransactionTooLargeException) {
+ throw (TransactionTooLargeException)caughtException;
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 19fc2b8..ee2fdba 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12143,6 +12143,24 @@
return false;
}
+ @Override
+ public void backgroundWhitelistUid(final int uid) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Only the OS may call backgroundWhitelistUid()");
+ }
+
+ if (DEBUG_BACKGROUND_CHECK) {
+ Slog.i(TAG, "Adding uid " + uid + " to bg uid whitelist");
+ }
+ synchronized (this) {
+ final int N = mBackgroundUidWhitelist.length;
+ int[] newList = new int[N+1];
+ System.arraycopy(mBackgroundUidWhitelist, 0, newList, 0, N);
+ newList[N] = uid;
+ mBackgroundUidWhitelist = newList;
+ }
+ }
+
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
String abiOverride) {
ProcessRecord app;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b72cd73..3e3fee5 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -745,7 +745,7 @@
}
/**
- * Returns a {@link TaskRecord} for the input id if available. Null otherwise.
+ * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
* @param id Id of the task we would like returned.
* @param matchMode The mode to match the given task id in.
* @param stackId The stack to restore the task to (default launch stack will be used if
@@ -765,7 +765,7 @@
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
- TaskRecord task = stack.taskForIdLocked(id);
+ final TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
}
@@ -780,11 +780,17 @@
// Otherwise, check the recent tasks and return if we find it there and we are not restoring
// the task from recents
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- TaskRecord task = mRecentTasks.taskForIdLocked(id);
- if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
- if (DEBUG_RECENTS && task == null) {
+ final TaskRecord task = mRecentTasks.taskForIdLocked(id);
+
+ if (task == null) {
+ if (DEBUG_RECENTS) {
Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
}
+
+ return null;
+ }
+
+ if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
return task;
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 82a0ff6..51aa4f8 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -103,6 +103,13 @@
apc.init();
synchronized(mPlayerLock) {
mPlayers.put(newPiid, apc);
+ if (mDuckedUids.contains(new Integer(apc.getClientUid()))) {
+ if (DEBUG) { Log.v(TAG, " > trackPlayer() piid=" + newPiid + " must be ducked"); }
+ mDuckedPlayers.add(new Integer(newPiid));
+ // FIXME here the player needs to be put in a state that is the same as if it
+ // had been ducked as it starts. At the moment, this works already for linked
+ // players, as is the case in gapless playback.
+ }
}
return newPiid;
}
@@ -141,6 +148,13 @@
Log.e(TAG, "Error handling event " + event);
change = false;
}
+ if (change && event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
+ && mDuckedUids.contains(new Integer(apc.getClientUid()))) {
+ if (DEBUG) { Log.v(TAG, " > playerEvent() piid=" + piid + " must be ducked"); }
+ if (!mDuckedPlayers.contains(new Integer(piid))) {
+ mDuckedPlayers.add(new Integer(piid));
+ }
+ }
}
if (change) {
dispatchPlaybackChange();
@@ -273,13 +287,20 @@
// PlayerFocusEnforcer implementation
private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
+ // size of 2 for typical cases of double-ducking, not expected to grow beyond that, but can
+ private final ArrayList<Integer> mDuckedUids = new ArrayList<Integer>(2);
@Override
public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
if (DEBUG) {
Log.v(TAG, String.format("duckPlayers: uids winner=%d loser=%d",
- winner.getClientUid(), loser.getClientUid())); }
+ winner.getClientUid(), loser.getClientUid()));
+ }
synchronized (mPlayerLock) {
+ final Integer loserUid = new Integer(loser.getClientUid());
+ if (!mDuckedUids.contains(loserUid)) {
+ mDuckedUids.add(loserUid);
+ }
if (mPlayers.isEmpty()) {
return true;
}
@@ -296,7 +317,7 @@
&& loser.hasSameUid(apc.getClientUid())
&& apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED)
{
- if (mDuckedPlayers.contains(piid)) {
+ if (mDuckedPlayers.contains(new Integer(piid))) {
if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); }
} else if (apc.getAudioAttributes().getContentType() ==
AudioAttributes.CONTENT_TYPE_SPEECH) {
@@ -313,7 +334,7 @@
apc.getPlayerProxy().applyVolumeShaper(
DUCK_VSHAPE,
PLAY_CREATE_IF_NEEDED);
- mDuckedPlayers.add(piid);
+ mDuckedPlayers.add(new Integer(piid));
} catch (Exception e) {
Log.e(TAG, "Error ducking player " + piid, e);
// something went wrong trying to duck, so let the app handle it
@@ -332,25 +353,36 @@
if (DEBUG) { Log.v(TAG, "unduckPlayers: uids winner=" + winner.getClientUid()); }
synchronized (mPlayerLock) {
if (mDuckedPlayers.isEmpty()) {
+ mDuckedUids.remove(new Integer(winner.getClientUid()));
return;
}
+ final ArrayList<Integer> playersToRemove =
+ new ArrayList<Integer>(mDuckedPlayers.size());
for (int piid : mDuckedPlayers) {
final AudioPlaybackConfiguration apc = mPlayers.get(piid);
- if (apc != null
- && winner.hasSameUid(apc.getClientUid())) {
- try {
- Log.v(TAG, "unducking player" + piid);
- mDuckedPlayers.remove(new Integer(piid));
- apc.getPlayerProxy().applyVolumeShaper(
- DUCK_ID,
- VolumeShaper.Operation.REVERSE);
- } catch (Exception e) {
- Log.e(TAG, "Error unducking player " + piid, e);
+ if (apc != null) {
+ if (winner.hasSameUid(apc.getClientUid())) {
+ try {
+ Log.v(TAG, "unducking player " + piid);
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_ID,
+ VolumeShaper.Operation.REVERSE);
+ } catch (Exception e) {
+ Log.e(TAG, "Error unducking player " + piid, e);
+ } finally {
+ playersToRemove.add(piid);
+ }
}
} else {
- Log.e(TAG, "Error unducking player " + piid + ", player not found");
+ // this piid was in the list of ducked players, but wasn't found, discard it
+ Log.v(TAG, "Error unducking player " + piid + ", player not found");
+ playersToRemove.add(piid);
}
}
+ for (int piid : playersToRemove) {
+ mDuckedPlayers.remove(new Integer(piid));
+ }
+ mDuckedUids.remove(new Integer(winner.getClientUid()));
}
}
@@ -383,7 +415,7 @@
try {
Log.v(TAG, "call: muting player" + piid);
apc.getPlayerProxy().setVolume(0.0f);
- mMutedPlayers.add(piid);
+ mMutedPlayers.add(new Integer(piid));
} catch (Exception e) {
Log.e(TAG, "call: error muting player " + piid, e);
}
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 0a6d8a4..8ad1bea 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -345,6 +345,7 @@
public void notePending(JobStatus job) {
final long now = SystemClock.uptimeMillis();
+ job.madePending = now;
rebatchIfNeeded(now);
mCurDataSet.incPending(job.getSourceUid(), job.getSourcePackageName(), now);
}
@@ -357,6 +358,7 @@
public void noteActive(JobStatus job) {
final long now = SystemClock.uptimeMillis();
+ job.madeActive = now;
rebatchIfNeeded(now);
if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 7c231ff..cd3ba4c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2035,27 +2035,35 @@
pw.print(" Evaluated priority: "); pw.println(priority);
}
pw.print(" Tag: "); pw.println(job.getTag());
+ pw.print(" Enq: ");
+ TimeUtils.formatDuration(now - job.madePending, pw);
+ pw.println(" ago");
}
pw.println();
pw.println("Active jobs:");
for (int i=0; i<mActiveServices.size(); i++) {
JobServiceContext jsc = mActiveServices.get(i);
pw.print(" Slot #"); pw.print(i); pw.print(": ");
- if (jsc.getRunningJob() == null) {
+ final JobStatus job = jsc.getRunningJob();
+ if (job == null) {
pw.println("inactive");
continue;
} else {
- pw.println(jsc.getRunningJob().toShortString());
+ pw.println(job.toShortString());
pw.print(" Running for: ");
TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
pw.print(", timeout at: ");
TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
pw.println();
- jsc.getRunningJob().dump(pw, " ", false);
+ job.dump(pw, " ", false);
int priority = evaluateJobPriorityLocked(jsc.getRunningJob());
if (priority != JobInfo.PRIORITY_DEFAULT) {
pw.print(" Evaluated priority: "); pw.println(priority);
}
+ pw.print(" Active at "); pw.println(job.madeActive);
+ pw.print(" Pending for ");
+ TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
+ pw.println();
}
}
if (filterUid == -1) {
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index f41e187..0e04d24 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -147,7 +147,6 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
-
if (action.equals(Intent.ACTION_SCREEN_ON)
|| action.equals(Intent.ACTION_DREAMING_STOPPED)) {
if (DEBUG) {
@@ -183,6 +182,11 @@
}
mIdle = true;
reportNewIdleState(mIdle);
+ } else {
+ if (DEBUG) {
+ Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
+ + mIdle + " screen=" + mScreenOn);
+ }
}
}
}
@@ -191,7 +195,7 @@
@Override
public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
pw.print("Idle: ");
- pw.println(mIdleTracker.isIdle() ? "true" : "false");
+ pw.println(mIdleTracker.isIdle());
pw.print("Tracking ");
pw.print(mTrackedTasks.size());
pw.println(":");
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 47630d0..d27d0e5 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -129,6 +129,10 @@
// Used by shell commands
public int overrideState = 0;
+ // Metrics about queue latency
+ public long madePending;
+ public long madeActive;
+
/**
* For use only by ContentObserverController: state it is maintaining about content URIs
* being observed.
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 5bdef9e..3705946 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -325,13 +325,11 @@
// Disable all other overlays.
allOverlays.remove(oi);
for (int i = 0; i < allOverlays.size(); i++) {
- mSettings.setEnabled(allOverlays.get(i).packageName, userId, false);
+ // TODO: Optimize this to only send updates after all changes.
+ setEnabled(allOverlays.get(i).packageName, false, userId);
}
- final PackageInfo targetPackage =
- mPackageManager.getPackageInfo(oi.targetPackageName, userId);
- mSettings.setEnabled(packageName, userId, enable);
- updateState(targetPackage, overlayPackage, userId);
+ setEnabled(packageName, enable, userId);
return true;
} catch (OverlayManagerSettings.BadKeyException e) {
return false;
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index b0730ef..f6e96b2 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -47,7 +48,7 @@
* service and handling all interactions in a timely manner.
* @hide
*/
-final class EphemeralResolverConnection {
+final class EphemeralResolverConnection implements DeathRecipient {
// This is running in a critical section and the timeout must be sufficiently low
private static final long BIND_SERVICE_TIMEOUT_MS =
("eng".equals(Build.TYPE)) ? 300 : 200;
@@ -65,7 +66,7 @@
public EphemeralResolverConnection(Context context, ComponentName componentName) {
mContext = context;
- mIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE).setComponent(componentName);
+ mIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE).setComponent(componentName);
}
public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[],
@@ -171,6 +172,15 @@
}
}
+ @Override
+ public void binderDied() {
+ if (mRemoteInstance != null) {
+ mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ }
+ mRemoteInstance = null;
+ mBindRequested = false;
+ }
+
/**
* Asynchronous callback when results come back from ephemeral resolution phase two.
*/
@@ -183,7 +193,11 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
- mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
+ try {
+ service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/);
+ mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
+ } catch (RemoteException e) {
+ }
mLock.notifyAll();
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 7eef7ad..9f7c4a2 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -66,6 +66,7 @@
public static final int FLAG_FREE_CACHE_V2 = 1 << 13;
public static final int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
public static final int FLAG_FREE_CACHE_NOOP = 1 << 15;
+ public static final int FLAG_FORCE = 1 << 16;
private final boolean mIsolated;
@@ -202,6 +203,15 @@
}
}
+ public void fixupAppData(String uuid, int flags) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.fixupAppData(uuid, flags);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
String dataAppName, int appId, String seInfo, int targetSdkVersion)
throws InstallerException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d89b12e..fe40efb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -608,6 +608,10 @@
final boolean mIsPreNUpgrade;
final boolean mIsPreNMR1Upgrade;
+ // Have we told the Activity Manager to whitelist the default container service by uid yet?
+ @GuardedBy("mPackages")
+ boolean mDefaultContainerWhitelisted = false;
+
@GuardedBy("mPackages")
private boolean mDexOptDialogShown;
@@ -842,11 +846,11 @@
/** The service connection to the ephemeral resolver */
final EphemeralResolverConnection mInstantAppResolverConnection;
+ /** Component used to show resolver settings for Instant Apps */
+ final ComponentName mInstantAppResolverSettingsComponent;
/** Component used to install ephemeral applications */
ComponentName mInstantAppInstallerComponent;
- /** Component used to show resolver settings for Instant Apps */
- ComponentName mInstantAppResolverSettingsComponent;
ActivityInfo mInstantAppInstallerActivity;
final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo();
@@ -2717,6 +2721,15 @@
UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
true /* onlyCoreApps */);
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "fixup");
+ try {
+ mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Trouble fixing GIDs", e);
+ }
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+
if (deferPackages == null || deferPackages.isEmpty()) {
return;
}
@@ -2807,11 +2820,13 @@
}
mInstantAppResolverConnection =
new EphemeralResolverConnection(mContext, ephemeralResolverComponent);
+ mInstantAppResolverSettingsComponent =
+ getEphemeralResolverSettingsLPr(ephemeralResolverComponent);
} else {
mInstantAppResolverConnection = null;
+ mInstantAppResolverSettingsComponent = null;
}
updateInstantAppInstallerLocked();
- mInstantAppResolverSettingsComponent = getEphemeralResolverSettingsLPr();
// Read and update the usage of dex files.
// Do this at the end of PM init so that all the packages have their
@@ -3045,10 +3060,18 @@
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
- final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
+ final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE);
+ List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
-
+ // temporarily look for the old action
+ if (resolvers.size() == 0) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral resolver not found with new action; try old one");
+ }
+ resolverIntent.setAction(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
+ resolvers = queryIntentServicesInternal(resolverIntent, null,
+ resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
+ }
final int N = resolvers.size();
if (N == 0) {
if (DEBUG_EPHEMERAL) {
@@ -3087,7 +3110,7 @@
}
private @Nullable ActivityInfo getEphemeralInstallerLPr() {
- final Intent intent = new Intent(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+ final Intent intent = new Intent(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
@@ -3095,8 +3118,17 @@
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+ List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
resolveFlags, UserHandle.USER_SYSTEM);
+ // temporarily look for the old action
+ if (matches.isEmpty()) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral installer not found with new action; try old one");
+ }
+ intent.setAction(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+ matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+ resolveFlags, UserHandle.USER_SYSTEM);
+ }
Iterator<ResolveInfo> iter = matches.iterator();
while (iter.hasNext()) {
final ResolveInfo rInfo = iter.next();
@@ -3119,35 +3151,27 @@
}
}
- private @Nullable ComponentName getEphemeralResolverSettingsLPr() {
- final Intent intent = new Intent(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- final int resolveFlags =
- MATCH_DIRECT_BOOT_AWARE
- | MATCH_DIRECT_BOOT_UNAWARE
- | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
- resolveFlags, UserHandle.USER_SYSTEM);
- Iterator<ResolveInfo> iter = matches.iterator();
- while (iter.hasNext()) {
- final ResolveInfo rInfo = iter.next();
- final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
- if (ps != null) {
- final PermissionsState permissionsState = ps.getPermissionsState();
- if (permissionsState.hasPermission(Manifest.permission.ACCESS_INSTANT_APPS, 0)) {
- continue;
- }
+ private @Nullable ComponentName getEphemeralResolverSettingsLPr(
+ @NonNull ComponentName resolver) {
+ final Intent intent = new Intent(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .setPackage(resolver.getPackageName());
+ final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+ List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+ UserHandle.USER_SYSTEM);
+ // temporarily look for the old action
+ if (matches.isEmpty()) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral resolver settings not found with new action; try old one");
}
- iter.remove();
+ intent.setAction(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
+ matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+ UserHandle.USER_SYSTEM);
}
- if (matches.size() == 0) {
+ if (matches.isEmpty()) {
return null;
- } else if (matches.size() == 1) {
- return matches.get(0).getComponentInfo().getComponentName();
- } else {
- throw new RuntimeException(
- "There must be at most one ephemeral resolver settings; found " + matches);
}
+ return matches.get(0).getComponentInfo().getComponentName();
}
private void primeDomainVerificationsLPw(int userId) {
@@ -13030,7 +13054,18 @@
intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
IActivityManager am = ActivityManager.getService();
if (am != null) {
+ int dcsUid = -1;
+ synchronized (mPackages) {
+ if (!mDefaultContainerWhitelisted) {
+ mDefaultContainerWhitelisted = true;
+ PackageSetting ps = mSettings.mPackages.get(DEFAULT_CONTAINER_PACKAGE);
+ dcsUid = UserHandle.getUid(UserHandle.USER_SYSTEM, ps.appId);
+ }
+ }
try {
+ if (dcsUid > 0) {
+ am.backgroundWhitelistUid(dcsUid);
+ }
am.startService(null, intent, null, -1, null, false, mContext.getOpPackageName(),
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
@@ -16965,6 +17000,15 @@
return;
}
+ // Shared libraries for the package need to be updated.
+ synchronized (mPackages) {
+ try {
+ updateSharedLibrariesLPr(pkg, null);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
+ }
+ }
+
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` may not be in `mPackages` yet.
@@ -17013,6 +17057,7 @@
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
+
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
@@ -17639,6 +17684,7 @@
int removedAppId = -1;
int[] origUsers;
int[] removedUsers = null;
+ int[] broadcastUsers = null;
SparseArray<Integer> installReasons;
boolean isRemovedPackageSystemUpdate = false;
boolean isUpdate;
@@ -17712,16 +17758,16 @@
extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
if (removedPackage != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, 0, null, null, removedUsers);
+ extras, 0, null, null, broadcastUsers);
if (dataRemoved && !isRemovedPackageSystemUpdate) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, removedUsers);
+ null, null, broadcastUsers);
}
}
if (removedAppId >= 0) {
sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, 0, null, null,
- removedUsers);
+ broadcastUsers);
}
}
}
@@ -17750,6 +17796,20 @@
outInfo.removedUsers = deletedPs != null
? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
: null;
+ if (outInfo.removedUsers == null) {
+ outInfo.broadcastUsers = null;
+ } else {
+ outInfo.broadcastUsers = EMPTY_INT_ARRAY;
+ int[] allUsers = outInfo.removedUsers;
+ for (int i = allUsers.length - 1; i >= 0; --i) {
+ final int userId = allUsers[i];
+ if (deletedPs.getInstantApp(userId)) {
+ continue;
+ }
+ outInfo.broadcastUsers =
+ ArrayUtils.appendInt(outInfo.broadcastUsers, userId);
+ }
+ }
}
}
@@ -20858,13 +20918,6 @@
mSettings.dumpRestoredPermissionGrantsLPr(pw, dumpState);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) {
- // XXX should handle packageName != null by dumping only install data that
- // the given package is involved with.
- if (dumpState.onTitlePrinted()) pw.println();
- mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
- }
-
if (!checkin && dumpState.isDumping(DumpState.DUMP_FROZEN) && packageName == null) {
// XXX should handle packageName != null by dumping only install data that
// the given package is involved with.
@@ -20935,6 +20988,14 @@
}
}
}
+
+ // PackageInstaller should be called outside of mPackages lock
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) {
+ // XXX should handle packageName != null by dumping only install data that
+ // the given package is involved with.
+ if (dumpState.onTitlePrinted()) pw.println();
+ mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
+ }
}
private void dumpProto(FileDescriptor fd) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6fb056a..554deae 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4777,7 +4777,7 @@
pw.print(" notLaunched=");
pw.print(ps.getNotLaunched(user.id));
pw.print(" enabled=");
- pw.println(ps.getEnabled(user.id));
+ pw.print(ps.getEnabled(user.id));
pw.print(" instant=");
pw.println(ps.getInstantApp(user.id));
String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 218d218..32871bb 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -763,8 +763,10 @@
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
+ // ShutdownThread displays UI, so give it a UI context.
mHandler.post(() ->
- ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, false));
+ ShutdownThread.shutdown(getUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, false));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -780,11 +782,11 @@
try {
mHandler.post(() -> {
// ShutdownThread displays UI, so give it a UI context.
- Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
if (safeMode) {
- ShutdownThread.rebootSafeMode(uiContext, false);
+ ShutdownThread.rebootSafeMode(getUiContext(), false);
} else {
- ShutdownThread.reboot(uiContext, PowerManager.SHUTDOWN_USER_REQUESTED, false);
+ ShutdownThread.reboot(getUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, false);
}
});
} finally {
@@ -1018,4 +1020,8 @@
}
}
}
+
+ private static final Context getUiContext() {
+ return ActivityThread.currentActivityThread().getSystemUiContext();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 9197ccf9..0694eae 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -22,6 +22,7 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
@@ -170,6 +171,7 @@
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
enableUseOpenWifiComponent.getPackageName());
+ mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
@@ -350,6 +352,173 @@
eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
}
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerAppIsNull()
+ throws Exception {
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP)).thenReturn(null);
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerAppIsEmpty()
+ throws Exception {
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP)).thenReturn("");
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerIsNotActive()
+ throws Exception {
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP)).thenReturn("com.foo.package");
+ // Make getActiveScorer() return null.
+ setRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiSettingIsNotEmpty()
+ throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+ enableUseOpenWifiComponent.getPackageName());
+ mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP))
+ .thenReturn(enableUseOpenWifiComponent.getPackageName());
+ // The setting has a value so the migration shouldn't touch it.
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE))
+ .thenReturn(enableUseOpenWifiComponent.getPackageName());
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ verify(mSettingsFacade).putString(eq(mMockContext),
+ eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiActivityNotAvail()
+ throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ // The active component doesn't have an open wifi activity so the migration shouldn't
+ // set USE_OPEN_WIFI_PACKAGE.
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+ null /*useOpenWifiActivityPackage*/);
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP))
+ .thenReturn(enableUseOpenWifiComponent.getPackageName());
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ verify(mSettingsFacade).putString(eq(mMockContext),
+ eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_activity()
+ throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+ enableUseOpenWifiComponent.getPackageName());
+ mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+ // The older network scorer app setting doesn't match the new use open wifi activity package
+ // so the migration shouldn't set USE_OPEN_WIFI_PACKAGE.
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP))
+ .thenReturn(enableUseOpenWifiComponent.getPackageName() + ".diff");
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ verify(mSettingsFacade).putString(eq(mMockContext),
+ eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_service()
+ throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+ enableUseOpenWifiComponent.getPackageName());
+ mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+ // The older network scorer app setting doesn't match the active package so the migration
+ // shouldn't set USE_OPEN_WIFI_PACKAGE.
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP))
+ .thenReturn(recoComponent.getPackageName() + ".diff");
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade, never()).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+ verify(mSettingsFacade).putString(eq(mMockContext),
+ eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+ }
+
+ @Test
+ public void testMigrateNetworkScorerAppSettingIfNeeded_packageMatch_activity()
+ throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+ enableUseOpenWifiComponent.getPackageName());
+ mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+ // Old setting matches the new activity package, migration should happen.
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_SCORER_APP))
+ .thenReturn(enableUseOpenWifiComponent.getPackageName());
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+ mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+ verify(mSettingsFacade).putString(eq(mMockContext),
+ eq(Settings.Global.USE_OPEN_WIFI_PACKAGE),
+ eq(enableUseOpenWifiComponent.getPackageName()));
+ verify(mSettingsFacade).putString(eq(mMockContext),
+ eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+ }
+
private void setRecommendationsEnabledSetting(int value) {
when(mSettingsFacade.getInt(eq(mMockContext),
eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt())).thenReturn(value);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index aa37407..5d0c23f 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -149,7 +149,7 @@
// 2nd account
Account account2 = new Account("name", "example2.com");
long accId2 = mAccountsDb.insertCeAccount(account2, "password");
- mAccountsDb.insertDeAccount(account2, accId);
+ mAccountsDb.insertDeAccount(account2, accId2);
mAccountsDb.insertAuthToken(accId2, "type", "token");
mAccountsDb.deleteAuthTokensByAccountId(accId2);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
new file mode 100644
index 0000000..b59c2bc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertNull;
+
+import android.os.Debug;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+
+/**
+ * Tests for the {@link ActivityStackSupervisor} class.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityStackSupervisorTests extends ActivityTestsBase {
+ /**
+ * This test ensures that we do not try to restore a task based off an invalid task id. The
+ * stack supervisor is a test version so there will be no tasks present. We should expect
+ * {@code null} to be returned in this case.
+ */
+ @Test
+ public void testRestoringInvalidTask() throws Exception {
+ Debug.waitForDebugger();
+ final ActivityManagerService service = createActivityManagerService();
+ TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
+ assertNull(task);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index c5cc2ff..5240586 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -25,7 +25,7 @@
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import com.android.server.AttributeCache;
@@ -34,6 +34,7 @@
import com.android.server.wm.WindowManagerService;
import com.android.server.wm.WindowTestUtils;
+import org.junit.After;
import org.junit.Before;
import org.mockito.MockitoAnnotations;
@@ -42,8 +43,7 @@
*/
public class ActivityTestsBase {
private final Context mContext = InstrumentationRegistry.getContext();
- private static boolean sLooperPrepared;
- private Handler mHandler;
+ private HandlerThread mHandlerThread;
// Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
// be called at before any tests.
@@ -52,11 +52,13 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
+ mHandlerThread.start();
+ }
- if (!sLooperPrepared) {
- sLooperPrepared = true;
- Looper.prepare();
- }
+ @After
+ public void tearDown() {
+ mHandlerThread.quitSafely();
}
protected ActivityManagerService createActivityManagerService() {
@@ -126,7 +128,7 @@
@Override
protected ActivityStackSupervisor createStackSupervisor() {
- return new TestActivityStackSupervisor(this, new Handler().getLooper());
+ return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f3f68ff..2663aaf 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -50,6 +50,7 @@
import org.mockito.ArgumentCaptor;
+import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -249,6 +250,25 @@
assertEquals(7, updates.size());
}
+ public void testGetInstalledProvidersForPackage() {
+ List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
+ assertTrue(!allProviders.isEmpty());
+ String packageName = allProviders.get(0).provider.getPackageName();
+ List<AppWidgetProviderInfo> providersForPackage = mManager.getInstalledProvidersForPackage(
+ packageName, null);
+ // Remove providers from allProviders that don't have the given package name.
+ Iterator<AppWidgetProviderInfo> iter = allProviders.iterator();
+ while (iter.hasNext()) {
+ if (!iter.next().provider.getPackageName().equals(packageName)) {
+ iter.remove();
+ }
+ }
+ assertEquals(allProviders.size(), providersForPackage.size());
+ for (int i = 0; i < allProviders.size(); i++) {
+ assertEquals(allProviders.get(i).provider, providersForPackage.get(i).provider);
+ }
+ }
+
private int setupHostAndWidget() {
List<PendingHostUpdate> updates = mService.startListening(
mMockHost, mPkgName, HOST_ID, new int[0]).getList();
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 92233b1..f80ee73 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -356,6 +356,7 @@
private final StatusHints mStatusHints;
private final Bundle mExtras;
private final Bundle mIntentExtras;
+ private final long mCreationTimeMillis;
/**
* Whether the supplied capabilities supports the specified capability.
@@ -578,9 +579,12 @@
}
/**
- * @return The time the {@code Call} has been connected. This information is updated
- * periodically, but user interfaces should not rely on this to display any "call time
- * clock".
+ * Returns the time the {@link Call} connected (i.e. became active). This information is
+ * updated periodically, but user interfaces should not rely on this to display the "call
+ * time clock". For the time when the call was first added to Telecom, see
+ * {@link #getCreationTimeMillis()}.
+ *
+ * @return The time the {@link Call} connected in milliseconds since the epoch.
*/
public final long getConnectTimeMillis() {
return mConnectTimeMillis;
@@ -622,6 +626,18 @@
return mIntentExtras;
}
+ /**
+ * Returns the time when the call was first created and added to Telecom. This is the same
+ * time that is logged as the start time in the Call Log (see
+ * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
+ * (became active), see {@link #getConnectTimeMillis()}.
+ *
+ * @return The creation time of the call, in millis since the epoch.
+ */
+ public long getCreationTimeMillis() {
+ return mCreationTimeMillis;
+ }
+
@Override
public boolean equals(Object o) {
if (o instanceof Details) {
@@ -641,28 +657,29 @@
Objects.equals(mVideoState, d.mVideoState) &&
Objects.equals(mStatusHints, d.mStatusHints) &&
areBundlesEqual(mExtras, d.mExtras) &&
- areBundlesEqual(mIntentExtras, d.mIntentExtras);
+ areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
+ Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
}
return false;
}
@Override
public int hashCode() {
- return
- Objects.hashCode(mHandle) +
- Objects.hashCode(mHandlePresentation) +
- Objects.hashCode(mCallerDisplayName) +
- Objects.hashCode(mCallerDisplayNamePresentation) +
- Objects.hashCode(mAccountHandle) +
- Objects.hashCode(mCallCapabilities) +
- Objects.hashCode(mCallProperties) +
- Objects.hashCode(mDisconnectCause) +
- Objects.hashCode(mConnectTimeMillis) +
- Objects.hashCode(mGatewayInfo) +
- Objects.hashCode(mVideoState) +
- Objects.hashCode(mStatusHints) +
- Objects.hashCode(mExtras) +
- Objects.hashCode(mIntentExtras);
+ return Objects.hash(mHandle,
+ mHandlePresentation,
+ mCallerDisplayName,
+ mCallerDisplayNamePresentation,
+ mAccountHandle,
+ mCallCapabilities,
+ mCallProperties,
+ mDisconnectCause,
+ mConnectTimeMillis,
+ mGatewayInfo,
+ mVideoState,
+ mStatusHints,
+ mExtras,
+ mIntentExtras,
+ mCreationTimeMillis);
}
/** {@hide} */
@@ -681,7 +698,8 @@
int videoState,
StatusHints statusHints,
Bundle extras,
- Bundle intentExtras) {
+ Bundle intentExtras,
+ long creationTimeMillis) {
mTelecomCallId = telecomCallId;
mHandle = handle;
mHandlePresentation = handlePresentation;
@@ -697,6 +715,7 @@
mStatusHints = statusHints;
mExtras = extras;
mIntentExtras = intentExtras;
+ mCreationTimeMillis = creationTimeMillis;
}
/** {@hide} */
@@ -716,7 +735,8 @@
parcelableCall.getVideoState(),
parcelableCall.getStatusHints(),
parcelableCall.getExtras(),
- parcelableCall.getIntentExtras());
+ parcelableCall.getIntentExtras(),
+ parcelableCall.getCreationTimeMillis());
}
@Override
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 85a92d1..6212a77 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -59,6 +59,7 @@
private final List<String> mConferenceableCallIds;
private final Bundle mIntentExtras;
private final Bundle mExtras;
+ private final long mCreationTimeMillis;
public ParcelableCall(
String id,
@@ -85,7 +86,8 @@
int videoState,
List<String> conferenceableCallIds,
Bundle intentExtras,
- Bundle extras) {
+ Bundle extras,
+ long creationTimeMillis) {
mId = id;
mState = state;
mDisconnectCause = disconnectCause;
@@ -111,6 +113,7 @@
mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds);
mIntentExtras = intentExtras;
mExtras = extras;
+ mCreationTimeMillis = creationTimeMillis;
}
/** The unique ID of the call. */
@@ -289,6 +292,13 @@
return mIsVideoCallProviderChanged;
}
+ /**
+ * @return The time the call was created, in milliseconds since the epoch.
+ */
+ public long getCreationTimeMillis() {
+ return mCreationTimeMillis;
+ }
+
/** Responsible for creating ParcelableCall objects for deserialized Parcels. */
public static final Parcelable.Creator<ParcelableCall> CREATOR =
new Parcelable.Creator<ParcelableCall> () {
@@ -324,6 +334,7 @@
int supportedAudioRoutes = source.readInt();
boolean isRttCallChanged = source.readByte() == 1;
ParcelableRttCall rttCall = source.readParcelable(classLoader);
+ long creationTimeMillis = source.readLong();
return new ParcelableCall(
id,
state,
@@ -349,7 +360,8 @@
videoState,
conferenceableCallIds,
intentExtras,
- extras);
+ extras,
+ creationTimeMillis);
}
@Override
@@ -393,6 +405,7 @@
destination.writeInt(mSupportedAudioRoutes);
destination.writeByte((byte) (mIsRttCallChanged ? 1 : 0));
destination.writeParcelable(mRttCall, 0);
+ destination.writeLong(mCreationTimeMillis);
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index b4c531e..f9875c5 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -53,8 +53,9 @@
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
+ * @deprecated use {@link Intent#ACTION_SERVICE_STATE}
*/
- public static final String ACTION_SERVICE_STATE_CHANGED = "android.intent.action.SERVICE_STATE";
+ public static final String ACTION_SERVICE_STATE_CHANGED = Intent.ACTION_SERVICE_STATE;
/**
* <p>Broadcast Action: The radio technology has changed. The intent will have the following
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
index 36ebc90..71067ae 100644
--- a/tests/UiBench/Android.mk
+++ b/tests/UiBench/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := 24
+LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
# omit gradle 'build' dir
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 8461905..90f713b 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -155,7 +155,10 @@
xml::XmlPullParser* parser, std::string* out_raw_string, StyleString* out_style_string,
std::vector<UntranslatableSection>* out_untranslatable_sections) {
// Keeps track of formatting tags (<b>, <i>) and the range of characters for which they apply.
- std::vector<Span> span_stack;
+ // The stack elements refer to the indices in out_style_string->spans.
+ // By first adding to the out_style_string->spans vector, and then using the stack to refer
+ // to this vector, the original order of tags is preserved in cases such as <b><i>hello</b></i>.
+ std::vector<size_t> span_stack;
// Clear the output variables.
out_raw_string->clear();
@@ -192,7 +195,9 @@
return false;
}
- span_stack.push_back(Span{std::move(span_name), static_cast<uint32_t>(builder.Utf16Len())});
+ out_style_string->spans.push_back(
+ Span{std::move(span_name), static_cast<uint32_t>(builder.Utf16Len())});
+ span_stack.push_back(out_style_string->spans.size() - 1);
} else if (parser->element_namespace() == sXliffNamespaceUri) {
if (parser->element_name() == "g") {
if (untranslatable_start_depth) {
@@ -233,9 +238,8 @@
if (parser->element_namespace().empty()) {
// This is an HTML tag which we encode as a span. Update the span
// stack and pop the top entry.
- Span& top_span = span_stack.back();
+ Span& top_span = out_style_string->spans[span_stack.back()];
top_span.last_char = builder.Utf16Len() - 1;
- out_style_string->spans.push_back(std::move(top_span));
span_stack.pop_back();
} else if (untranslatable_start_depth == make_value(depth)) {
// This is the end of an untranslatable section. Use UTF8 indices/lengths.
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index eefa320..8062c2e6 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -101,20 +101,24 @@
// Use a surrogate pair unicode point so that we can verify that the span
// indices use UTF-16 length and not UTF-8 length.
std::string input =
- "<string name=\"foo\">This is my aunt\u2019s <b>string</b></string>";
+ "<string name=\"foo\">This is my aunt\u2019s <b>fickle <small>string</small></b></string>";
ASSERT_TRUE(TestParse(input));
StyledString* str = test::GetValue<StyledString>(&table_, "string/foo");
ASSERT_NE(nullptr, str);
- const std::string expected_str = "This is my aunt\u2019s string";
+ const std::string expected_str = "This is my aunt\u2019s fickle string";
EXPECT_EQ(expected_str, *str->value->str);
- EXPECT_EQ(1u, str->value->spans.size());
+ EXPECT_EQ(2u, str->value->spans.size());
EXPECT_TRUE(str->untranslatable_sections.empty());
EXPECT_EQ(std::string("b"), *str->value->spans[0].name);
EXPECT_EQ(17u, str->value->spans[0].first_char);
- EXPECT_EQ(23u, str->value->spans[0].last_char);
+ EXPECT_EQ(30u, str->value->spans[0].last_char);
+
+ EXPECT_EQ(std::string("small"), *str->value->spans[1].name);
+ EXPECT_EQ(24u, str->value->spans[1].first_char);
+ EXPECT_EQ(30u, str->value->spans[1].last_char);
}
TEST_F(ResourceParserTest, ParseStringWithWhitespace) {
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index fad9edd..a031ea4 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -22,136 +22,194 @@
#include "ResourceValues.h"
#include "ValueVisitor.h"
#include "compile/Pseudolocalizer.h"
+#include "util/Util.h"
using android::StringPiece;
+using android::StringPiece16;
namespace aapt {
-std::unique_ptr<StyledString> PseudolocalizeStyledString(
- StyledString* string, Pseudolocalizer::Method method, StringPool* pool) {
+// The struct that represents both Span objects and UntranslatableSections.
+struct UnifiedSpan {
+ // Only present for Span objects. If not present, this was an UntranslatableSection.
+ Maybe<std::string> tag;
+
+ // The UTF-16 index into the string where this span starts.
+ uint32_t first_char;
+
+ // The UTF-16 index into the string where this span ends, inclusive.
+ uint32_t last_char;
+};
+
+inline static bool operator<(const UnifiedSpan& left, const UnifiedSpan& right) {
+ if (left.first_char < right.first_char) {
+ return true;
+ } else if (left.first_char > right.first_char) {
+ return false;
+ } else if (left.last_char < right.last_char) {
+ return true;
+ }
+ return false;
+}
+
+inline static UnifiedSpan SpanToUnifiedSpan(const StringPool::Span& span) {
+ return UnifiedSpan{*span.name, span.first_char, span.last_char};
+}
+
+inline static UnifiedSpan UntranslatableSectionToUnifiedSpan(const UntranslatableSection& section) {
+ return UnifiedSpan{
+ {}, static_cast<uint32_t>(section.start), static_cast<uint32_t>(section.end) - 1};
+}
+
+// Merges the Span and UntranslatableSections of this StyledString into a single vector of
+// UnifiedSpans. This will first check that the Spans are sorted in ascending order.
+static std::vector<UnifiedSpan> MergeSpans(const StyledString& string) {
+ // Ensure the Spans are sorted and converted.
+ std::vector<UnifiedSpan> sorted_spans;
+ sorted_spans.reserve(string.value->spans.size());
+ std::transform(string.value->spans.begin(), string.value->spans.end(),
+ std::back_inserter(sorted_spans), SpanToUnifiedSpan);
+
+ // Stable sort to ensure tag sequences like "<b><i>" are preserved.
+ std::stable_sort(sorted_spans.begin(), sorted_spans.end());
+
+ // Ensure the UntranslatableSections are sorted and converted.
+ std::vector<UnifiedSpan> sorted_untranslatable_sections;
+ sorted_untranslatable_sections.reserve(string.untranslatable_sections.size());
+ std::transform(string.untranslatable_sections.begin(), string.untranslatable_sections.end(),
+ std::back_inserter(sorted_untranslatable_sections),
+ UntranslatableSectionToUnifiedSpan);
+ std::sort(sorted_untranslatable_sections.begin(), sorted_untranslatable_sections.end());
+
+ std::vector<UnifiedSpan> merged_spans;
+ merged_spans.reserve(sorted_spans.size() + sorted_untranslatable_sections.size());
+ auto span_iter = sorted_spans.begin();
+ auto untranslatable_iter = sorted_untranslatable_sections.begin();
+ while (span_iter != sorted_spans.end() &&
+ untranslatable_iter != sorted_untranslatable_sections.end()) {
+ if (*span_iter < *untranslatable_iter) {
+ merged_spans.push_back(std::move(*span_iter));
+ ++span_iter;
+ } else {
+ merged_spans.push_back(std::move(*untranslatable_iter));
+ ++untranslatable_iter;
+ }
+ }
+
+ while (span_iter != sorted_spans.end()) {
+ merged_spans.push_back(std::move(*span_iter));
+ ++span_iter;
+ }
+
+ while (untranslatable_iter != sorted_untranslatable_sections.end()) {
+ merged_spans.push_back(std::move(*untranslatable_iter));
+ ++untranslatable_iter;
+ }
+ return merged_spans;
+}
+
+std::unique_ptr<StyledString> PseudolocalizeStyledString(StyledString* string,
+ Pseudolocalizer::Method method,
+ StringPool* pool) {
Pseudolocalizer localizer(method);
- const StringPiece original_text = *string->value->str;
+ // Collect the spans and untranslatable sections into one set of spans, sorted by first_char.
+ // This will effectively subdivide the string into multiple sections that can be individually
+ // pseudolocalized, while keeping the span indices synchronized.
+ std::vector<UnifiedSpan> merged_spans = MergeSpans(*string);
+
+ // All Span indices are UTF-16 based, according to the resources.arsc format expected by the
+ // runtime. So we will do all our processing in UTF-16, then convert back.
+ const std::u16string text16 = util::Utf8ToUtf16(*string->value->str);
+
+ // Convenient wrapper around the text that allows us to work with StringPieces.
+ const StringPiece16 text(text16);
+
+ // The new string.
+ std::string new_string = localizer.Start();
+
+ // The stack that keeps track of what nested Span we're in.
+ std::vector<size_t> span_stack;
+
+ // The current position in the original text.
+ uint32_t cursor = 0u;
+
+ // The current position in the new text.
+ uint32_t new_cursor = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(new_string.data()),
+ new_string.size(), false);
+
+ // We assume no nesting of untranslatable sections, since XLIFF doesn't allow it.
+ bool translatable = true;
+ size_t span_idx = 0u;
+ while (span_idx < merged_spans.size() || !span_stack.empty()) {
+ UnifiedSpan* span = span_idx >= merged_spans.size() ? nullptr : &merged_spans[span_idx];
+ UnifiedSpan* parent_span = span_stack.empty() ? nullptr : &merged_spans[span_stack.back()];
+
+ if (span != nullptr) {
+ if (parent_span == nullptr || parent_span->last_char > span->first_char) {
+ // There is no parent, or this span is the child of the parent.
+ // Pseudolocalize all the text until this span.
+ const StringPiece16 substr = text.substr(cursor, span->first_char - cursor);
+ cursor += substr.size();
+
+ // Pseudolocalize the substring.
+ std::string new_substr = util::Utf16ToUtf8(substr);
+ if (translatable) {
+ new_substr = localizer.Text(new_substr);
+ }
+ new_cursor += utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(new_substr.data()),
+ new_substr.size(), false);
+ new_string += new_substr;
+
+ // Rewrite the first_char.
+ span->first_char = new_cursor;
+ if (!span->tag) {
+ // An untranslatable section has begun!
+ translatable = false;
+ }
+ span_stack.push_back(span_idx);
+ ++span_idx;
+ continue;
+ }
+ }
+
+ if (parent_span != nullptr) {
+ // There is a parent, and either this span is not a child of it, or there are no more spans.
+ // Pop this off the stack.
+ const StringPiece16 substr = text.substr(cursor, parent_span->last_char - cursor + 1);
+ cursor += substr.size();
+
+ // Pseudolocalize the substring.
+ std::string new_substr = util::Utf16ToUtf8(substr);
+ if (translatable) {
+ new_substr = localizer.Text(new_substr);
+ }
+ new_cursor += utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(new_substr.data()),
+ new_substr.size(), false);
+ new_string += new_substr;
+
+ parent_span->last_char = new_cursor - 1;
+ if (parent_span->tag) {
+ // An end to an untranslatable section.
+ translatable = true;
+ }
+ span_stack.pop_back();
+ }
+ }
+
+ // Finish the pseudolocalization at the end of the string.
+ new_string += localizer.Text(util::Utf16ToUtf8(text.substr(cursor, text.size() - cursor)));
+ new_string += localizer.End();
StyleString localized;
+ localized.str = std::move(new_string);
- // Copy the spans. We will update their offsets when we localize.
- localized.spans.reserve(string->value->spans.size());
- for (const StringPool::Span& span : string->value->spans) {
- localized.spans.push_back(
- Span{*span.name, span.first_char, span.last_char});
- }
-
- // The ranges are all represented with a single value. This is the start of
- // one range and end of another.
- struct Range {
- size_t start;
-
- // If set to true, toggles the state of translatability.
- bool toggle_translatability;
-
- // Once the new string is localized, these are the pointers to the spans to adjust.
- // Since this struct represents the start of one range and end of another,
- // we have the two pointers respectively.
- uint32_t* update_start;
- uint32_t* update_end;
- };
-
- auto cmp = [](const Range& r, size_t index) -> bool {
- return r.start < index;
- };
-
- // Construct the ranges. The ranges are represented like so: [0, 2, 5, 7]
- // The ranges are the spaces in between. In this example, with a total string
- // length of 9, the vector represents: (0,1], (2,4], (5,6], (7,9]
- //
- std::vector<Range> ranges;
- ranges.push_back(Range{0, false, nullptr, nullptr});
- ranges.push_back(Range{original_text.size() - 1, false, nullptr, nullptr});
- for (size_t i = 0; i < string->value->spans.size(); i++) {
- const StringPool::Span& span = string->value->spans[i];
-
- // Insert or update the Range marker for the start of this span.
- auto iter =
- std::lower_bound(ranges.begin(), ranges.end(), span.first_char, cmp);
- if (iter != ranges.end() && iter->start == span.first_char) {
- iter->update_start = &localized.spans[i].first_char;
- } else {
- ranges.insert(iter, Range{span.first_char, false, &localized.spans[i].first_char, nullptr});
- }
-
- // Insert or update the Range marker for the end of this span.
- iter = std::lower_bound(ranges.begin(), ranges.end(), span.last_char, cmp);
- if (iter != ranges.end() && iter->start == span.last_char) {
- iter->update_end = &localized.spans[i].last_char;
- } else {
- ranges.insert(iter, Range{span.last_char, false, nullptr, &localized.spans[i].last_char});
+ // Convert the UnifiedSpans into regular Spans, skipping the UntranslatableSections.
+ for (UnifiedSpan& span : merged_spans) {
+ if (span.tag) {
+ localized.spans.push_back(Span{std::move(span.tag.value()), span.first_char, span.last_char});
}
}
-
- // Parts of the string may be untranslatable. Merge those ranges
- // in as well, so that we have continuous sections of text to
- // feed into the pseudolocalizer.
- // We do this by marking the beginning of a range as either toggling
- // the translatability state or not.
- for (const UntranslatableSection& section : string->untranslatable_sections) {
- auto iter = std::lower_bound(ranges.begin(), ranges.end(), section.start, cmp);
- if (iter != ranges.end() && iter->start == section.start) {
- // An existing span starts (or ends) here. We just need to mark that
- // the translatability should toggle here. If translatability was
- // already being toggled, then that means we have two adjacent ranges of untranslatable
- // text, so remove the toggle and only toggle at the end of this range,
- // effectively merging these ranges.
- iter->toggle_translatability = !iter->toggle_translatability;
- } else {
- // Insert a new range that specifies to toggle the translatability.
- iter = ranges.insert(iter, Range{section.start, true, nullptr, nullptr});
- }
-
- // Update/create an end to the untranslatable section.
- iter = std::lower_bound(iter, ranges.end(), section.end, cmp);
- if (iter != ranges.end() && iter->start == section.end) {
- iter->toggle_translatability = true;
- } else {
- iter = ranges.insert(iter, Range{section.end, true, nullptr, nullptr});
- }
- }
-
- localized.str += localizer.Start();
-
- // Iterate over the ranges and localize each section.
- // The text starts as translatable, and each time a range has toggle_translatability
- // set to true, we toggle whether to translate or not.
- // This assumes no untranslatable ranges overlap.
- bool translatable = true;
- for (size_t i = 0; i < ranges.size(); i++) {
- const size_t start = ranges[i].start;
- size_t len = original_text.size() - start;
- if (i + 1 < ranges.size()) {
- len = ranges[i + 1].start - start;
- }
-
- if (ranges[i].update_start) {
- *ranges[i].update_start = localized.str.size();
- }
-
- if (ranges[i].update_end) {
- *ranges[i].update_end = localized.str.size();
- }
-
- if (ranges[i].toggle_translatability) {
- translatable = !translatable;
- }
-
- if (translatable) {
- localized.str += localizer.Text(original_text.substr(start, len));
- } else {
- localized.str += original_text.substr(start, len);
- }
- }
-
- localized.str += localizer.End();
-
return util::make_unique<StyledString>(pool->MakeRef(localized));
}
@@ -175,8 +233,7 @@
if (sub_visitor.value) {
localized->values[i] = std::move(sub_visitor.item);
} else {
- localized->values[i] =
- std::unique_ptr<Item>(plural->values[i]->Clone(pool_));
+ localized->values[i] = std::unique_ptr<Item>(plural->values[i]->Clone(pool_));
}
}
}
@@ -210,8 +267,7 @@
}
result += localizer_.End();
- std::unique_ptr<String> localized =
- util::make_unique<String>(pool_->MakeRef(result));
+ std::unique_ptr<String> localized = util::make_unique<String>(pool_->MakeRef(result));
localized->SetSource(string->GetSource());
localized->SetWeak(true);
item = std::move(localized);
@@ -282,14 +338,10 @@
}
}
-/**
- * A value is pseudolocalizable if it does not define a locale (or is the
- * default locale)
- * and is translatable.
- */
+// A value is pseudolocalizable if it does not define a locale (or is the default locale) and is
+// translatable.
static bool IsPseudolocalizable(ResourceConfigValue* config_value) {
- const int diff =
- config_value->config.diff(ConfigDescription::DefaultConfig());
+ const int diff = config_value->config.diff(ConfigDescription::DefaultConfig());
if (diff & ConfigDescription::CONFIG_LOCALE) {
return false;
}
@@ -298,19 +350,16 @@
} // namespace
-bool PseudolocaleGenerator::Consume(IAaptContext* context,
- ResourceTable* table) {
+bool PseudolocaleGenerator::Consume(IAaptContext* context, ResourceTable* table) {
for (auto& package : table->packages) {
for (auto& type : package->types) {
for (auto& entry : type->entries) {
- std::vector<ResourceConfigValue*> values =
- entry->FindValuesIf(IsPseudolocalizable);
-
+ std::vector<ResourceConfigValue*> values = entry->FindValuesIf(IsPseudolocalizable);
for (ResourceConfigValue* value : values) {
- PseudolocalizeIfNeeded(Pseudolocalizer::Method::kAccent, value,
- &table->string_pool, entry.get());
- PseudolocalizeIfNeeded(Pseudolocalizer::Method::kBidi, value,
- &table->string_pool, entry.get());
+ PseudolocalizeIfNeeded(Pseudolocalizer::Method::kAccent, value, &table->string_pool,
+ entry.get());
+ PseudolocalizeIfNeeded(Pseudolocalizer::Method::kBidi, value, &table->string_pool,
+ entry.get());
}
}
}
diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
index 4db37db..b08e1da 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
@@ -25,7 +25,7 @@
StringPool pool;
StyleString original_style;
original_style.str = "Hello world!";
- original_style.spans = {Span{"b", 2, 3}, Span{"b", 6, 7}, Span{"i", 1, 10}};
+ original_style.spans = {Span{"i", 1, 10}, Span{"b", 2, 3}, Span{"b", 6, 7}};
std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
@@ -34,22 +34,19 @@
EXPECT_EQ(original_style.str, *new_string->value->str);
ASSERT_EQ(original_style.spans.size(), new_string->value->spans.size());
- EXPECT_EQ(std::string("He").size(), new_string->value->spans[0].first_char);
- EXPECT_EQ(std::string("Hel").size(), new_string->value->spans[0].last_char);
- EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
+ EXPECT_EQ(std::string("i"), *new_string->value->spans[0].name);
+ EXPECT_EQ(std::u16string(u"H").size(), new_string->value->spans[0].first_char);
+ EXPECT_EQ(std::u16string(u"Hello worl").size(), new_string->value->spans[0].last_char);
- EXPECT_EQ(std::string("Hello ").size(),
- new_string->value->spans[1].first_char);
- EXPECT_EQ(std::string("Hello w").size(),
- new_string->value->spans[1].last_char);
EXPECT_EQ(std::string("b"), *new_string->value->spans[1].name);
+ EXPECT_EQ(std::u16string(u"He").size(), new_string->value->spans[1].first_char);
+ EXPECT_EQ(std::u16string(u"Hel").size(), new_string->value->spans[1].last_char);
- EXPECT_EQ(std::string("H").size(), new_string->value->spans[2].first_char);
- EXPECT_EQ(std::string("Hello worl").size(),
- new_string->value->spans[2].last_char);
- EXPECT_EQ(std::string("i"), *new_string->value->spans[2].name);
+ EXPECT_EQ(std::string("b"), *new_string->value->spans[2].name);
+ EXPECT_EQ(std::u16string(u"Hello ").size(), new_string->value->spans[2].first_char);
+ EXPECT_EQ(std::u16string(u"Hello w").size(), new_string->value->spans[2].last_char);
- original_style.spans.push_back(Span{"em", 0, 11u});
+ original_style.spans.insert(original_style.spans.begin(), Span{"em", 0, 11u});
new_string = PseudolocalizeStyledString(
util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
@@ -58,23 +55,128 @@
EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļð¡ one two]"), *new_string->value->str);
ASSERT_EQ(original_style.spans.size(), new_string->value->spans.size());
- EXPECT_EQ(std::string("[Ĥé").size(), new_string->value->spans[0].first_char);
- EXPECT_EQ(std::string("[Ĥéļ").size(), new_string->value->spans[0].last_char);
+ EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[0].first_char);
+ EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵöŕļð").size(), new_string->value->spans[0].last_char);
- EXPECT_EQ(std::string("[Ĥéļļö ").size(),
+ EXPECT_EQ(std::u16string(u"[Ĥ").size(), new_string->value->spans[1].first_char);
+ EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵöŕļ").size(), new_string->value->spans[1].last_char);
+
+ EXPECT_EQ(std::u16string(u"[Ĥé").size(), new_string->value->spans[2].first_char);
+ EXPECT_EQ(std::u16string(u"[Ĥéļ").size(), new_string->value->spans[2].last_char);
+
+ EXPECT_EQ(std::u16string(u"[Ĥéļļö ").size(), new_string->value->spans[3].first_char);
+ EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵ").size(), new_string->value->spans[3].last_char);
+}
+
+TEST(PseudolocaleGeneratorTest, PseudolocalizeAdjacentNestedTags) {
+ StringPool pool;
+ StyleString original_style;
+ original_style.str = "bold";
+ original_style.spans = {Span{"b", 0, 3}, Span{"i", 0, 3}};
+
+ std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
+ util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
+ Pseudolocalizer::Method::kAccent, &pool);
+ ASSERT_NE(nullptr, new_string);
+ ASSERT_EQ(2u, new_string->value->spans.size());
+ EXPECT_EQ(std::string("[ɓöļð one]"), *new_string->value->str);
+
+ EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
+ EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[0].first_char);
+ EXPECT_EQ(std::u16string(u"[ɓöļ").size(), new_string->value->spans[0].last_char);
+
+ EXPECT_EQ(std::string("i"), *new_string->value->spans[1].name);
+ EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[1].first_char);
+ EXPECT_EQ(std::u16string(u"[ɓöļ").size(), new_string->value->spans[1].last_char);
+}
+
+TEST(PseudolocaleGeneratorTest, PseudolocalizeAdjacentTagsUnsorted) {
+ StringPool pool;
+ StyleString original_style;
+ original_style.str = "bold";
+ original_style.spans = {Span{"i", 2, 3}, Span{"b", 0, 1}};
+
+ std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
+ util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
+ Pseudolocalizer::Method::kAccent, &pool);
+ ASSERT_NE(nullptr, new_string);
+ ASSERT_EQ(2u, new_string->value->spans.size());
+ EXPECT_EQ(std::string("[ɓöļð one]"), *new_string->value->str);
+
+ EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
+ EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[0].first_char);
+ EXPECT_EQ(std::u16string(u"[ɓ").size(), new_string->value->spans[0].last_char);
+
+ EXPECT_EQ(std::string("i"), *new_string->value->spans[1].name);
+ EXPECT_EQ(std::u16string(u"[ɓö").size(), new_string->value->spans[1].first_char);
+ EXPECT_EQ(std::u16string(u"[ɓöļ").size(), new_string->value->spans[1].last_char);
+}
+
+TEST(PseudolocaleGeneratorTest, PseudolocalizeNestedAndAdjacentTags) {
+ StringPool pool;
+ StyleString original_style;
+ original_style.str = "This sentence is not what you think it is at all.";
+ original_style.spans = {Span{"b", 16u, 19u}, Span{"em", 29u, 47u}, Span{"i", 38u, 40u},
+ Span{"b", 44u, 47u}};
+
+ std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
+ util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
+ Pseudolocalizer::Method::kAccent, &pool);
+ ASSERT_NE(nullptr, new_string);
+ ASSERT_EQ(4u, new_string->value->spans.size());
+ EXPECT_EQ(std::string(
+ "[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ åļļ. one two three four five six]"),
+ *new_string->value->str);
+
+ EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš").size(), new_string->value->spans[0].first_char);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñö").size(), new_string->value->spans[0].last_char);
+
+ EXPECT_EQ(std::string("em"), *new_string->value->spans[1].name);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû").size(),
new_string->value->spans[1].first_char);
- EXPECT_EQ(std::string("[Ĥéļļö ŵ").size(),
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ åļ").size(),
new_string->value->spans[1].last_char);
- EXPECT_EQ(std::string("[Ĥ").size(), new_string->value->spans[2].first_char);
- EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļ").size(),
+ EXPECT_EQ(std::string("i"), *new_string->value->spans[2].name);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ").size(),
+ new_string->value->spans[2].first_char);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ î").size(),
new_string->value->spans[2].last_char);
- EXPECT_EQ(std::string("[").size(), new_string->value->spans[3].first_char);
- EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļð").size(),
+ EXPECT_EQ(std::string("b"), *new_string->value->spans[3].name);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ").size(),
+ new_string->value->spans[3].first_char);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ åļ").size(),
new_string->value->spans[3].last_char);
}
+TEST(PseudolocaleGeneratorTest, PseudolocalizePartsOfString) {
+ StringPool pool;
+ StyleString original_style;
+ original_style.str = "This should NOT be pseudolocalized.";
+ original_style.spans = {Span{"em", 4u, 14u}, Span{"i", 18u, 33u}};
+ std::unique_ptr<StyledString> original_string =
+ util::make_unique<StyledString>(pool.MakeRef(original_style));
+ original_string->untranslatable_sections = {UntranslatableSection{11u, 15u}};
+
+ std::unique_ptr<StyledString> new_string =
+ PseudolocalizeStyledString(original_string.get(), Pseudolocalizer::Method::kAccent, &pool);
+ ASSERT_NE(nullptr, new_string);
+ ASSERT_EQ(2u, new_string->value->spans.size());
+ EXPECT_EQ(std::string("[Ţĥîš šĥöûļð NOT ɓé þšéûðöļöçåļîžéð. one two three four]"),
+ *new_string->value->str);
+
+ EXPECT_EQ(std::string("em"), *new_string->value->spans[0].name);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš").size(), new_string->value->spans[0].first_char);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šĥöûļð NO").size(), new_string->value->spans[0].last_char);
+
+ EXPECT_EQ(std::string("i"), *new_string->value->spans[1].name);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šĥöûļð NOT ɓé").size(), new_string->value->spans[1].first_char);
+ EXPECT_EQ(std::u16string(u"[Ţĥîš šĥöûļð NOT ɓé þšéûðöļöçåļîžé").size(),
+ new_string->value->spans[1].last_char);
+}
+
TEST(PseudolocaleGeneratorTest, PseudolocalizeOnlyDefaultConfigs) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
@@ -138,7 +240,7 @@
{
StyleString original_style;
original_style.str = "Hello world!";
- original_style.spans = {Span{"b", 2, 3}, Span{"b", 6, 7}, Span{"i", 1, 10}};
+ original_style.spans = {Span{"i", 1, 10}, Span{"b", 2, 3}, Span{"b", 6, 7}};
auto styled_string =
util::make_unique<StyledString>(table->string_pool.MakeRef(original_style));
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 7f71589..a33fd06 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -1913,7 +1913,7 @@
std::vector<std::string> overlay_arg_list;
std::vector<std::string> extra_java_packages;
Maybe<std::string> package_id;
- Maybe<std::string> configs;
+ std::vector<std::string> configs;
Maybe<std::string> preferred_density;
Maybe<std::string> product_list;
bool legacy_x_flag = false;
@@ -1971,7 +1971,7 @@
&legacy_x_flag)
.OptionalSwitch("-z", "Require localization of strings marked 'suggested'",
&require_localization)
- .OptionalFlag("-c",
+ .OptionalFlagList("-c",
"Comma separated list of configurations to include. The default\n"
"is all configurations",
&configs)
@@ -2151,28 +2151,29 @@
}
AxisConfigFilter filter;
- if (configs) {
- for (const StringPiece& config_str : util::Tokenize(configs.value(), ',')) {
- ConfigDescription config;
- LocaleValue lv;
- if (lv.InitFromFilterString(config_str)) {
- lv.WriteTo(&config);
- } else if (!ConfigDescription::Parse(config_str, &config)) {
- context.GetDiagnostics()->Error(DiagMessage() << "invalid config '"
- << config_str
- << "' for -c option");
- return 1;
- }
+ if (configs.empty()) {
+ for (const std::string& config_arg : configs) {
+ for (const StringPiece& config_str : util::Tokenize(config_arg, ',')) {
+ ConfigDescription config;
+ LocaleValue lv;
+ if (lv.InitFromFilterString(config_str)) {
+ lv.WriteTo(&config);
+ } else if (!ConfigDescription::Parse(config_str, &config)) {
+ context.GetDiagnostics()->Error(DiagMessage() << "invalid config '"
+ << config_str
+ << "' for -c option");
+ return 1;
+ }
- if (config.density != 0) {
- context.GetDiagnostics()->Warn(DiagMessage() << "ignoring density '"
- << config
- << "' for -c option");
- } else {
- filter.AddConfig(config);
+ if (config.density != 0) {
+ context.GetDiagnostics()->Warn(DiagMessage() << "ignoring density '"
+ << config
+ << "' for -c option");
+ } else {
+ filter.AddConfig(config);
+ }
}
}
-
options.table_splitter_options.config_filter = &filter;
}