Merge "Initial implementation of autofill partitioning." into oc-dev
diff --git a/Android.mk b/Android.mk
index 634272b..e27aa30 100644
--- a/Android.mk
+++ b/Android.mk
@@ -320,6 +320,8 @@
core/java/android/service/wallpaper/IWallpaperService.aidl \
core/java/android/service/chooser/IChooserTargetService.aidl \
core/java/android/service/chooser/IChooserTargetResult.aidl \
+ core/java/android/service/resolver/IResolverRankerService.aidl \
+ core/java/android/service/resolver/IResolverRankerResult.aidl \
core/java/android/text/ITextClassificationService.aidl \
core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
@@ -367,7 +369,6 @@
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
core/java/com/android/internal/backup/IBackupTransport.aidl \
core/java/com/android/internal/backup/IObbBackupService.aidl \
- core/java/com/android/internal/font/IFontManager.aidl \
core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \
core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl \
@@ -729,6 +730,7 @@
frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \
frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
+ frameworks/base/core/java/android/service/resolver/ResolverTarget.aidl \
frameworks/base/core/java/android/speech/tts/Voice.aidl \
frameworks/base/core/java/android/app/usage/CacheQuotaHint.aidl \
frameworks/base/core/java/android/app/usage/ExternalStorageStats.aidl \
@@ -1461,8 +1463,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 5926e98..e640e30 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8889,7 +8889,6 @@
field public static final java.lang.String DOWNLOAD_SERVICE = "download";
field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
- field public static final java.lang.String FONT_SERVICE = "font";
field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
field public static final java.lang.String INPUT_SERVICE = "input";
@@ -13243,7 +13242,7 @@
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
- method public boolean setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -13777,8 +13776,8 @@
method public static android.graphics.Typeface.Builder obtain();
method public void recycle();
method public void reset();
- method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String);
- method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]);
+ method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
method public android.graphics.Typeface.Builder setItalic(int);
method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
@@ -14388,6 +14387,21 @@
field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
}
+ public final class FontVariationAxis implements android.os.Parcelable {
+ ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public int describeContents();
+ method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public float getStyleValue();
+ method public java.lang.String getTag();
+ method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
+ }
+
+ public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
+ ctor public FontVariationAxis.InvalidFormatException(java.lang.String);
+ }
+
}
package android.graphics.pdf {
@@ -24542,85 +24556,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";
}
@@ -24707,22 +24642,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;
@@ -24751,28 +24780,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
@@ -41052,65 +41175,6 @@
method public android.text.Editable newEditable(java.lang.CharSequence);
}
- public final class FontConfig implements android.os.Parcelable {
- ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]);
- method public int describeContents();
- method public android.text.FontConfig.Alias[] getAliases();
- method public android.text.FontConfig.Family[] getFamilies();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
- }
-
- public static final class FontConfig.Alias implements android.os.Parcelable {
- ctor public FontConfig.Alias(java.lang.String, java.lang.String, int);
- method public int describeContents();
- method public java.lang.String getName();
- method public java.lang.String getToName();
- method public int getWeight();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
- }
-
- public static final class FontConfig.Axis implements android.os.Parcelable {
- ctor public FontConfig.Axis(int, float);
- ctor public FontConfig.Axis(java.lang.String, float);
- method public int describeContents();
- method public float getStyleValue();
- method public int getTag();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR;
- }
-
- public static final class FontConfig.Family implements android.os.Parcelable {
- ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int);
- method public int describeContents();
- method public android.text.FontConfig.Font[] getFonts();
- method public java.lang.String getLanguage();
- method public java.lang.String getName();
- method public int getVariant();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR;
- field public static final int VARIANT_COMPACT = 1; // 0x1
- field public static final int VARIANT_DEFAULT = 0; // 0x0
- field public static final int VARIANT_ELEGANT = 2; // 0x2
- }
-
- public static final class FontConfig.Font implements android.os.Parcelable {
- method public int describeContents();
- method public android.text.FontConfig.Axis[] getAxes();
- method public java.lang.String getFontName();
- method public int getTtcIndex();
- method public android.net.Uri getUri();
- method public int getWeight();
- method public boolean isItalic();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
- }
-
- public final class FontManager {
- method public android.text.FontConfig getSystemFonts();
- }
-
public abstract interface GetChars implements java.lang.CharSequence {
method public abstract void getChars(int, int, char[], int);
}
@@ -41258,6 +41322,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 {
@@ -41459,7 +41525,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);
@@ -48663,7 +48729,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();
@@ -48712,7 +48778,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);
@@ -49003,12 +49069,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);
@@ -51269,7 +51335,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();
@@ -51364,7 +51430,7 @@
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
- method public boolean setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
@@ -51382,7 +51448,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-current.txt b/api/system-current.txt
index a5f10cd..383b332 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -53,6 +53,7 @@
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+ field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
@@ -9386,7 +9387,6 @@
field public static final java.lang.String DOWNLOAD_SERVICE = "download";
field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
- field public static final java.lang.String FONT_SERVICE = "font";
field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
@@ -13975,7 +13975,7 @@
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
- method public boolean setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -14509,8 +14509,8 @@
method public static android.graphics.Typeface.Builder obtain();
method public void recycle();
method public void reset();
- method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String);
- method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]);
+ method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
method public android.graphics.Typeface.Builder setItalic(int);
method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
@@ -15120,6 +15120,21 @@
field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
}
+ public final class FontVariationAxis implements android.os.Parcelable {
+ ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public int describeContents();
+ method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public float getStyleValue();
+ method public java.lang.String getTag();
+ method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
+ }
+
+ public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
+ ctor public FontVariationAxis.InvalidFormatException(java.lang.String);
+ }
+
}
package android.graphics.pdf {
@@ -26487,85 +26502,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";
}
@@ -26653,22 +26589,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;
@@ -26697,28 +26727,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
@@ -40465,6 +40589,36 @@
}
+package android.service.resolver {
+
+ public abstract class ResolverRankerService extends android.app.Service {
+ ctor public ResolverRankerService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public void onPredictSharingProbabilities(java.util.List<android.service.resolver.ResolverTarget>);
+ method public void onTrainRankingModel(java.util.List<android.service.resolver.ResolverTarget>, int);
+ field public static final java.lang.String BIND_PERMISSION = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.resolver.ResolverRankerService";
+ }
+
+ public final class ResolverTarget implements android.os.Parcelable {
+ ctor public ResolverTarget();
+ method public int describeContents();
+ method public float getChooserScore();
+ method public float getLaunchScore();
+ method public float getRecencyScore();
+ method public float getSelectProbability();
+ method public float getTimeSpentScore();
+ method public void setChooserScore(float);
+ method public void setLaunchScore(float);
+ method public void setRecencyScore(float);
+ method public void setSelectProbability(float);
+ method public void setTimeSpentScore(float);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.resolver.ResolverTarget> CREATOR;
+ }
+
+}
+
package android.service.restrictions {
public abstract class RestrictionsReceiver extends android.content.BroadcastReceiver {
@@ -44514,65 +44668,6 @@
method public android.text.Editable newEditable(java.lang.CharSequence);
}
- public final class FontConfig implements android.os.Parcelable {
- ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]);
- method public int describeContents();
- method public android.text.FontConfig.Alias[] getAliases();
- method public android.text.FontConfig.Family[] getFamilies();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
- }
-
- public static final class FontConfig.Alias implements android.os.Parcelable {
- ctor public FontConfig.Alias(java.lang.String, java.lang.String, int);
- method public int describeContents();
- method public java.lang.String getName();
- method public java.lang.String getToName();
- method public int getWeight();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
- }
-
- public static final class FontConfig.Axis implements android.os.Parcelable {
- ctor public FontConfig.Axis(int, float);
- ctor public FontConfig.Axis(java.lang.String, float);
- method public int describeContents();
- method public float getStyleValue();
- method public int getTag();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR;
- }
-
- public static final class FontConfig.Family implements android.os.Parcelable {
- ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int);
- method public int describeContents();
- method public android.text.FontConfig.Font[] getFonts();
- method public java.lang.String getLanguage();
- method public java.lang.String getName();
- method public int getVariant();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR;
- field public static final int VARIANT_COMPACT = 1; // 0x1
- field public static final int VARIANT_DEFAULT = 0; // 0x0
- field public static final int VARIANT_ELEGANT = 2; // 0x2
- }
-
- public static final class FontConfig.Font implements android.os.Parcelable {
- method public int describeContents();
- method public android.text.FontConfig.Axis[] getAxes();
- method public java.lang.String getFontName();
- method public int getTtcIndex();
- method public android.net.Uri getUri();
- method public int getWeight();
- method public boolean isItalic();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
- }
-
- public final class FontManager {
- method public android.text.FontConfig getSystemFonts();
- }
-
public abstract interface GetChars implements java.lang.CharSequence {
method public abstract void getChars(int, int, char[], int);
}
@@ -44720,6 +44815,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 {
@@ -44921,7 +45018,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);
@@ -52211,7 +52308,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();
@@ -52266,7 +52363,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);
@@ -52594,12 +52691,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);
@@ -55099,7 +55196,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();
@@ -55194,7 +55291,7 @@
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
- method public boolean setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
@@ -55212,7 +55309,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-current.txt b/api/test-current.txt
index 1b5eeed..795342f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -8921,7 +8921,6 @@
field public static final java.lang.String DOWNLOAD_SERVICE = "download";
field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
- field public static final java.lang.String FONT_SERVICE = "font";
field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
field public static final java.lang.String INPUT_SERVICE = "input";
@@ -13293,7 +13292,7 @@
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
- method public boolean setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -13827,8 +13826,8 @@
method public static android.graphics.Typeface.Builder obtain();
method public void recycle();
method public void reset();
- method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String);
- method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]);
+ method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
method public android.graphics.Typeface.Builder setItalic(int);
method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
@@ -14439,6 +14438,21 @@
field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
}
+ public final class FontVariationAxis implements android.os.Parcelable {
+ ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public int describeContents();
+ method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+ method public float getStyleValue();
+ method public java.lang.String getTag();
+ method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
+ }
+
+ public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
+ ctor public FontVariationAxis.InvalidFormatException(java.lang.String);
+ }
+
}
package android.graphics.pdf {
@@ -24655,85 +24669,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";
}
@@ -24820,22 +24755,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;
@@ -24864,28 +24893,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
@@ -41260,65 +41383,6 @@
method public android.text.Editable newEditable(java.lang.CharSequence);
}
- public final class FontConfig implements android.os.Parcelable {
- ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]);
- method public int describeContents();
- method public android.text.FontConfig.Alias[] getAliases();
- method public android.text.FontConfig.Family[] getFamilies();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
- }
-
- public static final class FontConfig.Alias implements android.os.Parcelable {
- ctor public FontConfig.Alias(java.lang.String, java.lang.String, int);
- method public int describeContents();
- method public java.lang.String getName();
- method public java.lang.String getToName();
- method public int getWeight();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
- }
-
- public static final class FontConfig.Axis implements android.os.Parcelable {
- ctor public FontConfig.Axis(int, float);
- ctor public FontConfig.Axis(java.lang.String, float);
- method public int describeContents();
- method public float getStyleValue();
- method public int getTag();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR;
- }
-
- public static final class FontConfig.Family implements android.os.Parcelable {
- ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int);
- method public int describeContents();
- method public android.text.FontConfig.Font[] getFonts();
- method public java.lang.String getLanguage();
- method public java.lang.String getName();
- method public int getVariant();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR;
- field public static final int VARIANT_COMPACT = 1; // 0x1
- field public static final int VARIANT_DEFAULT = 0; // 0x0
- field public static final int VARIANT_ELEGANT = 2; // 0x2
- }
-
- public static final class FontConfig.Font implements android.os.Parcelable {
- method public int describeContents();
- method public android.text.FontConfig.Axis[] getAxes();
- method public java.lang.String getFontName();
- method public int getTtcIndex();
- method public android.net.Uri getUri();
- method public int getWeight();
- method public boolean isItalic();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
- }
-
- public final class FontManager {
- method public android.text.FontConfig getSystemFonts();
- }
-
public abstract interface GetChars implements java.lang.CharSequence {
method public abstract void getChars(int, int, char[], int);
}
@@ -41466,6 +41530,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 {
@@ -41667,7 +41733,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);
@@ -49047,7 +49113,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();
@@ -49096,7 +49162,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);
@@ -49387,12 +49453,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);
@@ -51660,7 +51726,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();
@@ -51755,7 +51821,7 @@
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
- method public boolean setFontVariationSettings(java.lang.String);
+ method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
@@ -51773,7 +51839,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/compiled-classes-phone b/compiled-classes-phone
index ea8f4a4..1a19b2c 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -4061,7 +4061,6 @@
android.text.FontConfig$Family$1
android.text.FontConfig$Font
android.text.FontConfig$Font$1
-android.text.FontManager
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
@@ -5501,8 +5500,6 @@
com.android.internal.content.PackageMonitor
com.android.internal.content.ReferrerIntent
com.android.internal.content.ReferrerIntent$1
-com.android.internal.font.IFontManager
-com.android.internal.font.IFontManager$Stub
com.android.internal.graphics.drawable.AnimationScaleListDrawable
com.android.internal.graphics.drawable.AnimationScaleListDrawable$AnimationScaleListState
com.android.internal.hardware.AmbientDisplayConfiguration
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dbf81f9..d432160 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4159,14 +4159,25 @@
mTaskDescription.setPrimaryColor(colorPrimary);
}
}
- // For dev-preview only.
- if (mTaskDescription.getBackgroundColor() == 0) {
- int colorBackground = a.getColor(
- com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
- if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
- mTaskDescription.setBackgroundColor(colorBackground);
- }
+
+ int colorBackground = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
+ if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
+ mTaskDescription.setBackgroundColor(colorBackground);
}
+
+ final int statusBarColor = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0);
+ if (statusBarColor != 0) {
+ mTaskDescription.setStatusBarColor(statusBarColor);
+ }
+
+ final int navigationBarColor = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_navigationBarColor, 0);
+ if (navigationBarColor != 0) {
+ mTaskDescription.setNavigationBarColor(navigationBarColor);
+ }
+
a.recycle();
setTaskDescription(mTaskDescription);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4004bd6..aede1bb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1145,6 +1145,8 @@
private String mIconFilename;
private int mColorPrimary;
private int mColorBackground;
+ private int mStatusBarColor;
+ private int mNavigationBarColor;
/**
* Creates the TaskDescription to the specified values.
@@ -1155,7 +1157,7 @@
* opaque.
*/
public TaskDescription(String label, Bitmap icon, int colorPrimary) {
- this(label, icon, null, colorPrimary, 0);
+ this(label, icon, null, colorPrimary, 0, 0, 0);
if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
@@ -1168,7 +1170,7 @@
* @param icon An icon that represents the current state of this activity.
*/
public TaskDescription(String label, Bitmap icon) {
- this(label, icon, null, 0, 0);
+ this(label, icon, null, 0, 0, 0, 0);
}
/**
@@ -1177,24 +1179,26 @@
* @param label A label and description of the current state of this activity.
*/
public TaskDescription(String label) {
- this(label, null, null, 0, 0);
+ this(label, null, null, 0, 0, 0, 0);
}
/**
* Creates an empty TaskDescription.
*/
public TaskDescription() {
- this(null, null, null, 0, 0);
+ this(null, null, null, 0, 0, 0, 0);
}
/** @hide */
public TaskDescription(String label, Bitmap icon, String iconFilename, int colorPrimary,
- int colorBackground) {
+ int colorBackground, int statusBarColor, int navigationBarColor) {
mLabel = label;
mIcon = icon;
mIconFilename = iconFilename;
mColorPrimary = colorPrimary;
mColorBackground = colorBackground;
+ mStatusBarColor = statusBarColor;
+ mNavigationBarColor = navigationBarColor;
}
/**
@@ -1214,6 +1218,8 @@
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
mColorBackground = other.mColorBackground;
+ mStatusBarColor = other.mStatusBarColor;
+ mNavigationBarColor = other.mNavigationBarColor;
}
private TaskDescription(Parcel source) {
@@ -1253,6 +1259,20 @@
}
/**
+ * @hide
+ */
+ public void setStatusBarColor(int statusBarColor) {
+ mStatusBarColor = statusBarColor;
+ }
+
+ /**
+ * @hide
+ */
+ public void setNavigationBarColor(int navigationBarColor) {
+ mNavigationBarColor = navigationBarColor;
+ }
+
+ /**
* Sets the icon for this task description.
* @hide
*/
@@ -1325,6 +1345,20 @@
return mColorBackground;
}
+ /**
+ * @hide
+ */
+ public int getStatusBarColor() {
+ return mStatusBarColor;
+ }
+
+ /**
+ * @hide
+ */
+ public int getNavigationBarColor() {
+ return mNavigationBarColor;
+ }
+
/** @hide */
public void saveToXml(XmlSerializer out) throws IOException {
if (mLabel != null) {
@@ -1377,6 +1411,8 @@
}
dest.writeInt(mColorPrimary);
dest.writeInt(mColorBackground);
+ dest.writeInt(mStatusBarColor);
+ dest.writeInt(mNavigationBarColor);
if (mIconFilename == null) {
dest.writeInt(0);
} else {
@@ -1390,6 +1426,8 @@
mIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
mColorPrimary = source.readInt();
mColorBackground = source.readInt();
+ mStatusBarColor = source.readInt();
+ mNavigationBarColor = source.readInt();
mIconFilename = source.readInt() > 0 ? source.readString() : null;
}
@@ -1407,7 +1445,9 @@
public String toString() {
return "TaskDescription Label: " + mLabel + " Icon: " + mIcon +
" IconFilename: " + mIconFilename + " colorPrimary: " + mColorPrimary +
- " colorBackground: " + mColorBackground;
+ " colorBackground: " + mColorBackground +
+ " statusBarColor: " + mColorBackground +
+ " navigationBarColor: " + mNavigationBarColor;
}
}
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/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f719749..6b05bdf 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -125,7 +125,6 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.text.FontManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -141,7 +140,6 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.ISoundTriggerService;
import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.font.IFontManager;
import com.android.internal.os.IDropBoxManagerService;
import com.android.internal.policy.PhoneLayoutInflater;
@@ -820,14 +818,6 @@
return new IncidentManager(ctx);
}});
- registerService(Context.FONT_SERVICE, FontManager.class,
- new CachedServiceFetcher<FontManager>() {
- @Override
- public FontManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE);
- return new FontManager(IFontManager.Stub.asInterface(b));
- }});
registerService(Context.AUTOFILL_MANAGER_SERVICE, AutofillManager.class,
new CachedServiceFetcher<AutofillManager>() {
@Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index be267b3..368c7b8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3870,11 +3870,6 @@
public static final String DEVICE_IDENTIFIERS_SERVICE = "device_identifiers";
/**
- * Service that provides System font data.
- */
- public static final String FONT_SERVICE = "font";
-
- /**
* Service to report a system health "incident"
* @hide
*/
diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/core/java/android/service/resolver/IResolverRankerResult.aidl
similarity index 77%
copy from core/java/com/android/internal/font/IFontManager.aidl
copy to core/java/android/service/resolver/IResolverRankerResult.aidl
index 52a6262..bda3154 100644
--- a/core/java/com/android/internal/font/IFontManager.aidl
+++ b/core/java/android/service/resolver/IResolverRankerResult.aidl
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.internal.font;
+package android.service.resolver;
-import android.text.FontConfig;
+import android.service.resolver.ResolverTarget;
/**
- * Interface to the font manager.
* @hide
*/
-interface IFontManager {
- FontConfig getSystemFonts();
-}
+oneway interface IResolverRankerResult
+{
+ void sendResult(in List<ResolverTarget> results);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/core/java/android/service/resolver/IResolverRankerService.aidl
similarity index 65%
copy from core/java/com/android/internal/font/IFontManager.aidl
copy to core/java/android/service/resolver/IResolverRankerService.aidl
index 52a6262..f0d747d 100644
--- a/core/java/com/android/internal/font/IFontManager.aidl
+++ b/core/java/android/service/resolver/IResolverRankerService.aidl
@@ -14,14 +14,16 @@
* limitations under the License.
*/
-package com.android.internal.font;
+package android.service.resolver;
-import android.text.FontConfig;
+import android.service.resolver.IResolverRankerResult;
+import android.service.resolver.ResolverTarget;
/**
- * Interface to the font manager.
* @hide
*/
-interface IFontManager {
- FontConfig getSystemFonts();
-}
+oneway interface IResolverRankerService
+{
+ void predict(in List<ResolverTarget> targets, IResolverRankerResult result);
+ void train(in List<ResolverTarget> targets, int selectedPosition);
+}
\ No newline at end of file
diff --git a/core/java/android/service/resolver/ResolverRankerService.java b/core/java/android/service/resolver/ResolverRankerService.java
new file mode 100644
index 0000000..0506747
--- /dev/null
+++ b/core/java/android/service/resolver/ResolverRankerService.java
@@ -0,0 +1,187 @@
+/*
+ * 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.service.resolver;
+
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.RemoteException;
+import android.service.resolver.ResolverTarget;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A service to rank apps according to usage stats of apps, when the system is resolving targets for
+ * an Intent.
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with the
+ * {@link android.Manifest.permission#BIND_RESOLVER_RANKER_SERVICE} permission, and include an
+ * intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * <service android:name=".MyResolverRankerService"
+ * android:exported="true"
+ * android:priority="100"
+ * android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.resolver.ResolverRankerService" />
+ * </intent-filter>
+ * </service>
+ * </pre>
+ * @hide
+ */
+@SystemApi
+public abstract class ResolverRankerService extends Service {
+
+ private static final String TAG = "ResolverRankerService";
+
+ private static final boolean DEBUG = false;
+
+ /**
+ * The Intent action that a service must respond to. Add it to the intent filter of the service
+ * in its manifest.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE = "android.service.resolver.ResolverRankerService";
+
+ /**
+ * The permission that a service must require to ensure that only Android system can bind to it.
+ * If this permission is not enforced in the AndroidManifest of the service, the system will
+ * skip that service.
+ */
+ public static final String BIND_PERMISSION = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
+
+ private ResolverRankerServiceWrapper mWrapper = null;
+
+ /**
+ * Called by the system to retrieve a list of probabilities to rank apps/options. To implement
+ * it, set selectProbability of each input {@link ResolverTarget}. The higher the
+ * selectProbability is, the more likely the {@link ResolverTarget} will be selected by the
+ * user. Override this function to provide prediction results.
+ *
+ * @param targets a list of {@link ResolverTarget}, for the list of apps to be ranked.
+ *
+ * @throws Exception when the prediction task fails.
+ */
+ public void onPredictSharingProbabilities(final List<ResolverTarget> targets) {}
+
+ /**
+ * Called by the system to train/update a ranking service, after the user makes a selection from
+ * the ranked list of apps. Override this function to enable model updates.
+ *
+ * @param targets a list of {@link ResolverTarget}, for the list of apps to be ranked.
+ * @param selectedPosition the position of the selected app in the list.
+ *
+ * @throws Exception when the training task fails.
+ */
+ public void onTrainRankingModel(
+ final List<ResolverTarget> targets, final int selectedPosition) {}
+
+ private static final String HANDLER_THREAD_NAME = "RESOLVER_RANKER_SERVICE";
+ private volatile Handler mHandler;
+ private HandlerThread mHandlerThread;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (DEBUG) Log.d(TAG, "onBind " + intent);
+ if (!SERVICE_INTERFACE.equals(intent.getAction())) {
+ if (DEBUG) Log.d(TAG, "bad intent action " + intent.getAction() + "; returning null");
+ return null;
+ }
+ if (mHandlerThread == null) {
+ mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME);
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ }
+ if (mWrapper == null) {
+ mWrapper = new ResolverRankerServiceWrapper();
+ }
+ return mWrapper;
+ }
+
+ @Override
+ public void onDestroy() {
+ mHandler = null;
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ }
+ super.onDestroy();
+ }
+
+ private static void sendResult(List<ResolverTarget> targets, IResolverRankerResult result) {
+ try {
+ result.sendResult(targets);
+ } catch (Exception e) {
+ Log.e(TAG, "failed to send results: " + e);
+ }
+ }
+
+ private class ResolverRankerServiceWrapper extends IResolverRankerService.Stub {
+
+ @Override
+ public void predict(final List<ResolverTarget> targets, final IResolverRankerResult result)
+ throws RemoteException {
+ Runnable predictRunnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "predict calls onPredictSharingProbabilities.");
+ }
+ onPredictSharingProbabilities(targets);
+ sendResult(targets, result);
+ } catch (Exception e) {
+ Log.e(TAG, "onPredictSharingProbabilities failed; send null results: " + e);
+ sendResult(null, result);
+ }
+ }
+ };
+ final Handler h = mHandler;
+ if (h != null) {
+ h.post(predictRunnable);
+ }
+ }
+
+ @Override
+ public void train(final List<ResolverTarget> targets, final int selectedPosition)
+ throws RemoteException {
+ Runnable trainRunnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "train calls onTranRankingModel");
+ }
+ onTrainRankingModel(targets, selectedPosition);
+ } catch (Exception e) {
+ Log.e(TAG, "onTrainRankingModel failed; skip train: " + e);
+ }
+ }
+ };
+ final Handler h = mHandler;
+ if (h != null) {
+ h.post(trainRunnable);
+ }
+ }
+ }
+}
diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/core/java/android/service/resolver/ResolverTarget.aidl
similarity index 79%
rename from core/java/com/android/internal/font/IFontManager.aidl
rename to core/java/android/service/resolver/ResolverTarget.aidl
index 52a6262..6cab2d4 100644
--- a/core/java/com/android/internal/font/IFontManager.aidl
+++ b/core/java/android/service/resolver/ResolverTarget.aidl
@@ -14,14 +14,9 @@
* limitations under the License.
*/
-package com.android.internal.font;
-
-import android.text.FontConfig;
+package android.service.resolver;
/**
- * Interface to the font manager.
* @hide
*/
-interface IFontManager {
- FontConfig getSystemFonts();
-}
+parcelable ResolverTarget;
diff --git a/core/java/android/service/resolver/ResolverTarget.java b/core/java/android/service/resolver/ResolverTarget.java
new file mode 100644
index 0000000..fb3e2d7
--- /dev/null
+++ b/core/java/android/service/resolver/ResolverTarget.java
@@ -0,0 +1,216 @@
+/*
+ * 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.service.resolver;
+
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * A ResolverTarget contains features by which an app or option will be ranked, in
+ * {@link ResolverRankerService}.
+ * @hide
+ */
+@SystemApi
+public final class ResolverTarget implements Parcelable {
+ private static final String TAG = "ResolverTarget";
+
+ /**
+ * a float score for recency of last use.
+ */
+ private float mRecencyScore;
+
+ /**
+ * a float score for total time spent.
+ */
+ private float mTimeSpentScore;
+
+ /**
+ * a float score for number of launches.
+ */
+ private float mLaunchScore;
+
+ /**
+ * a float score for number of selected.
+ */
+ private float mChooserScore;
+
+ /**
+ * a float score for the probability to be selected.
+ */
+ private float mSelectProbability;
+
+ // constructor for the class.
+ public ResolverTarget() {}
+
+ ResolverTarget(Parcel in) {
+ mRecencyScore = in.readFloat();
+ mTimeSpentScore = in.readFloat();
+ mLaunchScore = in.readFloat();
+ mChooserScore = in.readFloat();
+ mSelectProbability = in.readFloat();
+ }
+
+ /**
+ * Gets the score for how recently the target was used in the foreground.
+ *
+ * @return a float score whose range is [0, 1]. The higher the score is, the more recently the
+ * target was used.
+ */
+ public float getRecencyScore() {
+ return mRecencyScore;
+ }
+
+ /**
+ * Sets the score for how recently the target was used in the foreground.
+ *
+ * @param recencyScore a float score whose range is [0, 1]. The higher the score is, the more
+ * recently the target was used.
+ */
+ public void setRecencyScore(float recencyScore) {
+ this.mRecencyScore = recencyScore;
+ }
+
+ /**
+ * Gets the score for how long the target has been used in the foreground.
+ *
+ * @return a float score whose range is [0, 1]. The higher the score is, the longer the target
+ * has been used for.
+ */
+ public float getTimeSpentScore() {
+ return mTimeSpentScore;
+ }
+
+ /**
+ * Sets the score for how long the target has been used in the foreground.
+ *
+ * @param timeSpentScore a float score whose range is [0, 1]. The higher the score is, the
+ * longer the target has been used for.
+ */
+ public void setTimeSpentScore(float timeSpentScore) {
+ this.mTimeSpentScore = timeSpentScore;
+ }
+
+ /**
+ * Gets the score for how many times the target has been launched to the foreground.
+ *
+ * @return a float score whose range is [0, 1]. The higher the score is, the more times the
+ * target has been launched.
+ */
+ public float getLaunchScore() {
+ return mLaunchScore;
+ }
+
+ /**
+ * Sets the score for how many times the target has been launched to the foreground.
+ *
+ * @param launchScore a float score whose range is [0, 1]. The higher the score is, the more
+ * times the target has been launched.
+ */
+ public void setLaunchScore(float launchScore) {
+ this.mLaunchScore = launchScore;
+ }
+
+ /**
+ * Gets the score for how many times the target has been selected by the user to share the same
+ * types of content.
+ *
+ * @return a float score whose range is [0, 1]. The higher the score is, the
+ * more times the target has been selected by the user to share the same types of content for.
+ */
+ public float getChooserScore() {
+ return mChooserScore;
+ }
+
+ /**
+ * Sets the score for how many times the target has been selected by the user to share the same
+ * types of content.
+ *
+ * @param chooserScore a float score whose range is [0, 1]. The higher the score is, the more
+ * times the target has been selected by the user to share the same types
+ * of content for.
+ */
+ public void setChooserScore(float chooserScore) {
+ this.mChooserScore = chooserScore;
+ }
+
+ /**
+ * Gets the probability of how likely this target will be selected by the user.
+ *
+ * @return a float score whose range is [0, 1]. The higher the score is, the more likely the
+ * user is going to select this target.
+ */
+ public float getSelectProbability() {
+ return mSelectProbability;
+ }
+
+ /**
+ * Sets the probability for how like this target will be selected by the user.
+ *
+ * @param selectProbability a float score whose range is [0, 1]. The higher the score is, the
+ * more likely tht user is going to select this target.
+ */
+ public void setSelectProbability(float selectProbability) {
+ this.mSelectProbability = selectProbability;
+ }
+
+ // serialize the class to a string.
+ @Override
+ public String toString() {
+ return "ResolverTarget{"
+ + mRecencyScore + ", "
+ + mTimeSpentScore + ", "
+ + mLaunchScore + ", "
+ + mChooserScore + ", "
+ + mSelectProbability + "}";
+ }
+
+ // describes the kinds of special objects contained in this Parcelable instance's marshaled
+ // representation.
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ // flattens this object in to a Parcel.
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeFloat(mRecencyScore);
+ dest.writeFloat(mTimeSpentScore);
+ dest.writeFloat(mLaunchScore);
+ dest.writeFloat(mChooserScore);
+ dest.writeFloat(mSelectProbability);
+ }
+
+ // creator definition for the class.
+ public static final Creator<ResolverTarget> CREATOR
+ = new Creator<ResolverTarget>() {
+ @Override
+ public ResolverTarget createFromParcel(Parcel source) {
+ return new ResolverTarget(source);
+ }
+
+ @Override
+ public ResolverTarget[] newArray(int size) {
+ return new ResolverTarget[size];
+ }
+ };
+}
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/FontConfig.java b/core/java/android/text/FontConfig.java
index 14d3ad7..8537d8f 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -21,7 +21,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.graphics.FontListParser;
+import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,6 +31,7 @@
/**
* Font configuration descriptions for System fonts.
+ * @hide
*/
public final class FontConfig implements Parcelable {
private final @NonNull Family[] mFamilies;
@@ -84,78 +85,12 @@
};
/**
- * Class that holds information about a Font axis.
- */
- public static final class Axis implements Parcelable {
- private final int mTag;
- private final float mStyleValue;
-
- public Axis(int tag, float styleValue) {
- mTag = tag;
- mStyleValue = styleValue;
- }
-
- public Axis(@NonNull String tagString, float styleValue) {
- if (!FontListParser.isValidTag(tagString)) {
- throw new IllegalArgumentException("Invalid tag pattern: " + tagString);
- }
- mTag = FontListParser.makeTag(tagString);
- mStyleValue = styleValue;
- }
-
- /**
- * Returns the variable font axis tag associated to this axis.
- */
- public int getTag() {
- return mTag;
- }
-
- /**
- * Returns the style value associated to the given axis for this font.
- */
- public float getStyleValue() {
- return mStyleValue;
- }
-
- /**
- * @hide
- */
- public Axis(Parcel in) {
- mTag = in.readInt();
- mStyleValue = in.readFloat();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flag) {
- out.writeInt(mTag);
- out.writeFloat(mStyleValue);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<Axis> CREATOR = new Creator<Axis>() {
- @Override
- public Axis createFromParcel(Parcel in) {
- return new Axis(in);
- }
-
- @Override
- public Axis[] newArray(int size) {
- return new Axis[size];
- }
- };
- }
-
- /**
* Class that holds information about a Font.
*/
public static final class Font implements Parcelable {
private final @NonNull String mFontName;
private final int mTtcIndex;
- private final @NonNull Axis[] mAxes;
+ private final @NonNull FontVariationAxis[] mAxes;
private final int mWeight;
private final boolean mIsItalic;
private Uri mUri;
@@ -163,8 +98,8 @@
/**
* @hide
*/
- public Font(@NonNull String fontName, int ttcIndex, @NonNull Axis[] axes, int weight,
- boolean isItalic) {
+ public Font(@NonNull String fontName, int ttcIndex, @NonNull FontVariationAxis[] axes,
+ int weight, boolean isItalic) {
mFontName = fontName;
mTtcIndex = ttcIndex;
mAxes = axes;
@@ -189,7 +124,7 @@
/**
* Returns the list of axes associated to this font.
*/
- public @NonNull Axis[] getAxes() {
+ public @NonNull FontVariationAxis[] getAxes() {
return mAxes;
}
@@ -230,7 +165,7 @@
public Font(Parcel in) {
mFontName = in.readString();
mTtcIndex = in.readInt();
- mAxes = in.createTypedArray(Axis.CREATOR);
+ mAxes = in.createTypedArray(FontVariationAxis.CREATOR);
mWeight = in.readInt();
mIsItalic = in.readInt() == 1;
mUri = in.readTypedObject(Uri.CREATOR);
diff --git a/core/java/android/text/FontManager.java b/core/java/android/text/FontManager.java
deleted file mode 100644
index b61cbf3..0000000
--- a/core/java/android/text/FontManager.java
+++ /dev/null
@@ -1,49 +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.text;
-
-import android.os.RemoteException;
-
-import com.android.internal.font.IFontManager;
-
-/**
- * Interact with the Font service.
- */
-public final class FontManager {
- private static final String TAG = "FontManager";
-
- private final IFontManager mService;
-
- /**
- * @hide
- */
- public FontManager(IFontManager service) {
- mService = service;
- }
-
- /**
- * Retrieve the system fonts data. This loads the fonts.xml data if needed and loads all system
- * fonts in to memory, providing file descriptors for them.
- */
- public FontConfig getSystemFonts() {
- try {
- return mService.getSystemFonts();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-}
diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/core/java/android/text/FontVariationAxis.aidl
similarity index 64%
copy from core/java/com/android/internal/font/IFontManager.aidl
copy to core/java/android/text/FontVariationAxis.aidl
index 52a6262..d5d52c2 100644
--- a/core/java/com/android/internal/font/IFontManager.aidl
+++ b/core/java/android/text/FontVariationAxis.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2017 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.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,14 +14,6 @@
* limitations under the License.
*/
-package com.android.internal.font;
+package android.text;
-import android.text.FontConfig;
-
-/**
- * Interface to the font manager.
- * @hide
- */
-interface IFontManager {
- FontConfig getSystemFonts();
-}
+parcelable FontVariationAxis;
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/Choreographer.java b/core/java/android/view/Choreographer.java
index 3316f3a..aac5baa 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -529,6 +529,18 @@
}
}
+ /**
+ * Like {@link #getLastFrameTimeNanos}, but always returns the last frame time, not matter
+ * whether callbacks are currently running.
+ * @return The frame start time of the last frame, in the {@link System#nanoTime()} time base.
+ * @hide
+ */
+ public long getLastFrameTimeNanos() {
+ synchronized (mLock) {
+ return USE_FRAME_TIME ? mLastFrameTimeNanos : System.nanoTime();
+ }
+ }
+
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
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..0221040 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();
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/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/TextView.java b/core/java/android/widget/TextView.java
index 6f8df36..1b60ebc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -56,6 +56,7 @@
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
+import android.graphics.fonts.FontVariationAxis;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.LocaleList;
@@ -609,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;
@@ -820,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();
@@ -3737,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();
@@ -3753,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;
}
/**
@@ -3808,10 +3810,14 @@
* TextView. This function also returns true for empty settings string. Otherwise
* returns false.
*
+ * @throws FontVariationAxis.InvalidFormatException
+ * If given string is not a valid font variation settings format.
+ *
* @see #getFontVariationSettings()
* @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
*/
- public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
+ public boolean setFontVariationSettings(@Nullable String fontVariationSettings)
+ throws FontVariationAxis.InvalidFormatException {
final String existingSettings = mTextPaint.getFontVariationSettings();
if (fontVariationSettings == existingSettings
|| (fontVariationSettings != null
@@ -7678,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)
@@ -7720,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) {
@@ -7770,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)
@@ -8110,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/app/LRResolverRankerService.java b/core/java/com/android/internal/app/LRResolverRankerService.java
new file mode 100644
index 0000000..1cad7c7
--- /dev/null
+++ b/core/java/com/android/internal/app/LRResolverRankerService.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.storage.StorageManager;
+import android.service.resolver.ResolverRankerService;
+import android.service.resolver.ResolverTarget;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A Logistic Regression based {@link android.service.resolver.ResolverRankerService}, to be used
+ * in {@link ResolverComparator}.
+ */
+public final class LRResolverRankerService extends ResolverRankerService {
+ private static final String TAG = "LRResolverRankerService";
+
+ private static final boolean DEBUG = false;
+
+ private static final String PARAM_SHARED_PREF_NAME = "resolver_ranker_params";
+ private static final String BIAS_PREF_KEY = "bias";
+ private static final String VERSION_PREF_KEY = "version";
+
+ private static final String LAUNCH_SCORE = "launch";
+ private static final String TIME_SPENT_SCORE = "timeSpent";
+ private static final String RECENCY_SCORE = "recency";
+ private static final String CHOOSER_SCORE = "chooser";
+
+ // parameters for a pre-trained model, to initialize the app ranker. When updating the
+ // pre-trained model, please update these params, as well as initModel().
+ private static final int CURRENT_VERSION = 1;
+ private static final float LEARNING_RATE = 0.0001f;
+ private static final float REGULARIZER_PARAM = 0.0001f;
+
+ private SharedPreferences mParamSharedPref;
+ private ArrayMap<String, Float> mFeatureWeights;
+ private float mBias;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ initModel();
+ return super.onBind(intent);
+ }
+
+ @Override
+ public void onPredictSharingProbabilities(List<ResolverTarget> targets) {
+ final int size = targets.size();
+ for (int i = 0; i < size; ++i) {
+ ResolverTarget target = targets.get(i);
+ ArrayMap<String, Float> features = getFeatures(target);
+ target.setSelectProbability(predict(features));
+ }
+ }
+
+ @Override
+ public void onTrainRankingModel(List<ResolverTarget> targets, int selectedPosition) {
+ final int size = targets.size();
+ if (selectedPosition < 0 || selectedPosition >= size) {
+ if (DEBUG) {
+ Log.d(TAG, "Invalid Position of Selected App " + selectedPosition);
+ }
+ return;
+ }
+ final ArrayMap<String, Float> positive = getFeatures(targets.get(selectedPosition));
+ final float positiveProbability = targets.get(selectedPosition).getSelectProbability();
+ final int targetSize = targets.size();
+ for (int i = 0; i < targetSize; ++i) {
+ if (i == selectedPosition) {
+ continue;
+ }
+ final ArrayMap<String, Float> negative = getFeatures(targets.get(i));
+ final float negativeProbability = targets.get(i).getSelectProbability();
+ if (negativeProbability > positiveProbability) {
+ update(negative, negativeProbability, false);
+ update(positive, positiveProbability, true);
+ }
+ }
+ commitUpdate();
+ }
+
+ private void initModel() {
+ mParamSharedPref = getParamSharedPref();
+ mFeatureWeights = new ArrayMap<>(4);
+ if (mParamSharedPref == null ||
+ mParamSharedPref.getInt(VERSION_PREF_KEY, 0) < CURRENT_VERSION) {
+ // Initializing the app ranker to a pre-trained model. When updating the pre-trained
+ // model, please increment CURRENT_VERSION, and update LEARNING_RATE and
+ // REGULARIZER_PARAM.
+ mBias = -1.6568f;
+ mFeatureWeights.put(LAUNCH_SCORE, 2.5543f);
+ mFeatureWeights.put(TIME_SPENT_SCORE, 2.8412f);
+ mFeatureWeights.put(RECENCY_SCORE, 0.269f);
+ mFeatureWeights.put(CHOOSER_SCORE, 4.2222f);
+ } else {
+ mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
+ mFeatureWeights.put(LAUNCH_SCORE, mParamSharedPref.getFloat(LAUNCH_SCORE, 0.0f));
+ mFeatureWeights.put(
+ TIME_SPENT_SCORE, mParamSharedPref.getFloat(TIME_SPENT_SCORE, 0.0f));
+ mFeatureWeights.put(RECENCY_SCORE, mParamSharedPref.getFloat(RECENCY_SCORE, 0.0f));
+ mFeatureWeights.put(CHOOSER_SCORE, mParamSharedPref.getFloat(CHOOSER_SCORE, 0.0f));
+ }
+ }
+
+ private ArrayMap<String, Float> getFeatures(ResolverTarget target) {
+ ArrayMap<String, Float> features = new ArrayMap<>(4);
+ features.put(RECENCY_SCORE, target.getRecencyScore());
+ features.put(TIME_SPENT_SCORE, target.getTimeSpentScore());
+ features.put(LAUNCH_SCORE, target.getLaunchScore());
+ features.put(CHOOSER_SCORE, target.getChooserScore());
+ return features;
+ }
+
+ private float predict(ArrayMap<String, Float> target) {
+ if (target == null) {
+ return 0.0f;
+ }
+ final int featureSize = target.size();
+ float sum = 0.0f;
+ for (int i = 0; i < featureSize; i++) {
+ String featureName = target.keyAt(i);
+ float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+ sum += weight * target.valueAt(i);
+ }
+ return (float) (1.0 / (1.0 + Math.exp(-mBias - sum)));
+ }
+
+ private void update(ArrayMap<String, Float> target, float predict, boolean isSelected) {
+ if (target == null) {
+ return;
+ }
+ final int featureSize = target.size();
+ float error = isSelected ? 1.0f - predict : -predict;
+ for (int i = 0; i < featureSize; i++) {
+ String featureName = target.keyAt(i);
+ float currentWeight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+ mBias += LEARNING_RATE * error;
+ currentWeight = currentWeight - LEARNING_RATE * REGULARIZER_PARAM * currentWeight +
+ LEARNING_RATE * error * target.valueAt(i);
+ mFeatureWeights.put(featureName, currentWeight);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Weights: " + mFeatureWeights + " Bias: " + mBias);
+ }
+ }
+
+ private void commitUpdate() {
+ try {
+ SharedPreferences.Editor editor = mParamSharedPref.edit();
+ editor.putFloat(BIAS_PREF_KEY, mBias);
+ final int size = mFeatureWeights.size();
+ for (int i = 0; i < size; i++) {
+ editor.putFloat(mFeatureWeights.keyAt(i), mFeatureWeights.valueAt(i));
+ }
+ editor.putInt(VERSION_PREF_KEY, CURRENT_VERSION);
+ editor.apply();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to commit update" + e);
+ }
+ }
+
+ private SharedPreferences getParamSharedPref() {
+ // The package info in the context isn't initialized in the way it is for normal apps,
+ // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
+ // build the path manually below using the same policy that appears in ContextImpl.
+ if (DEBUG) {
+ Log.d(TAG, "Context Package Name: " + getPackageName());
+ }
+ final File prefsFile = new File(new File(
+ Environment.getDataUserCePackageDirectory(
+ StorageManager.UUID_PRIVATE_INTERNAL, getUserId(), getPackageName()),
+ "shared_prefs"),
+ PARAM_SHARED_PREF_NAME + ".xml");
+ return getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ }
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 3f1c9ad..622b708 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -530,6 +530,9 @@
getMainThreadHandler().removeCallbacks(mPostListReadyRunnable);
mPostListReadyRunnable = null;
}
+ if (mAdapter != null && mAdapter.mResolverListController != null) {
+ mAdapter.mResolverListController.destroy();
+ }
}
@Override
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 096fcb8..73b62a5 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -26,20 +26,34 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.SharedPreferences;
+import android.content.ServiceConnection;
import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
import android.os.storage.StorageManager;
import android.os.UserHandle;
+import android.service.resolver.IResolverRankerService;
+import android.service.resolver.IResolverRankerResult;
+import android.service.resolver.ResolverRankerService;
+import android.service.resolver.ResolverTarget;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import java.io.File;
+import java.lang.InterruptedException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -61,11 +75,15 @@
private static final float RECENCY_MULTIPLIER = 2.f;
- // feature names used in ranking.
- private static final String LAUNCH_SCORE = "launch";
- private static final String TIME_SPENT_SCORE = "timeSpent";
- private static final String RECENCY_SCORE = "recency";
- private static final String CHOOSER_SCORE = "chooser";
+ // message types
+ private static final int RESOLVER_RANKER_SERVICE_RESULT = 0;
+ private static final int RESOLVER_RANKER_RESULT_TIMEOUT = 1;
+
+ // timeout for establishing connections with a ResolverRankerService.
+ private static final int CONNECTION_COST_TIMEOUT_MILLIS = 200;
+ // timeout for establishing connections with a ResolverRankerService, collecting features and
+ // predicting ranking scores.
+ private static final int WATCHDOG_TIMEOUT_MILLIS = 500;
private final Collator mCollator;
private final boolean mHttp;
@@ -74,18 +92,74 @@
private final Map<String, UsageStats> mStats;
private final long mCurrentTime;
private final long mSinceTime;
- private final LinkedHashMap<ComponentName, ScoredTarget> mScoredTargets = new LinkedHashMap<>();
+ private final LinkedHashMap<ComponentName, ResolverTarget> mTargetsDict = new LinkedHashMap<>();
private final String mReferrerPackage;
+ private final Object mLock = new Object();
+ private ArrayList<ResolverTarget> mTargets;
private String mContentType;
private String[] mAnnotations;
private String mAction;
- private LogisticRegressionAppRanker mRanker;
+ private IResolverRankerService mRanker;
+ private ResolverRankerServiceConnection mConnection;
+ private AfterCompute mAfterCompute;
+ private Context mContext;
+ private CountDownLatch mConnectSignal;
- public ResolverComparator(Context context, Intent intent, String referrerPackage) {
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case RESOLVER_RANKER_SERVICE_RESULT:
+ if (DEBUG) {
+ Log.d(TAG, "RESOLVER_RANKER_SERVICE_RESULT");
+ }
+ if (mHandler.hasMessages(RESOLVER_RANKER_RESULT_TIMEOUT)) {
+ if (msg.obj != null) {
+ final List<ResolverTarget> receivedTargets =
+ (List<ResolverTarget>) msg.obj;
+ if (receivedTargets != null && mTargets != null
+ && receivedTargets.size() == mTargets.size()) {
+ final int size = mTargets.size();
+ for (int i = 0; i < size; ++i) {
+ mTargets.get(i).setSelectProbability(
+ receivedTargets.get(i).getSelectProbability());
+ }
+ } else {
+ Log.e(TAG, "Sizes of sent and received ResolverTargets diff.");
+ }
+ } else {
+ Log.e(TAG, "Receiving null prediction results.");
+ }
+ mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT);
+ mAfterCompute.afterCompute();
+ }
+ break;
+
+ case RESOLVER_RANKER_RESULT_TIMEOUT:
+ if (DEBUG) {
+ Log.d(TAG, "RESOLVER_RANKER_RESULT_TIMEOUT; unbinding services");
+ }
+ mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
+ mAfterCompute.afterCompute();
+ break;
+
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+
+ public interface AfterCompute {
+ public void afterCompute ();
+ }
+
+ public ResolverComparator(Context context, Intent intent, String referrerPackage,
+ AfterCompute afterCompute) {
mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
String scheme = intent.getScheme();
mHttp = "http".equals(scheme) || "https".equals(scheme);
mReferrerPackage = referrerPackage;
+ mAfterCompute = afterCompute;
+ mContext = context;
mPm = context.getPackageManager();
mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
@@ -96,9 +170,9 @@
mContentType = intent.getType();
getContentAnnotations(intent);
mAction = intent.getAction();
- mRanker = new LogisticRegressionAppRanker(context);
}
+ // get annotations of content from intent.
public void getContentAnnotations(Intent intent) {
ArrayList<String> annotations = intent.getStringArrayListExtra(
Intent.EXTRA_CONTENT_ANNOTATIONS);
@@ -114,20 +188,24 @@
}
}
+ public void setCallBack(AfterCompute afterCompute) {
+ mAfterCompute = afterCompute;
+ }
+
+ // compute features for each target according to usage stats of targets.
public void compute(List<ResolvedComponentInfo> targets) {
- mScoredTargets.clear();
+ reset();
final long recentSinceTime = mCurrentTime - RECENCY_TIME_PERIOD;
- long mostRecentlyUsedTime = recentSinceTime + 1;
- long mostTimeSpent = 1;
- int mostLaunched = 1;
- int mostSelected = 1;
+ float mostRecencyScore = 1.0f;
+ float mostTimeSpentScore = 1.0f;
+ float mostLaunchScore = 1.0f;
+ float mostChooserScore = 1.0f;
for (ResolvedComponentInfo target : targets) {
- final ScoredTarget scoredTarget
- = new ScoredTarget(target.getResolveInfoAt(0).activityInfo);
- mScoredTargets.put(target.name, scoredTarget);
+ final ResolverTarget resolverTarget = new ResolverTarget();
+ mTargetsDict.put(target.name, resolverTarget);
final UsageStats pkStats = mStats.get(target.name.getPackageName());
if (pkStats != null) {
// Only count recency for apps that weren't the caller
@@ -135,31 +213,33 @@
// Persistent processes muck this up, so omit them too.
if (!target.name.getPackageName().equals(mReferrerPackage)
&& !isPersistentProcess(target)) {
- final long lastTimeUsed = pkStats.getLastTimeUsed();
- scoredTarget.lastTimeUsed = lastTimeUsed;
- if (lastTimeUsed > mostRecentlyUsedTime) {
- mostRecentlyUsedTime = lastTimeUsed;
+ final float recencyScore =
+ (float) Math.max(pkStats.getLastTimeUsed() - recentSinceTime, 0);
+ resolverTarget.setRecencyScore(recencyScore);
+ if (recencyScore > mostRecencyScore) {
+ mostRecencyScore = recencyScore;
}
}
- final long timeSpent = pkStats.getTotalTimeInForeground();
- scoredTarget.timeSpent = timeSpent;
- if (timeSpent > mostTimeSpent) {
- mostTimeSpent = timeSpent;
+ final float timeSpentScore = (float) pkStats.getTotalTimeInForeground();
+ resolverTarget.setTimeSpentScore(timeSpentScore);
+ if (timeSpentScore > mostTimeSpentScore) {
+ mostTimeSpentScore = timeSpentScore;
}
- final int launched = pkStats.mLaunchCount;
- scoredTarget.launchCount = launched;
- if (launched > mostLaunched) {
- mostLaunched = launched;
+ final float launchScore = (float) pkStats.mLaunchCount;
+ resolverTarget.setLaunchScore(launchScore);
+ if (launchScore > mostLaunchScore) {
+ mostLaunchScore = launchScore;
}
- int selected = 0;
+ float chooserScore = 0.0f;
if (pkStats.mChooserCounts != null && mAction != null
&& pkStats.mChooserCounts.get(mAction) != null) {
- selected = pkStats.mChooserCounts.get(mAction).getOrDefault(mContentType, 0);
+ chooserScore = (float) pkStats.mChooserCounts.get(mAction)
+ .getOrDefault(mContentType, 0);
if (mAnnotations != null) {
final int size = mAnnotations.length;
for (int i = 0; i < size; i++) {
- selected += pkStats.mChooserCounts.get(mAction)
+ chooserScore += (float) pkStats.mChooserCounts.get(mAction)
.getOrDefault(mAnnotations[i], 0);
}
}
@@ -169,44 +249,37 @@
Log.d(TAG, "Action type is null");
} else {
Log.d(TAG, "Chooser Count of " + mAction + ":" +
- target.name.getPackageName() + " is " + Integer.toString(selected));
+ target.name.getPackageName() + " is " +
+ Float.toString(chooserScore));
}
}
- scoredTarget.chooserCount = selected;
- if (selected > mostSelected) {
- mostSelected = selected;
+ resolverTarget.setChooserScore(chooserScore);
+ if (chooserScore > mostChooserScore) {
+ mostChooserScore = chooserScore;
}
}
}
-
if (DEBUG) {
- Log.d(TAG, "compute - mostRecentlyUsedTime: " + mostRecentlyUsedTime
- + " mostTimeSpent: " + mostTimeSpent
- + " recentSinceTime: " + recentSinceTime
- + " mostLaunched: " + mostLaunched);
+ Log.d(TAG, "compute - mostRecencyScore: " + mostRecencyScore
+ + " mostTimeSpentScore: " + mostTimeSpentScore
+ + " mostLaunchScore: " + mostLaunchScore
+ + " mostChooserScore: " + mostChooserScore);
}
- for (ScoredTarget target : mScoredTargets.values()) {
- final float recency = (float) Math.max(target.lastTimeUsed - recentSinceTime, 0)
- / (mostRecentlyUsedTime - recentSinceTime);
- target.setFeatures((float) target.launchCount / mostLaunched,
- (float) target.timeSpent / mostTimeSpent,
- recency * recency * RECENCY_MULTIPLIER,
- (float) target.chooserCount / mostSelected);
- target.selectProb = mRanker.predict(target.getFeatures());
+ mTargets = new ArrayList<>(mTargetsDict.values());
+ for (ResolverTarget target : mTargets) {
+ final float recency = target.getRecencyScore() / mostRecencyScore;
+ setFeatures(target, recency * recency * RECENCY_MULTIPLIER,
+ target.getLaunchScore() / mostLaunchScore,
+ target.getTimeSpentScore() / mostTimeSpentScore,
+ target.getChooserScore() / mostChooserScore);
+ addDefaultSelectProbability(target);
if (DEBUG) {
Log.d(TAG, "Scores: " + target);
}
}
- }
-
- static boolean isPersistentProcess(ResolvedComponentInfo rci) {
- if (rci != null && rci.getCount() > 0) {
- return (rci.getResolveInfoAt(0).activityInfo.applicationInfo.flags &
- ApplicationInfo.FLAG_PERSISTENT) != 0;
- }
- return false;
+ predictSelectProbabilities(mTargets);
}
@Override
@@ -245,16 +318,16 @@
// Pinned items stay stable within a normal lexical sort and ignore scoring.
if (!lPinned && !rPinned) {
if (mStats != null) {
- final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
+ final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName(
lhs.activityInfo.packageName, lhs.activityInfo.name));
- final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
+ final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName(
rhs.activityInfo.packageName, rhs.activityInfo.name));
- final int selectProbDiff = Float.compare(
- rhsTarget.selectProb, lhsTarget.selectProb);
+ final int selectProbabilityDiff = Float.compare(
+ rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability());
- if (selectProbDiff != 0) {
- return selectProbDiff > 0 ? 1 : -1;
+ if (selectProbabilityDiff != 0) {
+ return selectProbabilityDiff > 0 ? 1 : -1;
}
}
}
@@ -268,177 +341,234 @@
}
public float getScore(ComponentName name) {
- final ScoredTarget target = mScoredTargets.get(name);
+ final ResolverTarget target = mTargetsDict.get(name);
if (target != null) {
- return target.selectProb;
+ return target.getSelectProbability();
}
return 0;
}
- static class ScoredTarget {
- public final ComponentInfo componentInfo;
- public long lastTimeUsed;
- public long timeSpent;
- public long launchCount;
- public long chooserCount;
- public ArrayMap<String, Float> features;
- public float selectProb;
-
- public ScoredTarget(ComponentInfo ci) {
- componentInfo = ci;
- features = new ArrayMap<>(5);
- }
-
- @Override
- public String toString() {
- return "ScoredTarget{" + componentInfo
- + " lastTimeUsed: " + lastTimeUsed
- + " timeSpent: " + timeSpent
- + " launchCount: " + launchCount
- + " chooserCount: " + chooserCount
- + " selectProb: " + selectProb
- + "}";
- }
-
- public void setFeatures(float launchCountScore, float usageTimeScore, float recencyScore,
- float chooserCountScore) {
- features.put(LAUNCH_SCORE, launchCountScore);
- features.put(TIME_SPENT_SCORE, usageTimeScore);
- features.put(RECENCY_SCORE, recencyScore);
- features.put(CHOOSER_SCORE, chooserCountScore);
- }
-
- public ArrayMap<String, Float> getFeatures() {
- return features;
- }
- }
-
public void updateChooserCounts(String packageName, int userId, String action) {
if (mUsm != null) {
mUsm.reportChooserSelection(packageName, userId, mContentType, mAnnotations, action);
}
}
+ // update ranking model when the connection to it is valid.
public void updateModel(ComponentName componentName) {
- if (mScoredTargets == null || componentName == null ||
- !mScoredTargets.containsKey(componentName)) {
- return;
- }
- ScoredTarget selected = mScoredTargets.get(componentName);
- for (ComponentName targetComponent : mScoredTargets.keySet()) {
- if (targetComponent.equals(componentName)) {
- continue;
- }
- ScoredTarget target = mScoredTargets.get(targetComponent);
- // A potential point of optimization. Save updates or derive a closed form for the
- // positive case, to avoid calculating them repeatedly.
- if (target.selectProb >= selected.selectProb) {
- mRanker.update(target.getFeatures(), target.selectProb, false);
- mRanker.update(selected.getFeatures(), selected.selectProb, true);
+ synchronized (mLock) {
+ if (mRanker != null) {
+ try {
+ int selectedPos = new ArrayList<ComponentName>(mTargetsDict.keySet())
+ .indexOf(componentName);
+ if (selectedPos > 0) {
+ mRanker.train(mTargets, selectedPos);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Selected a unknown component: " + componentName);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in Train: " + e);
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Ranker is null; skip updateModel.");
+ }
}
}
- mRanker.commitUpdate();
}
- class LogisticRegressionAppRanker {
- private static final String PARAM_SHARED_PREF_NAME = "resolver_ranker_params";
- private static final String BIAS_PREF_KEY = "bias";
- private static final String VERSION_PREF_KEY = "version";
-
- // parameters for a pre-trained model, to initialize the app ranker. When updating the
- // pre-trained model, please update these params, as well as initModel().
- private static final int CURRENT_VERSION = 1;
- private static final float LEARNING_RATE = 0.0001f;
- private static final float REGULARIZER_PARAM = 0.0001f;
-
- private SharedPreferences mParamSharedPref;
- private ArrayMap<String, Float> mFeatureWeights;
- private float mBias;
-
- public LogisticRegressionAppRanker(Context context) {
- mParamSharedPref = getParamSharedPref(context);
- initModel();
+ // unbind the service and clear unhandled messges.
+ public void destroy() {
+ mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
+ mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT);
+ if (mConnection != null) {
+ mContext.unbindService(mConnection);
+ mConnection.destroy();
}
-
- public float predict(ArrayMap<String, Float> target) {
- if (target == null) {
- return 0.0f;
- }
- final int featureSize = target.size();
- float sum = 0.0f;
- for (int i = 0; i < featureSize; i++) {
- String featureName = target.keyAt(i);
- float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
- sum += weight * target.valueAt(i);
- }
- return (float) (1.0 / (1.0 + Math.exp(-mBias - sum)));
+ if (DEBUG) {
+ Log.d(TAG, "Unbinded Resolver Ranker.");
}
+ }
- public void update(ArrayMap<String, Float> target, float predict, boolean isSelected) {
- if (target == null) {
+ // connect to a ranking service.
+ private void initRanker(Context context) {
+ synchronized (mLock) {
+ if (mConnection != null && mRanker != null) {
+ if (DEBUG) {
+ Log.d(TAG, "Ranker still exists; reusing the existing one.");
+ }
return;
}
- final int featureSize = target.size();
- float error = isSelected ? 1.0f - predict : -predict;
- for (int i = 0; i < featureSize; i++) {
- String featureName = target.keyAt(i);
- float currentWeight = mFeatureWeights.getOrDefault(featureName, 0.0f);
- mBias += LEARNING_RATE * error;
- currentWeight = currentWeight - LEARNING_RATE * REGULARIZER_PARAM * currentWeight +
- LEARNING_RATE * error * target.valueAt(i);
- mFeatureWeights.put(featureName, currentWeight);
+ }
+ Intent intent = resolveRankerService();
+ if (intent == null) {
+ return;
+ }
+ mConnectSignal = new CountDownLatch(1);
+ mConnection = new ResolverRankerServiceConnection(mConnectSignal);
+ context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
+ }
+
+ // resolve the service for ranking.
+ private Intent resolveRankerService() {
+ Intent intent = new Intent(ResolverRankerService.SERVICE_INTERFACE);
+ final List<ResolveInfo> resolveInfos = mPm.queryIntentServices(intent, 0);
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ if (resolveInfo == null || resolveInfo.serviceInfo == null
+ || resolveInfo.serviceInfo.applicationInfo == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Failed to retrieve a ranker: " + resolveInfo);
+ }
+ continue;
+ }
+ ComponentName componentName = new ComponentName(
+ resolveInfo.serviceInfo.applicationInfo.packageName,
+ resolveInfo.serviceInfo.name);
+ try {
+ final String perm = mPm.getServiceInfo(componentName, 0).permission;
+ if (!ResolverRankerService.BIND_PERMISSION.equals(perm)) {
+ Log.w(TAG, "ResolverRankerService " + componentName + " does not require"
+ + " permission " + ResolverRankerService.BIND_PERMISSION
+ + " - this service will not be queried for ResolverComparator."
+ + " add android:permission=\""
+ + ResolverRankerService.BIND_PERMISSION + "\""
+ + " to the <service> tag for " + componentName
+ + " in the manifest.");
+ continue;
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not look up service " + componentName
+ + "; component name not found");
+ continue;
}
if (DEBUG) {
- Log.d(TAG, "Weights: " + mFeatureWeights + " Bias: " + mBias);
+ Log.d(TAG, "Succeeded to retrieve a ranker: " + componentName);
}
+ intent.setComponent(componentName);
+ return intent;
+ }
+ return null;
+ }
+
+ // set a watchdog, to avoid waiting for ranking service for too long.
+ private void startWatchDog(int timeOutLimit) {
+ if (DEBUG) Log.d(TAG, "Setting watchdog timer for " + timeOutLimit + "ms");
+ if (mHandler == null) {
+ Log.d(TAG, "Error: Handler is Null; Needs to be initialized.");
+ }
+ mHandler.sendEmptyMessageDelayed(RESOLVER_RANKER_RESULT_TIMEOUT, timeOutLimit);
+ }
+
+ private class ResolverRankerServiceConnection implements ServiceConnection {
+ private final CountDownLatch mConnectSignal;
+
+ public ResolverRankerServiceConnection(CountDownLatch connectSignal) {
+ mConnectSignal = connectSignal;
}
- public void commitUpdate() {
- SharedPreferences.Editor editor = mParamSharedPref.edit();
- editor.putFloat(BIAS_PREF_KEY, mBias);
- final int size = mFeatureWeights.size();
- for (int i = 0; i < size; i++) {
- editor.putFloat(mFeatureWeights.keyAt(i), mFeatureWeights.valueAt(i));
+ public final IResolverRankerResult resolverRankerResult =
+ new IResolverRankerResult.Stub() {
+ @Override
+ public void sendResult(List<ResolverTarget> targets) throws RemoteException {
+ if (DEBUG) {
+ Log.d(TAG, "Sending Result back to Resolver: " + targets);
+ }
+ synchronized (mLock) {
+ final Message msg = Message.obtain();
+ msg.what = RESOLVER_RANKER_SERVICE_RESULT;
+ msg.obj = targets;
+ mHandler.sendMessage(msg);
+ }
}
- editor.putInt(VERSION_PREF_KEY, CURRENT_VERSION);
- editor.apply();
- }
+ };
- private SharedPreferences getParamSharedPref(Context context) {
- // The package info in the context isn't initialized in the way it is for normal apps,
- // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
- // build the path manually below using the same policy that appears in ContextImpl.
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) {
- Log.d(TAG, "Context Package Name: " + context.getPackageName());
+ Log.d(TAG, "onServiceConnected: " + name);
}
- final File prefsFile = new File(new File(
- Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
- context.getUserId(), context.getPackageName()),
- "shared_prefs"),
- PARAM_SHARED_PREF_NAME + ".xml");
- return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ synchronized (mLock) {
+ mRanker = IResolverRankerService.Stub.asInterface(service);
+ mConnectSignal.countDown();
+ }
}
- private void initModel() {
- mFeatureWeights = new ArrayMap<>(4);
- if (mParamSharedPref == null ||
- mParamSharedPref.getInt(VERSION_PREF_KEY, 0) < CURRENT_VERSION) {
- // Initializing the app ranker to a pre-trained model. When updating the pre-trained
- // model, please increment CURRENT_VERSION, and update LEARNING_RATE and
- // REGULARIZER_PARAM.
- mBias = -1.6568f;
- mFeatureWeights.put(LAUNCH_SCORE, 2.5543f);
- mFeatureWeights.put(TIME_SPENT_SCORE, 2.8412f);
- mFeatureWeights.put(RECENCY_SCORE, 0.269f);
- mFeatureWeights.put(CHOOSER_SCORE, 4.2222f);
- } else {
- mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
- mFeatureWeights.put(LAUNCH_SCORE, mParamSharedPref.getFloat(LAUNCH_SCORE, 0.0f));
- mFeatureWeights.put(
- TIME_SPENT_SCORE, mParamSharedPref.getFloat(TIME_SPENT_SCORE, 0.0f));
- mFeatureWeights.put(RECENCY_SCORE, mParamSharedPref.getFloat(RECENCY_SCORE, 0.0f));
- mFeatureWeights.put(CHOOSER_SCORE, mParamSharedPref.getFloat(CHOOSER_SCORE, 0.0f));
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) {
+ Log.d(TAG, "onServiceDisconnected: " + name);
+ }
+ synchronized (mLock) {
+ destroy();
}
}
+
+ public void destroy() {
+ synchronized (mLock) {
+ mRanker = null;
+ }
+ }
+ }
+
+ private void reset() {
+ mTargetsDict.clear();
+ mTargets = null;
+ startWatchDog(WATCHDOG_TIMEOUT_MILLIS);
+ initRanker(mContext);
+ }
+
+ // predict select probabilities if ranking service is valid.
+ private void predictSelectProbabilities(List<ResolverTarget> targets) {
+ if (mConnection == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Has not found valid ResolverRankerService; Skip Prediction");
+ }
+ return;
+ } else {
+ try {
+ mConnectSignal.await(CONNECTION_COST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ synchronized (mLock) {
+ if (mRanker != null) {
+ mRanker.predict(targets, mConnection.resolverRankerResult);
+ return;
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Ranker has not been initialized; skip predict.");
+ }
+ }
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Error in Wait for Service Connection.");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in Predict: " + e);
+ }
+ }
+ mAfterCompute.afterCompute();
+ }
+
+ // adds select prob as the default values, according to a pre-trained Logistic Regression model.
+ private void addDefaultSelectProbability(ResolverTarget target) {
+ float sum = 2.5543f * target.getLaunchScore() + 2.8412f * target.getTimeSpentScore() +
+ 0.269f * target.getRecencyScore() + 4.2222f * target.getChooserScore();
+ target.setSelectProbability((float) (1.0 / (1.0 + Math.exp(1.6568f - sum))));
+ }
+
+ // sets features for each target
+ private void setFeatures(ResolverTarget target, float recencyScore, float launchScore,
+ float timeSpentScore, float chooserScore) {
+ target.setRecencyScore(recencyScore);
+ target.setLaunchScore(launchScore);
+ target.setTimeSpentScore(timeSpentScore);
+ target.setChooserScore(chooserScore);
+ }
+
+ static boolean isPersistentProcess(ResolvedComponentInfo rci) {
+ if (rci != null && rci.getCount() > 0) {
+ return (rci.getResolveInfoAt(0).activityInfo.applicationInfo.flags &
+ ApplicationInfo.FLAG_PERSISTENT) != 0;
+ }
+ return false;
}
}
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 4071ff4..e8bebb7 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -32,8 +32,10 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.InterruptedException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
import java.util.List;
/**
@@ -205,14 +207,42 @@
return listToReturn;
}
+ private class ComputeCallback implements ResolverComparator.AfterCompute {
+
+ private CountDownLatch mFinishComputeSignal;
+
+ public ComputeCallback(CountDownLatch finishComputeSignal) {
+ mFinishComputeSignal = finishComputeSignal;
+ }
+
+ public void afterCompute () {
+ mFinishComputeSignal.countDown();
+ }
+ }
+
@VisibleForTesting
@WorkerThread
public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
+ final CountDownLatch finishComputeSignal = new CountDownLatch(1);
+ ComputeCallback callback = new ComputeCallback(finishComputeSignal);
if (mResolverComparator == null) {
- mResolverComparator = new ResolverComparator(mContext, mTargetIntent, mReferrerPackage);
+ mResolverComparator =
+ new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, callback);
+ } else {
+ mResolverComparator.setCallBack(callback);
}
- mResolverComparator.compute(inputList);
- Collections.sort(inputList, mResolverComparator);
+ try {
+ long beforeRank = System.currentTimeMillis();
+ mResolverComparator.compute(inputList);
+ finishComputeSignal.await();
+ Collections.sort(inputList, mResolverComparator);
+ long afterRank = System.currentTimeMillis();
+ if (DEBUG) {
+ Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Compute & Sort was interrupted: " + e);
+ }
}
private static boolean isSameResolvedComponent(ResolveInfo a,
@@ -233,7 +263,7 @@
@VisibleForTesting
public float getScore(ResolverActivity.DisplayResolveInfo target) {
if (mResolverComparator == null) {
- mResolverComparator = new ResolverComparator(mContext, mTargetIntent, mReferrerPackage);
+ return 0.0f;
}
return mResolverComparator.getScore(target.getResolvedComponentName());
}
@@ -249,4 +279,10 @@
mResolverComparator.updateChooserCounts(packageName, userId, action);
}
}
+
+ public void destroy() {
+ if (mResolverComparator != null) {
+ mResolverComparator.destroy();
+ }
+ }
}
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 1abb59b..a70209c 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -74,6 +74,7 @@
private final Rect mOldStableInsets = new Rect();
private final Rect mSystemInsets = new Rect();
private final Rect mStableInsets = new Rect();
+ private final Rect mTmpRect = new Rect();
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
@@ -370,12 +371,6 @@
DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
- final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom,
- systemInsets.bottom);
- final int rightInset = DecorView.getColorViewRightInset(stableInsets.right,
- systemInsets.right);
- final int leftInset = DecorView.getColorViewLeftInset(stableInsets.left,
- systemInsets.left);
if (mStatusBarColor != null) {
mStatusBarColor.setBounds(0, 0, left + width, topInset);
mStatusBarColor.draw(canvas);
@@ -385,14 +380,8 @@
// don't want the navigation bar background be moving around when resizing in docked mode.
// However, we need it for the transitions into/out of docked mode.
if (mNavigationBarColor != null && fullscreen) {
- final int size = DecorView.getNavBarSize(bottomInset, rightInset, leftInset);
- if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
- mNavigationBarColor.setBounds(width - size, 0, width, height);
- } else if (DecorView.isNavBarToLeftEdge(bottomInset, leftInset)) {
- mNavigationBarColor.setBounds(0, 0, size, height);
- } else {
- mNavigationBarColor.setBounds(0, height - size, width, height);
- }
+ DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect);
+ mNavigationBarColor.setBounds(mTmpRect);
mNavigationBarColor.draw(canvas);
}
mSystemBarBackgroundNode.end(canvas);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index a8e16c9..653796d 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -119,6 +119,21 @@
// The height of a window which has not in DIP.
private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
+ public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
+ new ColorViewAttributes(SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+ Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
+ Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.statusBarBackground,
+ FLAG_FULLSCREEN);
+
+ public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
+ new ColorViewAttributes(
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+ Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
+ Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.navigationBarBackground,
+ 0 /* hideWindowFlag */);
+
// Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
// size calculation takes the shadow size into account. We set the elevation currently
// to max until the first layout command has been executed.
@@ -162,18 +177,10 @@
// View added at runtime to draw under the navigation bar area
private View mNavigationGuard;
- private final ColorViewState mStatusColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
- Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
- Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground,
- FLAG_FULLSCREEN);
- private final ColorViewState mNavigationColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
- Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
- Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground,
- 0 /* hideWindowFlag */);
+ private final ColorViewState mStatusColorViewState =
+ new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
+ private final ColorViewState mNavigationColorViewState =
+ new ColorViewState(NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES);
private final Interpolator mShowInterpolator;
private final Interpolator mHideInterpolator;
@@ -983,35 +990,50 @@
return false;
}
- static int getColorViewTopInset(int stableTop, int systemTop) {
+ public static int getColorViewTopInset(int stableTop, int systemTop) {
return Math.min(stableTop, systemTop);
}
- static int getColorViewBottomInset(int stableBottom, int systemBottom) {
+ public static int getColorViewBottomInset(int stableBottom, int systemBottom) {
return Math.min(stableBottom, systemBottom);
}
- static int getColorViewRightInset(int stableRight, int systemRight) {
+ public static int getColorViewRightInset(int stableRight, int systemRight) {
return Math.min(stableRight, systemRight);
}
- static int getColorViewLeftInset(int stableLeft, int systemLeft) {
+ public static int getColorViewLeftInset(int stableLeft, int systemLeft) {
return Math.min(stableLeft, systemLeft);
}
- static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
+ public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
return bottomInset == 0 && rightInset > 0;
}
- static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
+ public static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
return bottomInset == 0 && leftInset > 0;
}
- static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
+ public static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset
: isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
}
+ public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
+ Rect contentInsets, Rect outRect) {
+ final int bottomInset = getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom);
+ final int leftInset = getColorViewLeftInset(stableInsets.left, contentInsets.left);
+ final int rightInset = getColorViewLeftInset(stableInsets.right, contentInsets.right);
+ final int size = getNavBarSize(bottomInset, rightInset, leftInset);
+ if (isNavBarToRightEdge(bottomInset, rightInset)) {
+ outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
+ } else if (isNavBarToLeftEdge(bottomInset, leftInset)) {
+ outRect.set(0, 0, size, canvasHeight);
+ } else {
+ outRect.set(0, canvasHeight - size, canvasWidth, canvasHeight);
+ }
+ }
+
WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
WindowManager.LayoutParams attrs = mWindow.getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
@@ -1131,9 +1153,14 @@
}
private int calculateStatusBarColor() {
- int flags = mWindow.getAttributes().flags;
- return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
- : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor
+ return calculateStatusBarColor(mWindow.getAttributes().flags,
+ mSemiTransparentStatusBarColor, mWindow.mStatusBarColor);
+ }
+
+ public static int calculateStatusBarColor(int flags, int semiTransparentStatusBarColor,
+ int statusBarColor) {
+ return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? semiTransparentStatusBarColor
+ : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? statusBarColor
: Color.BLACK;
}
@@ -1160,13 +1187,9 @@
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int size, boolean verticalBar, boolean seascape, int sideMargin,
boolean animate, boolean force) {
- state.present = (sysUiVis & state.systemUiHideFlag) == 0
- && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
- && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || force);
- boolean show = state.present
- && (color & Color.BLACK) != 0
- && ((mWindow.getAttributes().flags & state.translucentFlag) == 0 || force);
+ state.present = state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force);
+ boolean show = state.attributes.isVisible(state.present, color,
+ mWindow.getAttributes().flags, force);
boolean showView = show && !isResizing() && size > 0;
boolean visibilityChanged = false;
@@ -1175,15 +1198,15 @@
int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size;
int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT;
int resolvedGravity = verticalBar
- ? (seascape ? state.seascapeGravity : state.horizontalGravity)
- : state.verticalGravity;
+ ? (seascape ? state.attributes.seascapeGravity : state.attributes.horizontalGravity)
+ : state.attributes.verticalGravity;
if (view == null) {
if (showView) {
state.view = view = new View(mContext);
view.setBackgroundColor(color);
- view.setTransitionName(state.transitionName);
- view.setId(state.id);
+ view.setTransitionName(state.attributes.transitionName);
+ view.setId(state.attributes.id);
visibilityChanged = true;
view.setVisibility(INVISIBLE);
state.targetVisibility = VISIBLE;
@@ -2269,6 +2292,15 @@
boolean visible;
int color;
+ final ColorViewAttributes attributes;
+
+ ColorViewState(ColorViewAttributes attributes) {
+ this.attributes = attributes;
+ }
+ }
+
+ public static class ColorViewAttributes {
+
final int id;
final int systemUiHideFlag;
final int translucentFlag;
@@ -2278,9 +2310,9 @@
final String transitionName;
final int hideWindowFlag;
- ColorViewState(int systemUiHideFlag,
- int translucentFlag, int verticalGravity, int horizontalGravity,
- int seascapeGravity, String transitionName, int id, int hideWindowFlag) {
+ private ColorViewAttributes(int systemUiHideFlag, int translucentFlag, int verticalGravity,
+ int horizontalGravity, int seascapeGravity, String transitionName, int id,
+ int hideWindowFlag) {
this.id = id;
this.systemUiHideFlag = systemUiHideFlag;
this.translucentFlag = translucentFlag;
@@ -2290,6 +2322,24 @@
this.transitionName = transitionName;
this.hideWindowFlag = hideWindowFlag;
}
+
+ public boolean isPresent(int sysUiVis, int windowFlags, boolean force) {
+ return (sysUiVis & systemUiHideFlag) == 0
+ && (windowFlags & hideWindowFlag) == 0
+ && ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ || force);
+ }
+
+ public boolean isVisible(boolean present, int color, int windowFlags, boolean force) {
+ return present
+ && (color & Color.BLACK) != 0
+ && ((windowFlags & translucentFlag) == 0 || force);
+ }
+
+ public boolean isVisible(int sysUiVis, int color, int windowFlags, boolean force) {
+ final boolean present = isPresent(sysUiVis, windowFlags, force);
+ return isVisible(present, color, windowFlags, force);
+ }
}
/**
diff --git a/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java b/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java
new file mode 100644
index 0000000..e40090f
--- /dev/null
+++ b/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.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.internal.view;
+
+import android.os.Handler;
+import android.os.Message;
+import android.view.Choreographer;
+import android.view.Display;
+
+/**
+ * Utility class to schedule things at vsync-sf instead of vsync-app
+ * @hide
+ */
+public class SurfaceFlingerVsyncChoreographer {
+
+ private static final long ONE_MS_IN_NS = 1000000;
+ private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
+
+ private final Handler mHandler;
+ private final Choreographer mChoreographer = Choreographer.getInstance();
+
+ /**
+ * The offset between vsync-app and vsync-surfaceflinger. See
+ * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
+ */
+ private long mSurfaceFlingerOffsetMs;
+
+ public SurfaceFlingerVsyncChoreographer(Handler handler, Display display) {
+ mHandler = handler;
+ mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(display);
+ }
+
+ public long getSurfaceFlingerOffsetMs() {
+ return mSurfaceFlingerOffsetMs;
+ }
+
+ /**
+ * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
+ * is a couple of milliseconds before vsync-sf, a touch or animation event that causes a surface
+ * flinger transaction are sometimes processed before the vsync-sf tick, and sometimes after,
+ * which leads to jank. Figure out this difference here and then post all the touch/animation
+ * events to start being processed at vsync-sf.
+ *
+ * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
+ */
+ private long calculateAppSurfaceFlingerVsyncOffsetMs(Display display) {
+
+ // Calculate vsync offset from SurfaceFlinger.
+ // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
+ long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
+ long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
+ return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
+ }
+
+ public void scheduleAtSfVsync(Runnable r) {
+ final long delay = calculateDelay();
+ if (delay <= 0) {
+ r.run();
+ } else {
+ mHandler.postDelayed(r, delay);
+ }
+ }
+
+ public void scheduleAtSfVsync(Handler h, Message m) {
+ final long delay = calculateDelay();
+ if (delay <= 0) {
+ h.handleMessage(m);
+ } else {
+ m.setAsynchronous(true);
+ h.sendMessageDelayed(m, delay);
+ }
+ }
+
+ private long calculateDelay() {
+ final long sinceFrameStart = System.nanoTime() - mChoreographer.getLastFrameTimeNanos();
+ return mSurfaceFlingerOffsetMs - sinceFrameStart / 1000000;
+ }
+}
diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp
index 91fec2a..3bcf0c7 100644
--- a/core/jni/android/graphics/FontUtils.cpp
+++ b/core/jni/android/graphics/FontUtils.cpp
@@ -55,7 +55,7 @@
gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I");
- jclass axisClass = FindClassOrDie(env, "android/text/FontConfig$Axis");
+ jclass axisClass = FindClassOrDie(env, "android/graphics/fonts/FontVariationAxis");
gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "mTag", "I");
gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "mStyleValue", "F");
}
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index a77ed62..1a35330 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);
@@ -89,7 +97,7 @@
SkShader* shader = 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, matrix).release();
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
ThrowIAE_IfNull(env, shader);
@@ -109,7 +117,7 @@
colors[1] = color1;
SkShader* s = SkGradientShader::MakeLinear(pts, colors, NULL, 2,
- (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
+ static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, matrix).release();
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
@@ -135,7 +143,7 @@
SkShader* shader = 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, matrix).release();
env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
JNI_ABORT);
@@ -154,7 +162,7 @@
colors[1] = color1;
SkShader* s = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2,
- (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
+ static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, matrix).release();
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
}
@@ -174,8 +182,8 @@
#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();
+ SkShader* shader = SkGradientShader::MakeSweep(x, y, reinterpret_cast<const SkColor*>(colors),
+ pos, count, sGradientShaderFlags, matrix).release();
env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
JNI_ABORT);
ThrowIAE_IfNull(env, shader);
@@ -189,7 +197,7 @@
colors[0] = color0;
colors[1] = color1;
SkShader* s = SkGradientShader::MakeSweep(x, y, colors, NULL, 2,
- /* flags */ 0, matrix).release();
+ sGradientShaderFlags, matrix).release();
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 713287e..5839fd5 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -101,17 +101,7 @@
return sur;
}
-jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
- const sp<IGraphicBufferProducer>& bufferProducer) {
- if (bufferProducer == NULL) {
- return NULL;
- }
-
- sp<Surface> surface(new Surface(bufferProducer, true));
- if (surface == NULL) {
- return NULL;
- }
-
+jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
gSurfaceClassInfo.ctor, (jlong)surface.get());
if (surfaceObj == NULL) {
@@ -126,6 +116,16 @@
return surfaceObj;
}
+jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
+ const sp<IGraphicBufferProducer>& bufferProducer) {
+ if (bufferProducer == NULL) {
+ return NULL;
+ }
+
+ sp<Surface> surface(new Surface(bufferProducer, true));
+ return android_view_Surface_createFromSurface(env, surface);
+}
+
int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
switch(f) {
diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h
index 3f1bdff..2641ab8 100644
--- a/core/jni/include/android_runtime/android_view_Surface.h
+++ b/core/jni/include/android_runtime/android_view_Surface.h
@@ -69,6 +69,10 @@
/* Gets the underlying Surface from a Surface Java object. */
extern sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj);
+/* Creates a Surface from an android::Surface. */
+extern jobject android_view_Surface_createFromSurface(JNIEnv* env,
+ const sp<Surface>& surface);
+
/* Creates a Surface from an IGraphicBufferProducer. */
extern jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e7a447c..0a50048 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3129,6 +3129,15 @@
<permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
android:protectionLevel="signature" />
+ <!-- @SystemApi Must be required by services that extend
+ {@link android.service.resolver.ResolverRankerService}, to ensure that only the system can
+ bind to them.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- Must be required by a {@link
android.service.notification.ConditionProviderService},
to ensure that only the system can bind to it.
@@ -3640,6 +3649,14 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
+ <service android:name="com.android.internal.app.LRResolverRankerService"
+ android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE"
+ android:exported="false"
+ android:priority="-1" >
+ <intent-filter>
+ <action android:name="android.service.resolver.ResolverRankerService" />
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 554f50c..ee73b69 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8566,6 +8566,11 @@
<!-- @hide From Theme.colorBackground, used for the TaskDescription background
color. -->
<attr name="colorBackground" />
+ <!-- @hide From Theme.statusBarColor, used for the TaskDescription status bar color. -->
+ <attr name="statusBarColor"/>
+ <!-- @hide From Theme.navigationBarColor, used for the TaskDescription navigation bar
+ color. -->
+ <attr name="navigationBarColor"/>
</declare-styleable>
<declare-styleable name="Shortcut">
diff --git a/core/tests/coretests/src/android/graphics/VariationParserTest.java b/core/tests/coretests/src/android/graphics/VariationParserTest.java
deleted file mode 100644
index fdabb13..0000000
--- a/core/tests/coretests/src/android/graphics/VariationParserTest.java
+++ /dev/null
@@ -1,126 +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.graphics;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.FontConfig;
-
-import junit.framework.TestCase;
-
-import java.util.List;
-
-
-public class VariationParserTest extends TestCase {
-
- @SmallTest
- public void testParseFontVariationSetting() {
- int tag = FontListParser.makeTag("wdth");
- List<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings("'wdth' 1");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(1.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings("\"wdth\" 100");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(100.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings(" 'wdth' 100");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(100.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(0.5f, axes.get(0).getStyleValue());
-
- tag = FontListParser.makeTag("AX ");
- axes = FontListParser.parseFontVariationSettings("'AX ' 1");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(1.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings("'AX '\t1");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(1.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings("'AX '\n1");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(1.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings("'AX '\r1");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(1.0f, axes.get(0).getStyleValue());
-
- axes = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1");
- assertEquals(tag, axes.get(0).getTag());
- assertEquals(1.0f, axes.get(0).getStyleValue());
-
- // Test for invalid input
- axes = FontListParser.parseFontVariationSettings("");
- assertEquals(0, axes.size());
- axes = FontListParser.parseFontVariationSettings("invalid_form");
- assertEquals(0, axes.size());
-
- // Test with invalid tag
- axes = FontListParser.parseFontVariationSettings("'' 1");
- assertEquals(0, axes.size());
- axes = FontListParser.parseFontVariationSettings("'invalid' 1");
- assertEquals(0, axes.size());
-
- // Test with invalid styleValue
- axes = FontListParser.parseFontVariationSettings("'wdth' ");
- assertEquals(0, axes.size());
- axes = FontListParser.parseFontVariationSettings("'wdth' x");
- assertEquals(0, axes.size());
- axes = FontListParser.parseFontVariationSettings("'wdth' \t");
- assertEquals(0, axes.size());
- axes = FontListParser.parseFontVariationSettings("'wdth' \n\r");
- assertEquals(0, axes.size());
- }
-
- @SmallTest
- public void testParseFontVariationStyleSettings() {
- List<FontConfig.Axis> axes =
- FontListParser.parseFontVariationSettings("'wdth' 10,'AX '\r1");
- int tag1 = FontListParser.makeTag("wdth");
- int tag2 = FontListParser.makeTag("AX ");
- assertEquals(tag1, axes.get(0).getTag());
- assertEquals(10.0f, axes.get(0).getStyleValue());
- assertEquals(tag2, axes.get(1).getTag());
- assertEquals(1.0f, axes.get(1).getStyleValue());
-
- // Test only spacers are allowed before tag
- axes = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1");
- tag1 = FontListParser.makeTag("wdth");
- assertEquals(tag1, axes.get(0).getTag());
- assertEquals(10.0f, axes.get(0).getStyleValue());
- assertEquals(1, axes.size());
- }
-
- @SmallTest
- public void testInvalidTagCharacters() {
- List<FontConfig.Axis> axes =
- FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
- assertEquals(0, axes.size());
- axes = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
- assertEquals(0, axes.size());
- }
-
- @SmallTest
- public void testMakeTag() {
- assertEquals(0x77647468, FontListParser.makeTag("wdth"));
- assertEquals(0x41582020, FontListParser.makeTag("AX "));
- assertEquals(0x20202020, FontListParser.makeTag(" "));
- }
-}
diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java
new file mode 100644
index 0000000..bcc47e1
--- /dev/null
+++ b/core/tests/coretests/src/android/text/VariationParserTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.text;
+
+import android.graphics.fonts.FontVariationAxis;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+public class VariationParserTest extends TestCase {
+ private static final String[] INVALID_STYLE_VALUES = {
+ "", "x", "\t", "\n"
+ };
+
+ @SmallTest
+ public void testFromFontVariationSetting_InvalidStyleValue() {
+ // Test with invalid styleValue
+ for (String invalidStyle : INVALID_STYLE_VALUES) {
+ try {
+ FontVariationAxis.fromFontVariationSettings("'wdth' " + invalidStyle);
+ fail();
+ } catch (FontVariationAxis.InvalidFormatException e) {
+ // pass
+ }
+ }
+ for (String invalidStyle : INVALID_STYLE_VALUES) {
+ try {
+ FontVariationAxis.fromFontVariationSettings("'wght' 1, 'wdth' " + invalidStyle);
+ fail();
+ } catch (FontVariationAxis.InvalidFormatException e) {
+ // pass
+ }
+ }
+ }
+
+ @SmallTest
+ public void testOpenTypeTagValue() throws FontVariationAxis.InvalidFormatException {
+ assertEquals(0x77647468, (new FontVariationAxis("wdth", 0).getOpenTypeTagValue()));
+ assertEquals(0x41582020, (new FontVariationAxis("AX ", 0).getOpenTypeTagValue()));
+ assertEquals(0x20202020, (new FontVariationAxis(" ", 0).getOpenTypeTagValue()));
+ }
+}
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 76c29a9..3dab1f7 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -3,15 +3,10 @@
WARNING: Parsing of this file by third-party apps is not supported. The
file, and the font files it refers to, will be renamed and/or moved out
from their respective location in the next Android release, and/or the
- format or syntax of the file may change significantly. You must not
- parse this file for information about system fonts. Instead, you must
- call android.text.FontManager#getSystemFonts(). For example, it can be
- called as context.getSystemService(FontManager.class).getSystemFonts().
- Note that the returned FontConfig includes data on all the defined font
- families and all the details about weight, style, etc. It also provides
- an open file descriptor to each font file. Note that callers of the API
- should ensure they close the given file descriptors once they are done
- using them.
+ format or syntax of the file may change significantly. If you parse this
+ file for information about system fonts, do it at your own risk. Your
+ application will almost certainly break with the next major Android
+ release.
In this file, all fonts without names are added to the default list.
Fonts are chosen based on a match: full BCP-47 language tag including
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 6214ba6..4b1b0c6 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -17,6 +17,7 @@
package android.graphics;
import android.content.res.AssetManager;
+import android.graphics.fonts.FontVariationAxis;
import android.text.FontConfig;
import android.util.Log;
import dalvik.annotation.optimization.CriticalNative;
@@ -81,7 +82,7 @@
}
}
- public boolean addFont(String path, int ttcIndex, FontConfig.Axis[] axes, int weight,
+ public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
int italic) {
if (mBuilderPtr == 0) {
throw new IllegalStateException("Unable to call addFont after freezing.");
@@ -91,8 +92,8 @@
long fontSize = fileChannel.size();
ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
if (axes != null) {
- for (FontConfig.Axis axis : axes) {
- nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
+ for (FontVariationAxis axis : axes) {
+ nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
}
}
return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
@@ -102,14 +103,14 @@
}
}
- public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontConfig.Axis[] axes,
+ public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
int weight, int italic) {
if (mBuilderPtr == 0) {
throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
}
if (axes != null) {
- for (FontConfig.Axis axis : axes) {
- nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
+ for (FontVariationAxis axis : axes) {
+ nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
}
}
return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
@@ -129,13 +130,13 @@
*/
public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
boolean isAsset, int ttcIndex, int weight, int isItalic,
- FontConfig.Axis[] axes) {
+ FontVariationAxis[] axes) {
if (mBuilderPtr == 0) {
throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
}
if (axes != null) {
- for (FontConfig.Axis axis : axes) {
- nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
+ for (FontVariationAxis axis : axes) {
+ nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
}
}
return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index ff9f11d..1a4f225 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -17,6 +17,7 @@
package android.graphics;
import android.text.FontConfig;
+import android.graphics.fonts.FontVariationAxis;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
@@ -50,72 +51,6 @@
}
}
- // Note that a well-formed variation contains a four-character tag and a float as styleValue,
- // with spacers in between. The tag is enclosd either by double quotes or single quotes.
- @VisibleForTesting
- public static ArrayList<FontConfig.Axis> parseFontVariationSettings(@Nullable String settings) {
- ArrayList<FontConfig.Axis> axisList = new ArrayList<>();
- if (settings == null) {
- return axisList;
- }
- String[] settingList = settings.split(",");
- settingLoop:
- for (String setting : settingList) {
- int pos = 0;
- while (pos < setting.length()) {
- char c = setting.charAt(pos);
- if (c == '\'' || c == '"') {
- break;
- } else if (!isSpacer(c)) {
- continue settingLoop; // Only spacers are allowed before tag appeared.
- }
- pos++;
- }
- if (pos + 7 > setting.length()) {
- continue; // 7 is the minimum length of tag-style value pair text.
- }
- if (setting.charAt(pos) != setting.charAt(pos + 5)) {
- continue; // Tag should be wrapped with double or single quote.
- }
- String tagString = setting.substring(pos + 1, pos + 5);
- if (!TAG_PATTERN.matcher(tagString).matches()) {
- continue; // Skip incorrect format tag.
- }
- pos += 6;
- while (pos < setting.length()) {
- if (!isSpacer(setting.charAt(pos++))) {
- break; // Skip spacers between the tag and the styleValue.
- }
- }
- // Skip invalid styleValue
- float styleValue;
- String valueString = setting.substring(pos - 1);
- if (!STYLE_VALUE_PATTERN.matcher(valueString).matches()) {
- continue; // Skip incorrect format styleValue.
- }
- try {
- styleValue = Float.parseFloat(valueString);
- } catch (NumberFormatException e) {
- continue; // ignoreing invalid number format
- }
- int tag = makeTag(tagString);
- axisList.add(new FontConfig.Axis(tag, styleValue));
- }
- return axisList;
- }
-
- public static int makeTag(String tagString) {
- char c1 = tagString.charAt(0);
- char c2 = tagString.charAt(1);
- char c3 = tagString.charAt(2);
- char c4 = tagString.charAt(3);
- return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
- }
-
- private static boolean isSpacer(char c) {
- return c == ' ' || c == '\r' || c == '\t' || c == '\n';
- }
-
private static FontConfig readFamilies(XmlPullParser parser)
throws XmlPullParserException, IOException {
List<FontConfig.Family> families = new ArrayList<>();
@@ -172,7 +107,7 @@
throws XmlPullParserException, IOException {
String indexStr = parser.getAttributeValue(null, "index");
int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
- List<FontConfig.Axis> axes = new ArrayList<FontConfig.Axis>();
+ List<FontVariationAxis> axes = new ArrayList<FontVariationAxis>();
String weightStr = parser.getAttributeValue(null, "weight");
int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));
@@ -191,47 +126,20 @@
}
String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
return new FontConfig.Font(sanitizedName, index,
- axes.toArray(new FontConfig.Axis[axes.size()]), weight, isItalic);
+ axes.toArray(new FontVariationAxis[axes.size()]), weight, isItalic);
}
- /** The 'tag' attribute value is read as four character values between U+0020 and U+007E
- * inclusive.
- */
- private static final Pattern TAG_PATTERN = Pattern.compile("[\\x20-\\x7E]{4}");
-
- public static boolean isValidTag(String tagString) {
- if (tagString == null || tagString.length() != 4) {
- return false;
- }
- return TAG_PATTERN.matcher(tagString).matches();
- }
-
- /** The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
- * '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
- */
- private static final Pattern STYLE_VALUE_PATTERN =
- Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))");
-
- private static FontConfig.Axis readAxis(XmlPullParser parser)
+ private static FontVariationAxis readAxis(XmlPullParser parser)
throws XmlPullParserException, IOException {
- int tag = 0;
String tagStr = parser.getAttributeValue(null, "tag");
- if (isValidTag(tagStr)) {
- tag = makeTag(tagStr);
- } else {
- throw new XmlPullParserException("Invalid tag attribute value.", parser, null);
- }
-
- float styleValue = 0;
String styleValueStr = parser.getAttributeValue(null, "stylevalue");
- if (styleValueStr != null && STYLE_VALUE_PATTERN.matcher(styleValueStr).matches()) {
- styleValue = Float.parseFloat(styleValueStr);
- } else {
- throw new XmlPullParserException("Invalid styleValue attribute value.", parser, null);
- }
-
skip(parser); // axis tag is empty, ignore any contents and consume end tag
- return new FontConfig.Axis(tag, styleValue);
+ try {
+ return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr));
+ } catch (FontVariationAxis.InvalidFormatException e) {
+ // Treat as system failure since system preinstalled font setting has invalid format.
+ throw new RuntimeException(e);
+ }
}
private static FontConfig.Alias readAlias(XmlPullParser parser)
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index c4f7dc3..828729a 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Size;
import android.graphics.FontListParser;
+import android.graphics.fonts.FontVariationAxis;
import android.os.LocaleList;
import android.text.FontConfig;
import android.text.GraphicsOperations;
@@ -1551,8 +1552,11 @@
* @return true if the given settings is effective to at least one font file underlying this
* typeface. This function also returns true for empty settings string. Otherwise
* returns false
+ * @throws FontVariationAxis.InvalidFormatException
+ * If given string is not a valid font variation settings format.
*/
- public boolean setFontVariationSettings(String settings) {
+ public boolean setFontVariationSettings(String settings)
+ throws FontVariationAxis.InvalidFormatException {
settings = TextUtils.nullIfEmpty(settings);
if (settings == mFontVariationSettings
|| (settings != null && settings.equals(mFontVariationSettings))) {
@@ -1566,11 +1570,10 @@
return true;
}
- final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(settings);
- final ArrayList<FontConfig.Axis> filteredAxes = new ArrayList<FontConfig.Axis>();
- for (int i = 0; i < axes.size(); ++i) {
- final FontConfig.Axis axis = axes.get(i);
- if (mTypeface.isSupportedAxes(axis.getTag())) {
+ FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings(settings);
+ final ArrayList<FontVariationAxis> filteredAxes = new ArrayList<FontVariationAxis>();
+ for (final FontVariationAxis axis : axes) {
+ if (mTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) {
filteredAxes.add(axis);
}
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 8c3a2e8..560d29f 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -32,6 +32,7 @@
import android.graphics.FontListParser;
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
+import android.graphics.fonts.FontVariationAxis;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
@@ -358,11 +359,15 @@
FileChannel.MapMode.READ_ONLY, 0, fontSize);
int style = result.getStyle();
int weight = (style & BOLD) != 0 ? 700 : 400;
- final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(
- result.getFontVariationSettings());
- if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(),
- axes.toArray(new FontConfig.Axis[axes.size()]), weight,
- (style & ITALIC) == 0 ? Builder.NORMAL : Builder.ITALIC)) {
+ FontVariationAxis[] axes = null;
+ try {
+ axes = FontVariationAxis.fromFontVariationSettings(
+ result.getFontVariationSettings());
+ } 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)) {
Log.e(TAG, "Error creating font " + request.getQuery());
callback.onTypefaceRequestFailed(
FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
@@ -514,7 +519,7 @@
public static final int ITALIC = 1;
private int mTtcIndex;
- private FontConfig.Axis[] mAxes;
+ private FontVariationAxis[] mAxes;
private AssetManager mAssetManager;
private String mPath;
@@ -682,15 +687,16 @@
* Sets a font variation settings.
*
* @param variationSettings See {@link android.widget.TextView#setFontVariationSettings}.
+ * @throws FontVariationAxis.InvalidFormatException If given string is not a valid font
+ * variation settings format.
*/
- public Builder setFontVariationSettings(@Nullable String variationSettings) {
+ public Builder setFontVariationSettings(@Nullable String variationSettings)
+ throws FontVariationAxis.InvalidFormatException {
checkNotRecycled();
if (mAxes != null) {
throw new IllegalStateException("Font variation settings are already set.");
}
- final List<FontConfig.Axis> axesList = FontListParser.parseFontVariationSettings(
- variationSettings);
- mAxes = axesList.toArray(new FontConfig.Axis[axesList.size()]);
+ mAxes = FontVariationAxis.fromFontVariationSettings(variationSettings);
return this;
}
@@ -699,7 +705,7 @@
*
* @param axes An array of font variation axis tag-value pairs.
*/
- public Builder setFontVariationSettings(@Nullable FontConfig.Axis[] axes) {
+ public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
checkNotRecycled();
if (mAxes != null) {
throw new IllegalStateException("Font variation settings are already set.");
@@ -718,7 +724,7 @@
* @return Unique id for a given AssetManager and asset path.
*/
private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
- @Nullable FontConfig.Axis[] axes) {
+ @Nullable FontVariationAxis[] axes) {
final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
final StringBuilder builder = new StringBuilder();
final int size = pkgs.size();
@@ -731,8 +737,8 @@
builder.append(Integer.toString(ttcIndex));
builder.append("-");
if (axes != null) {
- for (FontConfig.Axis axis : axes) {
- builder.append(Integer.toHexString(axis.getTag()));
+ for (FontVariationAxis axis : axes) {
+ builder.append(axis.getTag());
builder.append("-");
builder.append(Float.toString(axis.getStyleValue()));
}
@@ -865,7 +871,7 @@
/** @hide */
public static Typeface createFromTypefaceWithVariation(Typeface family,
- List<FontConfig.Axis> axes) {
+ List<FontVariationAxis> axes) {
final long ni = family == null ? 0 : family.native_instance;
return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
}
@@ -1162,9 +1168,9 @@
}
private static native long nativeCreateFromTypeface(long native_instance, int style);
- // TODO: clean up: change List<FontConfig.Axis> to FontConfig.Axis[]
+ // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
private static native long nativeCreateFromTypefaceWithVariation(
- long native_instance, List<FontConfig.Axis> axes);
+ long native_instance, List<FontVariationAxis> axes);
private static native long nativeCreateWeightAlias(long native_instance, int weight);
private static native void nativeUnref(long native_instance);
private static native int nativeGetStyle(long native_instance);
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 04864bdc..a491d7e 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -88,9 +88,7 @@
}
@Override
- public
- @Config
- int getChangingConfigurations() {
+ public @Config int getChangingConfigurations() {
return super.getChangingConfigurations()
| mDrawableContainerState.getChangingConfigurations();
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 322e55b..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();
}
/**
@@ -1841,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;
}
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
new file mode 100644
index 0000000..91ec0e8
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -0,0 +1,230 @@
+/*
+ * 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.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+/**
+ * Class that holds information about single font variation axis.
+ */
+public final class FontVariationAxis implements Parcelable {
+ private final int mTag;
+ private final String mTagString;
+ private final float mStyleValue;
+
+ /**
+ * Construct FontVariationAxis.
+ *
+ * The axis tag must contain four ASCII characters. Tag string that are longer or shorter than
+ * four characters, or contains characters outside of U+0020..U+007E are invalid.
+ *
+ * @throws {@link InvalidFormatException} If given tag string is invalid.
+ */
+ public FontVariationAxis(@NonNull String tagString, float styleValue)
+ throws InvalidFormatException {
+ if (!isValidTag(tagString)) {
+ throw new InvalidFormatException("Invalid tag pattern: " + tagString);
+ }
+ mTag = makeTag(tagString);
+ mTagString = tagString;
+ mStyleValue = styleValue;
+ }
+
+ /**
+ * Returns the OpenType style tag value.
+ * @hide
+ */
+ public int getOpenTypeTagValue() {
+ return mTag;
+ }
+
+ /**
+ * Returns the variable font axis tag associated to this axis.
+ */
+ public String getTag() {
+ return mTagString;
+ }
+
+ /**
+ * Returns the style value associated to the given axis for this font.
+ */
+ public float getStyleValue() {
+ return mStyleValue;
+ }
+
+ /**
+ * @hide
+ */
+ public FontVariationAxis(Parcel in) {
+ mTag = in.readInt();
+ mTagString = in.readString();
+ mStyleValue = in.readFloat();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flag) {
+ out.writeInt(mTag);
+ out.writeString(mTagString);
+ out.writeFloat(mStyleValue);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<FontVariationAxis> CREATOR = new Creator<FontVariationAxis>() {
+ @Override
+ public FontVariationAxis createFromParcel(Parcel in) {
+ return new FontVariationAxis(in);
+ }
+
+ @Override
+ public FontVariationAxis[] newArray(int size) {
+ return new FontVariationAxis[size];
+ }
+ };
+
+ /**
+ * Returns a valid font variation setting string for this object.
+ */
+ @Override
+ public @NonNull String toString() {
+ return "'" + mTagString + "' " + Float.toString(mStyleValue);
+ }
+
+ /**
+ * The 'tag' attribute value is read as four character values between U+0020 and U+007E
+ * inclusive.
+ */
+ private static final Pattern TAG_PATTERN = Pattern.compile("[\u0020-\u007E]{4}");
+
+ /**
+ * Returns true if 'tagString' is valid for font variation axis tag.
+ */
+ private static boolean isValidTag(String tagString) {
+ return tagString != null && TAG_PATTERN.matcher(tagString).matches();
+ }
+
+ /**
+ * The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
+ * '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
+ */
+ private static final Pattern STYLE_VALUE_PATTERN =
+ Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))");
+
+ private static boolean isValidValueFormat(String valueString) {
+ return valueString != null && STYLE_VALUE_PATTERN.matcher(valueString).matches();
+ }
+
+ /** @hide */
+ public static int makeTag(String tagString) {
+ final char c1 = tagString.charAt(0);
+ final char c2 = tagString.charAt(1);
+ final char c3 = tagString.charAt(2);
+ final char c4 = tagString.charAt(3);
+ return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
+ }
+
+ /**
+ * An exception indicates that the format of font variation settings is invalid.
+ */
+ public static class InvalidFormatException extends Exception {
+ public InvalidFormatException(String message) {
+ super(message);
+ }
+ };
+
+ /**
+ * Construct FontVariationAxis array from font variation settings.
+ *
+ * The settings string is constructed from multiple pairs of axis tag and style values. The axis
+ * tag must contain four ASCII characters and must be wrapped with single quotes (U+0027) or
+ * double quotes (U+0022). Axis strings that are longer or shorter than four characters, or
+ * contain characters outside of U+0020..U+007E are invalid. If a specified axis name is not
+ * defined in the font, the settings will be ignored.
+ *
+ * <pre>
+ * FontVariationAxis.fromFontVariationSettings("'wdth' 1.0");
+ * FontVariationAxis.fromFontVariationSettings("'AX ' 1.0, 'FB ' 2.0");
+ * </pre>
+ *
+ * @param settings font variation settings.
+ * @return FontVariationAxis[] the array of parsed font variation axis. {@code null} if settings
+ * has no font variation settings.
+ * @throws InvalidFormatException If given string is not a valid font variation settings format.
+ */
+ public static @Nullable FontVariationAxis[] fromFontVariationSettings(@Nullable String settings)
+ throws InvalidFormatException {
+ if (settings == null || settings.isEmpty()) {
+ return null;
+ }
+ final ArrayList<FontVariationAxis> axisList = new ArrayList<>();
+ final int length = settings.length();
+ for (int i = 0; i < length; i++) {
+ final char c = settings.charAt(i);
+ if (Character.isWhitespace(c)) {
+ continue;
+ }
+ if (!(c == '\'' || c == '"') || length < i + 6 || settings.charAt(i + 5) != c) {
+ throw new InvalidFormatException(
+ "Tag should be wrapped with double or single quote: " + settings);
+ }
+ final String tagString = settings.substring(i + 1, i + 5);
+
+ i += 6; // Move to end of tag.
+ int endOfValueString = settings.indexOf(',', i);
+ if (endOfValueString == -1) {
+ endOfValueString = length;
+ }
+ final float value;
+ try {
+ // Float.parseFloat ignores leading/trailing whitespaces.
+ value = Float.parseFloat(settings.substring(i, endOfValueString));
+ } catch (NumberFormatException e) {
+ throw new InvalidFormatException("Failed to parse float string: " + e.getMessage());
+ }
+ axisList.add(new FontVariationAxis(tagString, value));
+ i = endOfValueString;
+ }
+ if (axisList.isEmpty()) {
+ return null;
+ }
+ return axisList.toArray(new FontVariationAxis[0]);
+ }
+
+ /**
+ * Stringify the array of FontVariationAxis.
+ *
+ * @param axes an array of FontVariationAxis.
+ * @return String a valid font variation settings string.
+ */
+ public static @NonNull String toFontVariationSettings(@Nullable FontVariationAxis[] axes) {
+ if (axes == null || axes.length == 0) {
+ return "";
+ }
+ return TextUtils.join(",", axes);
+ }
+}
+
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/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/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index c7bed9b..c82a1f6 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -153,6 +153,7 @@
ANativeWindow_acquire;
ANativeWindow_fromSurface;
ANativeWindow_fromSurfaceTexture; # introduced-arm=13 introduced-mips=13 introduced-x86=13
+ ANativeWindow_toSurface; # introduced=26
ANativeWindow_getFormat;
ANativeWindow_getHeight;
ANativeWindow_getWidth;
diff --git a/native/android/native_window_jni.cpp b/native/android/native_window_jni.cpp
index dc30405..859c550 100644
--- a/native/android/native_window_jni.cpp
+++ b/native/android/native_window_jni.cpp
@@ -20,6 +20,7 @@
#include <android/native_window.h>
#include <system/window.h>
+#include <gui/Surface.h>
#include <utils/StrongPointer.h>
#include <android_runtime/android_view_Surface.h>
@@ -33,3 +34,11 @@
}
return win.get();
}
+
+jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) {
+ if (window == NULL) {
+ return NULL;
+ }
+ sp<Surface> surface = static_cast<Surface*>(window);
+ return android_view_Surface_createFromSurface(env, surface);
+}
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/bluetooth/BluetoothDiscoverableTimeoutReceiver.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
index 69b45e5..9ea7a4a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
@@ -71,14 +71,15 @@
@Override
public void onReceive(Context context, Intent intent) {
+ if (intent.getAction() == null || !intent.getAction().equals(INTENT_DISCOVERABLE_TIMEOUT)) {
+ return;
+ }
LocalBluetoothAdapter localBluetoothAdapter = LocalBluetoothAdapter.getInstance();
-
- if(localBluetoothAdapter != null &&
+ if(localBluetoothAdapter != null &&
localBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
Log.d(TAG, "Disable discoverable...");
-
localBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
- } else {
+ } else {
Log.e(TAG, "localBluetoothAdapter is NULL!!");
}
}
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/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 4b2c20f..5b9d95d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2014 The Android Open Source Project
*
@@ -358,9 +359,8 @@
@Override
public void onClick(View widget) {
final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mDialog.dismiss();
- mContext.startActivity(intent);
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
}
@Override
@@ -373,9 +373,8 @@
@Override
public void onClick(View widget) {
final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mDialog.dismiss();
- mContext.startActivity(intent);
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 1c71da0..3a43d30 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -355,9 +355,10 @@
rti.firstActiveTime = rti.lastActiveTime = i;
if (i % 2 == 0) {
rti.taskDescription = new ActivityManager.TaskDescription(description,
- Bitmap.createBitmap(mDummyIcon), null,
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()));
+ Bitmap.createBitmap(mDummyIcon), null,
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+ 0, 0);
} else {
rti.taskDescription = new ActivityManager.TaskDescription();
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 97506e6..0ee3e19 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -58,6 +58,7 @@
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
@@ -108,9 +109,6 @@
private static final Interpolator IME_ADJUST_INTERPOLATOR =
new PathInterpolator(0.2f, 0f, 0.1f, 1f);
- private static final long ONE_MS_IN_NS = 1000000;
- private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
-
private static final int MSG_RESIZE_STACK = 0;
private DividerHandleView mHandle;
@@ -161,12 +159,7 @@
private boolean mHomeStackResizable;
private boolean mAdjustedForIme;
private DividerState mState;
-
- /**
- * The offset between vsync-app and vsync-surfaceflinger. See
- * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
- */
- private long mSurfaceFlingerOffsetMs;
+ private SurfaceFlingerVsyncChoreographer mSfChoreographer;
private final Handler mHandler = new Handler() {
@Override
@@ -319,7 +312,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
- mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs();
+ mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, getDisplay());
}
@Override
@@ -328,25 +321,6 @@
EventBus.getDefault().unregister(this);
}
- /**
- * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
- * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the
- * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after,
- * which leads to jank. Figure out this difference here and then post all the touch/animation
- * events to start being processed at vsync-sf.
- *
- * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
- */
- private long calculateAppSurfaceFlingerVsyncOffsetMs() {
- Display display = getDisplay();
-
- // Calculate vsync offset from SurfaceFlinger.
- // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
- long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
- long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
- return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
- }
-
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (mStableInsets.left != insets.getStableInsetLeft()
@@ -630,8 +604,8 @@
delay = endDelay;
} else if (mCancelled) {
delay = 0;
- } else if (mSurfaceFlingerOffsetMs != 0) {
- delay = mSurfaceFlingerOffsetMs;
+ } else if (mSfChoreographer.getSurfaceFlingerOffsetMs() > 0) {
+ delay = mSfChoreographer.getSurfaceFlingerOffsetMs();
}
if (delay == 0) {
endAction.run();
@@ -916,14 +890,10 @@
}
public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) {
- if (mSurfaceFlingerOffsetMs != 0) {
- Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
- taskSnapTarget);
- message.setAsynchronous(true);
- mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs);
- } else {
- resizeStack(position, taskPosition, taskSnapTarget);
- }
+ Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
+ taskSnapTarget);
+ message.setAsynchronous(true);
+ mSfChoreographer.scheduleAtSfVsync(mHandler, message);
}
public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
diff --git a/preloaded-classes b/preloaded-classes
index a72a042..892c593 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1817,7 +1817,6 @@
android.text.FontConfig$Family$1
android.text.FontConfig$Font
android.text.FontConfig$Font$1
-android.text.FontManager
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index f6d91f4..c4a2831 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -165,6 +165,14 @@
// Package: android
NOTE_NET_LIMIT_SNOOZED = 36;
+ // Inform the user they need to sign in to an account
+ // Package: android, and others
+ NOTE_ACCOUNT_REQUIRE_SIGNIN = 37;
+
+ // Inform the user that there has been a permission request for an account
+ // Package: android
+ NOTE_ACCOUNT_CREDENTIAL_PERMISSION = 38;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
@@ -216,9 +224,5 @@
// Notify the user that data or apps are being moved to external storage.
// Package: com.android.systemui
NOTE_STORAGE_MOVE = 0x534d4f56;
-
- // Account Manager allocates IDs sequentially, starting here.
- // Package: android
- ACCOUNT_MANAGER_BASE = 0x70000000;
}
}
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/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 087c248..1968d2e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -585,17 +585,12 @@
result = mEnabledServicesForFeedbackTempList;
result.clear();
List<Service> services = userState.mBoundServices;
- while (feedbackType != 0) {
- final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
- feedbackType &= ~feedbackTypeBit;
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- Service service = services.get(i);
- // Don't report the UIAutomation (fake service)
- if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
- && (service.mFeedbackType & feedbackTypeBit) != 0) {
- result.add(service.mAccessibilityServiceInfo);
- }
+ for (int serviceCount = services.size(), i = 0; i < serviceCount; ++i) {
+ Service service = services.get(i);
+ // Don't report the UIAutomation (fake service)
+ if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
+ && (service.mFeedbackType & feedbackType) != 0) {
+ result.add(service.mAccessibilityServiceInfo);
}
}
}
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 099f557..8003d21 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -39,8 +39,8 @@
LOCAL_JACK_FLAGS := \
-D jack.transformations.boost-locked-region-priority=true \
- -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService \
- -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection \
- -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection
+ -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService,com.android.server.wm.WindowHashMap \
+ -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection,com.android.server.wm.WindowManagerService\#boostPriorityForLockedSection \
+ -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection,com.android.server.wm.WindowManagerService\#resetPriorityAfterLockedSection
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/FontManagerService.java b/services/core/java/com/android/server/FontManagerService.java
deleted file mode 100644
index f172647..0000000
--- a/services/core/java/com/android/server/FontManagerService.java
+++ /dev/null
@@ -1,100 +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 com.android.server;
-
-import android.content.Context;
-import android.graphics.FontListParser;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.text.FontConfig;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.font.IFontManager;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-public class FontManagerService extends IFontManager.Stub {
- private static final String TAG = "FontManagerService";
- private static final String FONTS_CONFIG = "/system/etc/fonts.xml";
- private static final String SYSTEM_FONT_DIR = "/system/fonts/";
-
- @GuardedBy("mLock")
- private FontConfig mConfig;
- private final Object mLock = new Object();
-
- public static final class Lifecycle extends SystemService {
- private final FontManagerService mService;
-
- public Lifecycle(Context context) {
- super(context);
- mService = new FontManagerService();
- }
-
- @Override
- public void onStart() {
- try {
- publishBinderService(Context.FONT_SERVICE, mService);
- } catch (Throwable t) {
- // Starting this service is not critical to the running of this device and should
- // therefore not crash the device. If it fails, log the error and continue.
- Slog.e(TAG, "Could not start the FontManagerService.", t);
- }
- }
- }
-
- @Override
- public FontConfig getSystemFonts() {
- synchronized (mLock) {
- if (mConfig != null) {
- return mConfig;
- }
-
- mConfig = loadFromSystem();
- if (mConfig == null) {
- return null;
- }
-
- for (FontConfig.Family family : mConfig.getFamilies()) {
- for (FontConfig.Font font : family.getFonts()) {
- File fontFile = new File(SYSTEM_FONT_DIR, font.getFontName());
- font.setUri(Uri.fromFile(fontFile));
- }
- }
-
- return mConfig;
- }
- }
-
- private FontConfig loadFromSystem() {
- File configFilename = new File(FONTS_CONFIG);
- try {
- FileInputStream fontsIn = new FileInputStream(configFilename);
- return FontListParser.parse(fontsIn);
- } catch (IOException | XmlPullParserException e) {
- Slog.e(TAG, "Error opening " + configFilename, e);
- }
- return null;
- }
-
- public FontManagerService() {
- }
-}
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/ThreadPriorityBooster.java b/services/core/java/com/android/server/ThreadPriorityBooster.java
new file mode 100644
index 0000000..17965d0
--- /dev/null
+++ b/services/core/java/com/android/server/ThreadPriorityBooster.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import android.os.Process;
+
+/**
+ * Utility class to boost threads in sections where important locks are held.
+ */
+public class ThreadPriorityBooster {
+
+ private final int mBoostToPriority;
+ private final int mLockGuardIndex;
+
+ private final ThreadLocal<PriorityState> mThreadState = new ThreadLocal<PriorityState>() {
+ @Override protected PriorityState initialValue() {
+ return new PriorityState();
+ }
+ };
+
+ public ThreadPriorityBooster(int boostToPriority, int lockGuardIndex) {
+ mBoostToPriority = boostToPriority;
+ mLockGuardIndex = lockGuardIndex;
+ }
+
+ public void boost() {
+ final int tid = Process.myTid();
+ final int prevPriority = Process.getThreadPriority(tid);
+ PriorityState state = mThreadState.get();
+ if (state.regionCounter == 0 && prevPriority > mBoostToPriority) {
+ state.prevPriority = prevPriority;
+ Process.setThreadPriority(tid, mBoostToPriority);
+ }
+ state.regionCounter++;
+ if (LockGuard.ENABLED) {
+ LockGuard.guard(mLockGuardIndex);
+ }
+ }
+
+ public void reset() {
+ PriorityState state = mThreadState.get();
+ state.regionCounter--;
+ if (state.regionCounter == 0 && state.prevPriority > mBoostToPriority) {
+ Process.setThreadPriority(Process.myTid(), state.prevPriority);
+ }
+ }
+
+ private static class PriorityState {
+
+ /**
+ * Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
+ * the current thread is currently in. When it drops down to zero, we will no longer boost
+ * the thread's priority.
+ */
+ int regionCounter;
+
+ /**
+ * The thread's previous priority before boosting.
+ */
+ int prevPriority;
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d996ee2..e560d32 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -123,7 +123,6 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -191,17 +190,14 @@
}
private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
- private final AtomicInteger mNotificationIds =
- new AtomicInteger(SystemMessage.ACCOUNT_MANAGER_BASE);
static class UserAccounts {
private final int userId;
final AccountsDb accountsDb;
- private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
- credentialsPermissionNotificationIds =
- new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
- private final HashMap<Account, Integer> signinRequiredNotificationIds =
- new HashMap<Account, Integer>();
+ private final HashMap<Pair<Pair<Account, String>, Integer>, NotificationId>
+ credentialsPermissionNotificationIds = new HashMap<>();
+ private final HashMap<Account, NotificationId> signinRequiredNotificationIds
+ = new HashMap<>();
final Object cacheLock = new Object();
final Object dbLock = new Object(); // if needed, dbLock must be obtained before cacheLock
/** protected by the {@link #cacheLock} */
@@ -1863,12 +1859,12 @@
*/
cancelNotification(
getSigninRequiredNotificationId(accounts, accountToRename),
- new UserHandle(accounts.userId));
+ new UserHandle(accounts.userId));
synchronized(accounts.credentialsPermissionNotificationIds) {
for (Pair<Pair<Account, String>, Integer> pair:
accounts.credentialsPermissionNotificationIds.keySet()) {
if (accountToRename.equals(pair.first.first)) {
- int id = accounts.credentialsPermissionNotificationIds.get(pair);
+ NotificationId id = accounts.credentialsPermissionNotificationIds.get(pair);
cancelNotification(id, new UserHandle(accounts.userId));
}
}
@@ -2021,7 +2017,7 @@
for (Pair<Pair<Account, String>, Integer> pair:
accounts.credentialsPermissionNotificationIds.keySet()) {
if (account.equals(pair.first.first)) {
- int id = accounts.credentialsPermissionNotificationIds.get(pair);
+ NotificationId id = accounts.credentialsPermissionNotificationIds.get(pair);
cancelNotification(id, user);
}
}
@@ -2912,8 +2908,8 @@
// the intent from a non-Activity context. This is the default behavior.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
- intent.addCategory(String.valueOf(getCredentialPermissionNotificationId(account,
- authTokenType, uid) + (packageName != null ? packageName : "")));
+ intent.addCategory(getCredentialPermissionNotificationId(account,
+ authTokenType, uid).mTag + (packageName != null ? packageName : ""));
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
@@ -2922,33 +2918,39 @@
return intent;
}
- private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
- int uid) {
- Integer id;
+ private NotificationId getCredentialPermissionNotificationId(Account account,
+ String authTokenType, int uid) {
+ NotificationId nId;
UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
synchronized (accounts.credentialsPermissionNotificationIds) {
final Pair<Pair<Account, String>, Integer> key =
new Pair<Pair<Account, String>, Integer>(
new Pair<Account, String>(account, authTokenType), uid);
- id = accounts.credentialsPermissionNotificationIds.get(key);
- if (id == null) {
- id = mNotificationIds.incrementAndGet();
- accounts.credentialsPermissionNotificationIds.put(key, id);
+ nId = accounts.credentialsPermissionNotificationIds.get(key);
+ if (nId == null) {
+ String tag = TAG + ":" + SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION
+ + ":" + account.hashCode() + ":" + authTokenType.hashCode();
+ int id = SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION;
+ nId = new NotificationId(tag, id);
+ accounts.credentialsPermissionNotificationIds.put(key, nId);
}
}
- return id;
+ return nId;
}
- private Integer getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
- Integer id;
+ private NotificationId getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
+ NotificationId nId;
synchronized (accounts.signinRequiredNotificationIds) {
- id = accounts.signinRequiredNotificationIds.get(account);
- if (id == null) {
- id = mNotificationIds.incrementAndGet();
- accounts.signinRequiredNotificationIds.put(account, id);
+ nId = accounts.signinRequiredNotificationIds.get(account);
+ if (nId == null) {
+ String tag = TAG + ":" + SystemMessage.NOTE_ACCOUNT_REQUIRE_SIGNIN
+ + ":" + account.hashCode();
+ int id = SystemMessage.NOTE_ACCOUNT_REQUIRE_SIGNIN;
+ nId = new NotificationId(tag, id);
+ accounts.signinRequiredNotificationIds.put(account, nId);
}
}
- return id;
+ return nId;
}
@Override
@@ -4931,8 +4933,8 @@
createNoCredentialsPermissionNotification(account, intent, packageName, userId);
} else {
Context contextForUser = getContextForUser(new UserHandle(userId));
- final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
- intent.addCategory(String.valueOf(notificationId));
+ final NotificationId id = getSigninRequiredNotificationId(accounts, account);
+ intent.addCategory(id.mTag);
final String notificationTitleFormat =
contextForUser.getText(R.string.notification_title).toString();
@@ -4948,21 +4950,21 @@
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
null, new UserHandle(userId)))
.build();
- installNotification(notificationId, n, packageName, userId);
+ installNotification(id, n, packageName, userId);
}
} finally {
restoreCallingIdentity(identityToken);
}
}
- private void installNotification(int notificationId, final Notification notification,
+ private void installNotification(NotificationId id, final Notification notification,
String packageName, int userId) {
final long token = clearCallingIdentity();
try {
INotificationManager notificationManager = mInjector.getNotificationManager();
try {
- notificationManager.enqueueNotificationWithTag(packageName, packageName, null,
- notificationId, notification, new int[1], userId);
+ notificationManager.enqueueNotificationWithTag(packageName, packageName,
+ id.mTag, id.mId, notification, new int[1], userId);
} catch (RemoteException e) {
/* ignore - local call */
}
@@ -4971,15 +4973,15 @@
}
}
- private void cancelNotification(int id, UserHandle user) {
+ private void cancelNotification(NotificationId id, UserHandle user) {
cancelNotification(id, mContext.getPackageName(), user);
}
- private void cancelNotification(int id, String packageName, UserHandle user) {
+ private void cancelNotification(NotificationId id, String packageName, UserHandle user) {
long identityToken = clearCallingIdentity();
try {
INotificationManager service = mInjector.getNotificationManager();
- service.cancelNotificationWithTag(packageName, null, id, user.getIdentifier());
+ service.cancelNotificationWithTag(packageName, id.mTag, id.mId, user.getIdentifier());
} catch (RemoteException e) {
/* ignore - local call */
} finally {
@@ -5893,4 +5895,14 @@
return NotificationManager.getService();
}
}
+
+ private class NotificationId {
+ final String mTag;
+ private final int mId;
+
+ NotificationId(String tag, int type) {
+ mTag = tag;
+ mId = type;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4c747a1..19fc2b8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,12 +17,12 @@
package com.android.server.am;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
+import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -42,13 +42,49 @@
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.Process.BLUETOOTH_UID;
+import static android.os.Process.FIRST_APPLICATION_UID;
+import static android.os.Process.FIRST_ISOLATED_UID;
+import static android.os.Process.LAST_ISOLATED_UID;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.PHONE_UID;
import static android.os.Process.PROC_CHAR;
import static android.os.Process.PROC_OUT_LONG;
import static android.os.Process.PROC_PARENS;
import static android.os.Process.PROC_SPACE_TERM;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
+import static android.os.Process.ProcessStartResult;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SCHED_FIFO;
+import static android.os.Process.SCHED_OTHER;
+import static android.os.Process.SCHED_RESET_ON_FORK;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SIGNAL_QUIT;
+import static android.os.Process.SIGNAL_USR1;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE;
+import static android.os.Process.THREAD_GROUP_DEFAULT;
+import static android.os.Process.THREAD_GROUP_TOP_APP;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
+import static android.os.Process.getFreeMemory;
+import static android.os.Process.getThreadPriority;
+import static android.os.Process.getTotalMemory;
+import static android.os.Process.isThreadInProcess;
+import static android.os.Process.killProcess;
+import static android.os.Process.killProcessQuiet;
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
+import static android.os.Process.readProcFile;
+import static android.os.Process.removeAllProcessGroups;
+import static android.os.Process.sendSignal;
+import static android.os.Process.setProcessGroup;
+import static android.os.Process.setThreadPriority;
+import static android.os.Process.setThreadScheduler;
+import static android.os.Process.startWebView;
+import static android.os.Process.zygoteProcess;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -323,7 +359,6 @@
import android.view.View;
import android.view.WindowManager;
-import com.android.internal.notification.SystemNotificationChannels;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -341,6 +376,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.IResultReceiver;
@@ -367,6 +403,7 @@
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
+import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
@@ -409,7 +446,6 @@
import java.util.concurrent.atomic.AtomicLong;
import dalvik.system.VMRuntime;
-
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
@@ -547,7 +583,7 @@
// Maximum number of persisted Uri grants a package is allowed
static final int MAX_PERSISTED_URI_GRANTS = 128;
- static final int MY_PID = Process.myPid();
+ static final int MY_PID = myPid();
static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -680,13 +716,13 @@
if (mTopAppVrThreadTid > 0) {
// Ensure that when entering persistent VR mode the last top-app loses
// SCHED_FIFO.
- Process.setThreadScheduler(mTopAppVrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(mTopAppVrThreadTid, SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
} else if (mPersistentVrThreadTid > 0) {
// Ensure that when leaving persistent VR mode we reschedule the high priority
// persistent thread.
- Process.setThreadScheduler(mPersistentVrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(mPersistentVrThreadTid, SCHED_OTHER, 0);
mPersistentVrThreadTid = 0;
}
}
@@ -773,42 +809,15 @@
&& !mKeyguardController.isKeyguardShowing();
}
- private static final class PriorityState {
- // Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
- // the current thread is currently in. When it drops down to zero, we will no longer boost
- // the thread's priority.
- private int regionCounter = 0;
-
- // The thread's previous priority before boosting.
- private int prevPriority = Integer.MIN_VALUE;
- }
-
- static ThreadLocal<PriorityState> sThreadPriorityState = new ThreadLocal<PriorityState>() {
- @Override protected PriorityState initialValue() {
- return new PriorityState();
- }
- };
+ private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+ THREAD_PRIORITY_FOREGROUND, LockGuard.INDEX_ACTIVITY);
static void boostPriorityForLockedSection() {
- int tid = Process.myTid();
- int prevPriority = Process.getThreadPriority(tid);
- PriorityState state = sThreadPriorityState.get();
- if (state.regionCounter == 0 && prevPriority > -2) {
- state.prevPriority = prevPriority;
- Process.setThreadPriority(tid, -2);
- }
- state.regionCounter++;
- if (LockGuard.ENABLED) {
- LockGuard.guard(LockGuard.INDEX_ACTIVITY);
- }
+ sThreadPriorityBooster.boost();
}
static void resetPriorityAfterLockedSection() {
- PriorityState state = sThreadPriorityState.get();
- state.regionCounter--;
- if (state.regionCounter == 0 && state.prevPriority > -2) {
- Process.setThreadPriority(Process.myTid(), state.prevPriority);
- }
+ sThreadPriorityBooster.reset();
}
public class PendingAssistExtras extends Binder implements Runnable {
@@ -889,7 +898,7 @@
* Non-persistent app uid whitelist for background restrictions
*/
int[] mBackgroundUidWhitelist = new int[] {
- Process.BLUETOOTH_UID
+ BLUETOOTH_UID
};
/**
@@ -2467,12 +2476,12 @@
if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
try {
if (mVrState == VR_MODE) {
- Process.setThreadScheduler(proc.vrThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(proc.vrThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
mTopAppVrThreadTid = proc.vrThreadTid;
} else {
- Process.setThreadScheduler(proc.vrThreadTid,
- Process.SCHED_OTHER, 0);
+ setThreadScheduler(proc.vrThreadTid,
+ SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
} catch (IllegalArgumentException e) {
@@ -2529,7 +2538,7 @@
final List<ProcessCpuTracker.Stats> stats;
synchronized (mProcessCpuTracker) {
stats = mProcessCpuTracker.getStats( (st)-> {
- return st.vsize > 0 && st.uid < Process.FIRST_APPLICATION_UID;
+ return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID;
});
}
final int N = stats.size();
@@ -2780,7 +2789,7 @@
com.android.internal.R.bool.config_permissionReviewRequired);
mHandlerThread = new ServiceThread(TAG,
- android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+ THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
mUiHandler = mInjector.getUiHandler(this);
@@ -2801,7 +2810,7 @@
/* static; one-time init here */
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
- android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
+ THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
}
@@ -2919,7 +2928,7 @@
}
private void start() {
- Process.removeAllProcessGroups();
+ removeAllProcessGroups();
mProcessCpuThread.start();
mBatteryStatsService.publish(mContext);
@@ -3127,7 +3136,7 @@
synchronized (this) {
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
AppOpsManager.OP_NONE, null, false, false,
- -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ -1, SYSTEM_UID, UserHandle.USER_ALL);
}
}
@@ -3399,7 +3408,7 @@
if (lrui >= 0) {
if (!app.killed) {
Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
- Process.killProcessQuiet(app.pid);
+ killProcessQuiet(app.pid);
killProcessGroup(app.uid, app.pid);
}
if (lrui <= mLruProcessActivityStart) {
@@ -3608,7 +3617,7 @@
}
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
- if (uid == Process.SYSTEM_UID) {
+ if (uid == SYSTEM_UID) {
// The system gets to run in any process. If there are multiple
// processes with the same uid, just pick the first (this
// should never happen).
@@ -3674,7 +3683,7 @@
// closest thing to a parent's uid is SYSTEM_UID.
// The only important thing here is to keep AI.uid != PR.uid, in order to trigger
// the |isolated| logic in the ProcessRecord constructor.
- info.uid = Process.SYSTEM_UID;
+ info.uid = SYSTEM_UID;
info.processName = processName;
info.className = entryPoint;
info.packageName = "android";
@@ -3969,9 +3978,9 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
- Process.ProcessStartResult startResult;
+ ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
- startResult = Process.startWebView(entryPoint,
+ startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, entryPointArgs);
@@ -4208,7 +4217,7 @@
}
void enforceShellRestriction(String restriction, int userHandle) {
- if (Binder.getCallingUid() == Process.SHELL_UID) {
+ if (Binder.getCallingUid() == SHELL_UID) {
if (userHandle < 0 || mUserController.hasUserRestriction(restriction, userHandle)) {
throw new SecurityException("Shell does not have permission to access user "
+ userHandle);
@@ -4574,7 +4583,7 @@
if (sourceRecord.app == null) {
throw new SecurityException("Called without a process attached to activity");
}
- if (UserHandle.getAppId(sourceRecord.app.uid) != Process.SYSTEM_UID) {
+ if (UserHandle.getAppId(sourceRecord.app.uid) != SYSTEM_UID) {
// This is still okay, as long as this activity is running under the
// uid of the original calling activity.
if (sourceRecord.app.uid != sourceRecord.launchedFromUid) {
@@ -5426,7 +5435,7 @@
if (!app.killed) {
if (!fromBinderDied) {
- Process.killProcessQuiet(pid);
+ killProcessQuiet(pid);
}
killProcessGroup(app.uid, pid);
app.killed = true;
@@ -5521,7 +5530,7 @@
}
public void dumpWithTimeout(int pid) {
- Process.sendSignal(pid, Process.SIGNAL_QUIT);
+ sendSignal(pid, SIGNAL_QUIT);
synchronized (this) {
try {
wait(TRACE_DUMP_TIMEOUT_MS); // Wait for traces file to be closed.
@@ -5776,7 +5785,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(Intent.EXTRA_UID, pkgUidF);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
- broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+ broadcastIntentInPackage("android", SYSTEM_UID, intent,
null, null, 0, null, null, null, null, false, false, userIdF);
if (observer != null) {
@@ -5994,7 +6003,7 @@
public void addPackageDependency(String packageName) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
- if (callingPid == Process.myPid()) {
+ if (callingPid == myPid()) {
// Yeah, um, no.
return;
}
@@ -6026,7 +6035,7 @@
}
int callerUid = Binder.getCallingUid();
// Only the system server can kill an application
- if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
+ if (UserHandle.getAppId(callerUid) == SYSTEM_UID) {
// Post an aysnc message to kill the application
Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
msg.arg1 = appId;
@@ -6053,7 +6062,7 @@
synchronized (this) {
// Only allow this from foreground processes, so that background
// applications can't abuse it to prevent system UI from being shown.
- if (uid >= Process.FIRST_APPLICATION_UID) {
+ if (uid >= FIRST_APPLICATION_UID) {
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(pid);
@@ -6084,7 +6093,7 @@
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
AppOpsManager.OP_NONE, null, false, false,
- -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ -1, SYSTEM_UID, UserHandle.USER_ALL);
}
@Override
@@ -6150,7 +6159,7 @@
int callerUid = Binder.getCallingUid();
// Only the system server can kill an application
- if (callerUid == Process.SYSTEM_UID) {
+ if (callerUid == SYSTEM_UID) {
synchronized (this) {
ProcessRecord app = getProcessRecordLocked(processName, uid, true);
if (app != null && app.thread != null) {
@@ -6186,7 +6195,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
+ null, false, false, MY_PID, SYSTEM_UID, UserHandle.getUserId(uid));
}
@@ -6703,7 +6712,7 @@
+ " (IApplicationThread " + thread + "); dropping process");
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
- Process.killProcessQuiet(pid);
+ killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
} else {
try {
@@ -6811,7 +6820,7 @@
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
if (mBackupTarget != null && mBackupAppName.equals(processName)) {
- isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
+ isRestrictedBackupMode = mBackupTarget.appInfo.uid >= FIRST_APPLICATION_UID
&& ((mBackupTarget.backupMode == BackupRecord.RESTORE)
|| (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
@@ -7034,7 +7043,7 @@
@Override
public void showBootMessage(final CharSequence msg, final boolean always) {
- if (Binder.getCallingUid() != Process.myUid()) {
+ if (Binder.getCallingUid() != myUid()) {
throw new SecurityException();
}
mWindowManager.showBootMessage(msg, always);
@@ -7071,7 +7080,7 @@
ArraySet<String> completedIsas = new ArraySet<String>();
for (String abi : Build.SUPPORTED_ABIS) {
- Process.zygoteProcess.establishZygoteConnectionForAbi(abi);
+ zygoteProcess.establishZygoteConnectionForAbi(abi);
final String instructionSet = VMRuntime.getInstructionSet(abi);
if (!completedIsas.contains(instructionSet)) {
try {
@@ -7412,7 +7421,7 @@
userId = UserHandle.USER_CURRENT;
}
try {
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
if (!UserHandle.isSameApp(callingUid, uid)) {
@@ -8679,7 +8688,7 @@
// Third... does the caller itself have permission to access
// this uri?
final int callingAppId = UserHandle.getAppId(callingUid);
- if ((callingAppId == Process.SYSTEM_UID) || (callingAppId == Process.ROOT_UID)) {
+ if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
// Exempted authority for cropping user photos in Settings app
} else {
@@ -9165,7 +9174,7 @@
throw new IllegalArgumentException("Unknown owner: " + token);
}
if (fromUid != Binder.getCallingUid()) {
- if (Binder.getCallingUid() != Process.myUid()) {
+ if (Binder.getCallingUid() != myUid()) {
// Only system code can grant URI permissions on behalf
// of other users.
throw new SecurityException("nice try");
@@ -9549,8 +9558,8 @@
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
final long cachedAppMem = mProcessList.getMemLevel(ProcessList.CACHED_APP_MIN_ADJ);
- outInfo.availMem = Process.getFreeMemory();
- outInfo.totalMem = Process.getTotalMemory();
+ outInfo.availMem = getFreeMemory();
+ outInfo.totalMem = getTotalMemory();
outInfo.threshold = homeAppMem;
outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((cachedAppMem-homeAppMem)/2));
outInfo.hiddenAppThreshold = cachedAppMem;
@@ -10693,7 +10702,7 @@
@Override
public void updateDeviceOwner(String packageName) {
final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
throw new SecurityException("updateDeviceOwner called from non-system process");
}
synchronized (this) {
@@ -10704,7 +10713,7 @@
@Override
public void updateLockTaskPackages(int userId, String[] packages) {
final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
"updateLockTaskPackages()");
}
@@ -10727,7 +10736,7 @@
// is initiated by system after the pinning request was shown and locked mode is initiated
// by an authorized app directly
final int callingUid = Binder.getCallingUid();
- boolean isSystemInitiated = callingUid == Process.SYSTEM_UID;
+ boolean isSystemInitiated = callingUid == SYSTEM_UID;
long ident = Binder.clearCallingIdentity();
try {
if (!isSystemInitiated) {
@@ -11206,7 +11215,7 @@
proc.procStatFile = "/proc/" + proc.pid + "/stat";
}
mProcessStateStatsLongs[0] = 0;
- if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+ if (!readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
mProcessStateStatsLongs, null)) {
if (DEBUG_OOM_ADJ) Slog.d(TAG, "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
return false;
@@ -11908,7 +11917,7 @@
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
- ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
+ ProcessRecord app = mProcessNames.get("system", SYSTEM_UID);
providers = generateApplicationProvidersLocked(app);
if (providers != null) {
for (int i=providers.size()-1; i>=0; i--) {
@@ -12081,11 +12090,11 @@
int uid = info.uid;
if (isolated) {
if (isolatedUid == 0) {
- int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
+ int stepsLeft = LAST_ISOLATED_UID - FIRST_ISOLATED_UID + 1;
while (true) {
- if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID
- || mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) {
- mNextIsolatedProcessUid = Process.FIRST_ISOLATED_UID;
+ if (mNextIsolatedProcessUid < FIRST_ISOLATED_UID
+ || mNextIsolatedProcessUid > LAST_ISOLATED_UID) {
+ mNextIsolatedProcessUid = FIRST_ISOLATED_UID;
}
uid = UserHandle.getUid(userId, mNextIsolatedProcessUid);
mNextIsolatedProcessUid++;
@@ -13274,7 +13283,7 @@
synchronized (this) {
// Disable any existing VR thread.
if (mTopAppVrThreadTid > 0) {
- Process.setThreadScheduler(mTopAppVrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(mTopAppVrThreadTid, SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
@@ -13298,15 +13307,15 @@
*/
private int updateVrThreadLocked(ProcessRecord proc, int lastTid, int pid, int tid) {
// ensure the tid belongs to the process
- if (!Process.isThreadInProcess(pid, tid)) {
+ if (!isThreadInProcess(pid, tid)) {
throw new IllegalArgumentException("VR thread does not belong to process");
}
// reset existing VR thread to CFS if this thread still exists and belongs to
// the calling process
- if (lastTid != 0 && Process.isThreadInProcess(pid, lastTid)) {
+ if (lastTid != 0 && isThreadInProcess(pid, lastTid)) {
try {
- Process.setThreadScheduler(lastTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(lastTid, SCHED_OTHER, 0);
} catch (IllegalArgumentException e) {
// Ignore this. Only occurs in race condition where previous VR thread
// was destroyed during this method call.
@@ -13317,8 +13326,8 @@
try {
if ((proc == null || proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP)
&& tid > 0) {
- Process.setThreadScheduler(tid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(tid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
}
return tid;
} catch (IllegalArgumentException e) {
@@ -13337,7 +13346,7 @@
proc = mPidsSelfLocked.get(pid);
if (proc != null && proc.renderThreadTid == 0 && tid > 0) {
// ensure the tid belongs to the process
- if (!Process.isThreadInProcess(pid, tid)) {
+ if (!isThreadInProcess(pid, tid)) {
throw new IllegalArgumentException(
"Render thread does not belong to process");
}
@@ -13349,10 +13358,10 @@
if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
if (mUseFifoUiScheduling) {
- Process.setThreadScheduler(proc.renderThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(proc.renderThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} else {
- Process.setThreadPriority(proc.renderThreadTid, -10);
+ setThreadPriority(proc.renderThreadTid, -10);
}
}
} else {
@@ -13513,7 +13522,7 @@
if (sender == null) {
uid = sourceUid;
} else {
- uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+ uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
}
BatteryStatsImpl.Uid.Pkg pkg =
stats.getPackageStatsLocked(sourceUid >= 0 ? sourceUid : uid,
@@ -13536,7 +13545,7 @@
if (sender == null) {
uid = sourceUid;
} else {
- uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+ uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
}
mBatteryStatsService.noteAlarmStart(tag, sourceUid >= 0 ? sourceUid : uid);
}
@@ -13555,14 +13564,14 @@
if (sender == null) {
uid = sourceUid;
} else {
- uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+ uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
}
mBatteryStatsService.noteAlarmFinish(tag, sourceUid >= 0 ? sourceUid : uid);
}
}
public boolean killPids(int[] pids, String pReason, boolean secure) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killPids only available to the system");
}
String reason = (pReason == null) ? "Unknown" : pReason;
@@ -13628,7 +13637,7 @@
@Override
public boolean killProcessesBelowForeground(String reason) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killProcessesBelowForeground() only available to system");
}
@@ -13636,7 +13645,7 @@
}
private boolean killProcessesBelowAdj(int belowAdj, String reason) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (Binder.getCallingUid() != SYSTEM_UID) {
throw new SecurityException("killProcessesBelowAdj() only available to system");
}
@@ -13713,7 +13722,7 @@
Log.i(TAG, "Shutting down activity manager...");
shutdown(10000);
Log.i(TAG, "Shutdown complete, restarting!");
- Process.killProcess(Process.myPid());
+ killProcess(myPid());
System.exit(10);
}
};
@@ -14057,7 +14066,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID,
+ null, false, false, MY_PID, SYSTEM_UID,
currentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -14071,7 +14080,7 @@
}
}, 0, null, null,
new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
@@ -16716,22 +16725,22 @@
private final long[] getKsmInfo() {
long[] longOut = new long[4];
final int[] SINGLE_LONG_FORMAT = new int[] {
- Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
+ PROC_SPACE_TERM| PROC_OUT_LONG
};
long[] longTmp = new long[1];
- Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
+ readProcFile("/sys/kernel/mm/ksm/pages_shared",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_SHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
longTmp[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
+ readProcFile("/sys/kernel/mm/ksm/pages_sharing",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_SHARING] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
longTmp[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
+ readProcFile("/sys/kernel/mm/ksm/pages_unshared",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_UNSHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
longTmp[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
+ readProcFile("/sys/kernel/mm/ksm/pages_volatile",
SINGLE_LONG_FORMAT, null, longTmp, null);
longOut[KSM_VOLATILE] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
return longOut;
@@ -18007,7 +18016,7 @@
String className, int flags) {
boolean result = false;
// For apps that don't have pre-defined UIDs, check for permission
- if (UserHandle.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) {
+ if (UserHandle.getAppId(aInfo.uid) >= FIRST_APPLICATION_UID) {
if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
if (ActivityManager.checkUidPermission(
INTERACT_ACROSS_USERS,
@@ -18026,7 +18035,7 @@
result = true;
} else if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
// Phone app and persistent apps are allowed to export singleuser providers.
- result = UserHandle.isSameApp(aInfo.uid, Process.PHONE_UID)
+ result = UserHandle.isSameApp(aInfo.uid, PHONE_UID)
|| (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0;
}
if (DEBUG_MU) Slog.v(TAG_MU,
@@ -18044,8 +18053,8 @@
boolean isValidSingletonCall(int callingUid, int componentUid) {
int componentAppId = UserHandle.getAppId(componentUid);
return UserHandle.isSameApp(callingUid, componentUid)
- || componentAppId == Process.SYSTEM_UID
- || componentAppId == Process.PHONE_UID
+ || componentAppId == SYSTEM_UID
+ || componentAppId == PHONE_UID
|| ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, componentUid)
== PackageManager.PERMISSION_GRANTED;
}
@@ -18286,7 +18295,7 @@
// =========================================================
private boolean isInstantApp(ProcessRecord record, String callerPackage, int uid) {
- if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) {
+ if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) {
return false;
}
// Easy case -- we have the app's ProcessRecord.
@@ -18347,7 +18356,7 @@
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
- if (callerApp.info.uid != Process.SYSTEM_UID &&
+ if (callerApp.info.uid != SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
@@ -18564,7 +18573,7 @@
for (int user : users) {
// Skip users that have Shell restrictions, with exception of always permitted
// Shell broadcasts
- if (callingUid == Process.SHELL_UID
+ if (callingUid == SHELL_UID
&& mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, user)
&& !isPermittedShellBroadcast(intent)) {
@@ -18748,7 +18757,7 @@
// and upgrade steps.
if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
- if ((callingUid != Process.SYSTEM_UID
+ if ((callingUid != SYSTEM_UID
|| (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
Slog.w(TAG, "Skipping broadcast of " + intent
@@ -18792,11 +18801,11 @@
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
- case Process.ROOT_UID:
- case Process.SYSTEM_UID:
- case Process.PHONE_UID:
- case Process.BLUETOOTH_UID:
- case Process.NFC_UID:
+ case ROOT_UID:
+ case SYSTEM_UID:
+ case PHONE_UID:
+ case BLUETOOTH_UID:
+ case NFC_UID:
isCallerSystem = true;
break;
default:
@@ -19172,7 +19181,7 @@
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
- if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
+ if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
// Query one target user at a time, excluding shell-restricted users
for (int i = 0; i < users.length; i++) {
if (mUserController.hasUserRestriction(
@@ -19414,8 +19423,8 @@
if ((flags & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
switch (Binder.getCallingUid()) {
- case Process.ROOT_UID:
- case Process.SHELL_UID:
+ case ROOT_UID:
+ case SHELL_UID:
break;
default:
Slog.w(TAG, "Removing FLAG_RECEIVER_FROM_SHELL because caller is UID "
@@ -19870,7 +19879,7 @@
private void enforceWriteSettingsPermission(String func) {
int uid = Binder.getCallingUid();
- if (uid == Process.ROOT_UID) {
+ if (uid == ROOT_UID) {
return;
}
@@ -20068,7 +20077,7 @@
| Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
UserHandle.USER_ALL);
if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
@@ -20079,7 +20088,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
UserHandle.USER_ALL);
}
@@ -21553,27 +21562,27 @@
int processGroup;
switch (app.curSchedGroup) {
case ProcessList.SCHED_GROUP_BACKGROUND:
- processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
break;
case ProcessList.SCHED_GROUP_TOP_APP:
case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
- processGroup = Process.THREAD_GROUP_TOP_APP;
+ processGroup = THREAD_GROUP_TOP_APP;
break;
default:
- processGroup = Process.THREAD_GROUP_DEFAULT;
+ processGroup = THREAD_GROUP_DEFAULT;
break;
}
long oldId = Binder.clearCallingIdentity();
try {
- Process.setProcessGroup(app.pid, processGroup);
+ setProcessGroup(app.pid, processGroup);
if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
// do nothing if we already switched to RT
if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
// Switch VR thread for app to SCHED_FIFO
if (mVrState == VR_MODE && app.vrThreadTid != 0) {
try {
- Process.setThreadScheduler(app.vrThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(app.vrThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
mTopAppVrThreadTid = app.vrThreadTid;
} catch (IllegalArgumentException e) {
// thread died, ignore
@@ -21581,17 +21590,17 @@
}
if (mUseFifoUiScheduling) {
// Switch UI pipeline for app to SCHED_FIFO
- app.savedPriority = Process.getThreadPriority(app.pid);
+ app.savedPriority = getThreadPriority(app.pid);
try {
- Process.setThreadScheduler(app.pid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(app.pid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
if (app.renderThreadTid != 0) {
try {
- Process.setThreadScheduler(app.renderThreadTid,
- Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+ setThreadScheduler(app.renderThreadTid,
+ SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
@@ -21606,10 +21615,10 @@
}
} else {
// Boost priority for top app UI and render threads
- Process.setThreadPriority(app.pid, -10);
+ setThreadPriority(app.pid, -10);
if (app.renderThreadTid != 0) {
try {
- Process.setThreadPriority(app.renderThreadTid, -10);
+ setThreadPriority(app.renderThreadTid, -10);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
@@ -21621,23 +21630,23 @@
// Reset VR thread to SCHED_OTHER
// Safe to do even if we're not in VR mode
if (app.vrThreadTid != 0) {
- Process.setThreadScheduler(app.vrThreadTid, Process.SCHED_OTHER, 0);
+ setThreadScheduler(app.vrThreadTid, SCHED_OTHER, 0);
mTopAppVrThreadTid = 0;
}
if (mUseFifoUiScheduling) {
// Reset UI pipeline to SCHED_OTHER
- Process.setThreadScheduler(app.pid, Process.SCHED_OTHER, 0);
- Process.setThreadPriority(app.pid, app.savedPriority);
+ setThreadScheduler(app.pid, SCHED_OTHER, 0);
+ setThreadPriority(app.pid, app.savedPriority);
if (app.renderThreadTid != 0) {
- Process.setThreadScheduler(app.renderThreadTid,
- Process.SCHED_OTHER, 0);
- Process.setThreadPriority(app.renderThreadTid, -4);
+ setThreadScheduler(app.renderThreadTid,
+ SCHED_OTHER, 0);
+ setThreadPriority(app.renderThreadTid, -4);
}
} else {
// Reset priority for top app UI and render threads
- Process.setThreadPriority(app.pid, 0);
+ setThreadPriority(app.pid, 0);
if (app.renderThreadTid != 0) {
- Process.setThreadPriority(app.renderThreadTid, 0);
+ setThreadPriority(app.renderThreadTid, 0);
}
}
}
@@ -22747,7 +22756,7 @@
/** This method sends the specified signal to each of the persistent apps */
public void signalPersistentProcesses(int sig) throws RemoteException {
- if (sig != Process.SIGNAL_USR1) {
+ if (sig != SIGNAL_USR1) {
throw new SecurityException("Only SIGNAL_USR1 is allowed");
}
@@ -22761,7 +22770,7 @@
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = mLruProcesses.get(i);
if (r.thread != null && r.persistent) {
- Process.sendSignal(r.pid, sig);
+ sendSignal(r.pid, sig);
}
}
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0c2c204..c7f20b9f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1613,6 +1613,9 @@
String iconFilename = null;
int colorPrimary = 0;
int colorBackground = 0;
+ int statusBarColor = 0;
+ int navigationBarColor = 0;
+ boolean topActivity = true;
for (--activityNdx; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
if (r.taskDescription != null) {
@@ -1625,13 +1628,16 @@
if (colorPrimary == 0) {
colorPrimary = r.taskDescription.getPrimaryColor();
}
- if (colorBackground == 0) {
+ if (topActivity) {
colorBackground = r.taskDescription.getBackgroundColor();
+ statusBarColor = r.taskDescription.getStatusBarColor();
+ navigationBarColor = r.taskDescription.getNavigationBarColor();
}
}
+ topActivity = false;
}
lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
- colorBackground);
+ colorBackground, statusBarColor, navigationBarColor);
if (mWindowContainerController != null) {
mWindowContainerController.setTaskDescription(lastTaskDescription);
}
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..0e13f97 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;
@@ -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..dec639f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -842,11 +842,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 +2717,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 +2816,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
@@ -3119,35 +3130,18 @@
}
}
- 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;
- }
- }
- iter.remove();
- }
- if (matches.size() == 0) {
+ private @Nullable ComponentName getEphemeralResolverSettingsLPr(
+ @NonNull ComponentName resolver) {
+ final Intent intent = new Intent(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .setPackage(resolver.getPackageName());
+ final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+ final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+ UserHandle.USER_SYSTEM);
+ 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) {
@@ -16965,6 +16959,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 +17016,7 @@
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
+
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
@@ -20858,13 +20862,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 +20932,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/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b507df0..95fb5af 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2945,6 +2945,7 @@
}
mStatusBar = win;
mStatusBarController.setWindow(win);
+ setKeyguardOccludedLw(mKeyguardOccluded, true /* force */);
break;
case TYPE_NAVIGATION_BAR:
mContext.enforceCallingOrSelfPermission(
@@ -3832,7 +3833,7 @@
mPendingKeyguardOccluded = occluded;
mKeyguardOccludedChanged = true;
} else {
- setKeyguardOccludedLw(occluded);
+ setKeyguardOccludedLw(occluded, false /* force */);
}
}
@@ -3841,7 +3842,7 @@
if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
+ mPendingKeyguardOccluded);
mKeyguardOccludedChanged = false;
- if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
+ if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */)) {
return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
}
}
@@ -5254,11 +5255,8 @@
}
}
- // Don't allow snapshots to influence SystemUI visibility flags.
- // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
- && attrs.type < FIRST_SYSTEM_WINDOW
- && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
+ && attrs.type < FIRST_SYSTEM_WINDOW;
final int stackId = win.getStackId();
if (mTopFullscreenOpaqueWindowState == null && visible) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
@@ -5475,23 +5473,27 @@
*
* @return Whether the flags have changed and we have to redo the layout.
*/
- private boolean setKeyguardOccludedLw(boolean isOccluded) {
+ private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
boolean wasOccluded = mKeyguardOccluded;
boolean showing = mKeyguardDelegate.isShowing();
if (wasOccluded && !isOccluded && showing) {
mKeyguardOccluded = false;
mKeyguardDelegate.setOccluded(false, true /* animate */);
- mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
- if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
- mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ if (mStatusBar != null) {
+ mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+ if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
+ mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ }
}
return true;
} else if (!wasOccluded && isOccluded && showing) {
mKeyguardOccluded = true;
mKeyguardDelegate.setOccluded(true, false /* animate */);
- mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
- mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+ if (mStatusBar != null) {
+ mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+ mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+ }
return true;
} else if (wasOccluded != isOccluded) {
mKeyguardOccluded = isOccluded;
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/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 4b4be40..2bc3c5f 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -566,7 +566,7 @@
return false;
}
- mContainer.startingData = new SnapshotStartingData(mService, snapshot.getSnapshot());
+ mContainer.startingData = new SnapshotStartingData(mService, snapshot);
scheduleAddStartingWindow();
return true;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index da524c7..4ebf1fc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2920,7 +2920,11 @@
if (stack != null) {
stack.getBounds(frame);
}
- } else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
+
+ // We want to screenshot with the exact bounds of the surface of the app. Thus,
+ // intersect it with the frame.
+ frame.intersect(w.mFrame);
+ }else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
final Rect wf = w.mFrame;
final Rect cr = w.mContentInsets;
int left = wf.left + cr.left;
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index e73d4d25..35f35db 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.GraphicBuffer;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -25,9 +26,9 @@
class SnapshotStartingData extends StartingData {
private final WindowManagerService mService;
- private final GraphicBuffer mSnapshot;
+ private final TaskSnapshot mSnapshot;
- SnapshotStartingData(WindowManagerService service, GraphicBuffer snapshot) {
+ SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot) {
super(service);
mService = service;
mSnapshot = snapshot;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3ffb093..b816d81 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -17,15 +17,14 @@
package com.android.server.wm;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -40,7 +39,6 @@
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.EventLogTags;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b8d0b8c..48b01f4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -28,6 +28,7 @@
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
import android.os.Environment;
import android.util.ArraySet;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -152,7 +153,7 @@
* MANAGER LOCK WHEN CALLING THIS METHOD!
*/
StartingSurface createStartingSurface(AppWindowToken token,
- GraphicBuffer snapshot) {
+ TaskSnapshot snapshot) {
return TaskSnapshotSurface.create(mService, token, snapshot);
}
@@ -166,8 +167,17 @@
if (buffer == null) {
return null;
}
+ final WindowState mainWindow = top.findMainWindow();
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
- top.findMainWindow().mStableInsets, false /* reduced */, 1f /* scale */);
+ minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */,
+ 1f /* scale */);
+ }
+
+ private Rect minRect(Rect rect1, Rect rect2) {
+ return new Rect(Math.min(rect1.left, rect2.left),
+ Math.min(rect1.top, rect2.top),
+ Math.min(rect1.right, rect2.right),
+ Math.min(rect1.bottom, rect2.bottom));
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 04403e2..1591e48 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -16,20 +16,35 @@
package com.android.server.wm;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.graphics.Color.WHITE;
+import static android.graphics.Color.alpha;
+import static android.view.SurfaceControl.HIDDEN;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getColorViewLeftInset;
+import static com.android.internal.policy.DecorView.getColorViewTopInset;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManager.TaskDescription;
-import android.graphics.Bitmap;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -37,17 +52,22 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.view.IWindowSession;
import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy.StartingSurface;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.DecorView;
import com.android.internal.view.BaseIWindow;
/**
@@ -57,19 +77,57 @@
*/
class TaskSnapshotSurface implements StartingSurface {
+ private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
+
+ /**
+ * When creating the starting window, we use the exact same layout flags such that we end up
+ * with a window with the exact same dimensions etc. However, these flags are not used in layout
+ * and might cause other side effects so we exclude them.
+ */
+ private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+ | FLAG_NOT_TOUCHABLE
+ | FLAG_NOT_TOUCH_MODAL
+ | FLAG_ALT_FOCUSABLE_IM
+ | FLAG_NOT_FOCUSABLE
+ | FLAG_HARDWARE_ACCELERATED
+ | FLAG_IGNORE_CHEEK_PRESSES
+ | FLAG_LOCAL_FOCUS_MODE
+ | FLAG_SLIPPERY
+ | FLAG_WATCH_OUTSIDE_TOUCH
+ | FLAG_SPLIT_TOUCH
+ | FLAG_SCALED
+ | FLAG_SECURE;
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
private static final int MSG_REPORT_DRAW = 0;
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
private final Window mWindow;
private final Surface mSurface;
+ private SurfaceControl mChildSurfaceControl;
private final IWindowSession mSession;
private final WindowManagerService mService;
+ private final Rect mTaskBounds;
+ private final Rect mStableInsets = new Rect();
+ private final Rect mContentInsets = new Rect();
+ private final Rect mFrame = new Rect();
+ private final TaskSnapshot mSnapshot;
+ private final CharSequence mTitle;
private boolean mHasDrawn;
private boolean mReportNextDraw;
- private Paint mFillBackgroundPaint = new Paint();
+ private long mShownTime;
+ private final Handler mHandler;
+ private final boolean mSizeMismatch;
+ private final Paint mBackgroundPaint = new Paint();
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mSysUiVis;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
- GraphicBuffer snapshot) {
+ TaskSnapshot snapshot) {
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
final Window window = new Window();
@@ -78,32 +136,51 @@
final Surface surface = new Surface();
final Rect tmpRect = new Rect();
final Rect tmpFrame = new Rect();
+ final Rect taskBounds;
+ final Rect tmpContentInsets = new Rect();
+ final Rect tmpStableInsets = new Rect();
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
- int fillBackgroundColor = Color.WHITE;
+ int backgroundColor = WHITE;
+ int statusBarColor = 0;
+ int navigationBarColor = 0;
+ final int sysUiVis;
+ final int windowFlags;
+ final int windowPrivateFlags;
synchronized (service.mWindowMap) {
+ final WindowState mainWindow = token.findMainWindow();
+ if (mainWindow == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+ + token);
+ return null;
+ }
+ sysUiVis = mainWindow.getSystemUiVisibility();
+ windowFlags = mainWindow.getAttrs().flags;
+ windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+
layoutParams.type = TYPE_APPLICATION_STARTING;
- layoutParams.format = snapshot.getFormat();
- layoutParams.flags = FLAG_LAYOUT_INSET_DECOR
- | FLAG_LAYOUT_IN_SCREEN
+ layoutParams.format = snapshot.getSnapshot().getFormat();
+ layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE
- | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ | FLAG_NOT_TOUCHABLE;
layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
-
- // TODO: Inherit behavior whether to draw behind status bar/nav bar.
- layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ layoutParams.systemUiVisibility = sysUiVis;
final Task task = token.getTask();
if (task != null) {
- layoutParams.setTitle(String.format(TITLE_FORMAT,task.mTaskId));
+ layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
final TaskDescription taskDescription = task.getTaskDescription();
if (taskDescription != null) {
- fillBackgroundColor = taskDescription.getBackgroundColor();
+ backgroundColor = taskDescription.getBackgroundColor();
+ statusBarColor = taskDescription.getStatusBarColor();
+ navigationBarColor = taskDescription.getNavigationBarColor();
}
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ } else {
+ taskBounds = null;
}
}
try {
@@ -118,31 +195,57 @@
// Local call.
}
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
- surface, fillBackgroundColor);
+ surface, snapshot, layoutParams.getTitle(), backgroundColor, statusBarColor,
+ navigationBarColor, sysUiVis, windowFlags, windowPrivateFlags, taskBounds);
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
- tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpMergedConfiguration,
- surface);
+ tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
+ tmpMergedConfiguration, surface);
} catch (RemoteException e) {
// Local call.
}
- snapshotSurface.drawSnapshot(snapshot);
+ snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
+ snapshotSurface.drawSnapshot();
return snapshotSurface;
}
@VisibleForTesting
TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface,
- int fillBackgroundColor) {
+ TaskSnapshot snapshot, CharSequence title, int backgroundColor, int statusBarColor,
+ int navigationBarColor, int sysUiVis, int windowFlags, int windowPrivateFlags,
+ Rect taskBounds) {
mService = service;
+ mHandler = new Handler(mService.mH.getLooper());
mSession = WindowManagerGlobal.getWindowSession();
mWindow = window;
mSurface = surface;
- mFillBackgroundPaint.setColor(fillBackgroundColor);
+ mSnapshot = snapshot;
+ mTitle = title;
+ mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
+ mTaskBounds = taskBounds;
+ mSysUiVis = sysUiVis;
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mSizeMismatch = (mFrame.width() != snapshot.getSnapshot().getWidth()
+ || mFrame.height() != snapshot.getSnapshot().getHeight());
+ mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
+ service.mContext.getColor(R.color.system_bar_background_semi_transparent),
+ statusBarColor);
+ mNavigationBarColor = navigationBarColor;
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(navigationBarColor);
}
@Override
public void remove() {
+ synchronized (mService.mWindowMap) {
+ final long now = SystemClock.uptimeMillis();
+ if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
+ mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
+ return;
+ }
+ }
try {
mSession.remove(mWindow);
} catch (RemoteException e) {
@@ -150,31 +253,149 @@
}
}
- private void drawSnapshot(GraphicBuffer snapshot) {
- mSurface.attachAndQueueBuffer(snapshot);
+ @VisibleForTesting
+ void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
+ mFrame.set(frame);
+ mContentInsets.set(contentInsets);
+ mStableInsets.set(stableInsets);
+ }
+
+ private void drawSnapshot() {
+ final GraphicBuffer buffer = mSnapshot.getSnapshot();
+ if (mSizeMismatch) {
+ // The dimensions of the buffer and the window don't match, so attaching the buffer
+ // will fail. Better create a child window with the exact dimensions and fill the parent
+ // window with the background color!
+ drawSizeMismatchSnapshot(buffer);
+ } else {
+ drawSizeMatchSnapshot(buffer);
+ }
final boolean reportNextDraw;
synchronized (mService.mWindowMap) {
+ mShownTime = SystemClock.uptimeMillis();
mHasDrawn = true;
reportNextDraw = mReportNextDraw;
}
if (reportNextDraw) {
reportDrawn();
}
+ }
+
+ private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
+ mSurface.attachAndQueueBuffer(buffer);
+ mSurface.release();
+ }
+
+ private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+ final SurfaceSession session = new SurfaceSession(mSurface);
+
+ // Keep a reference to it such that it doesn't get destroyed when finalized.
+ mChildSurfaceControl = new SurfaceControl(session,
+ mTitle + " - task-snapshot-surface",
+ buffer.getWidth(), buffer.getHeight(), buffer.getFormat(), HIDDEN);
+ Surface surface = new Surface();
+ surface.copyFrom(mChildSurfaceControl);
+
+ // Clip off ugly navigation bar.
+ final Rect crop = calculateSnapshotCrop();
+ final Rect frame = calculateSnapshotFrame(crop);
+ SurfaceControl.openTransaction();
+ try {
+ // We can just show the surface here as it will still be hidden as the parent is
+ // still hidden.
+ mChildSurfaceControl.show();
+ mChildSurfaceControl.setWindowCrop(crop);
+ mChildSurfaceControl.setPosition(frame.left, frame.top);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ surface.attachAndQueueBuffer(buffer);
+ surface.release();
+
+ final Canvas c = mSurface.lockCanvas(null);
+ drawBackgroundAndBars(c, frame);
+ mSurface.unlockCanvasAndPost(c);
mSurface.release();
}
@VisibleForTesting
- void fillEmptyBackground(Canvas c, Bitmap b) {
- final boolean fillHorizontally = c.getWidth() > b.getWidth();
- final boolean fillVertically = c.getHeight() > b.getHeight();
+ Rect calculateSnapshotCrop() {
+ final Rect rect = new Rect();
+ rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight());
+ final Rect insets = mSnapshot.getContentInsets();
+
+ // Let's remove all system decorations except the status bar, but only if the task is at the
+ // very top of the screen.
+ rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom);
+ return rect;
+ }
+
+ @VisibleForTesting
+ Rect calculateSnapshotFrame(Rect crop) {
+ final Rect frame = new Rect(crop);
+
+ // By default, offset it to to top/left corner
+ frame.offsetTo(-crop.left, -crop.top);
+
+ // However, we also need to make space for the navigation bar on the left side.
+ final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
+ mContentInsets.left);
+ frame.offset(colorViewLeftInset, 0);
+ return frame;
+ }
+
+ @VisibleForTesting
+ void drawBackgroundAndBars(Canvas c, Rect frame) {
+ final int statusBarHeight = getStatusBarColorViewHeight();
+ final boolean fillHorizontally = c.getWidth() > frame.right;
+ final boolean fillVertically = c.getHeight() > frame.bottom;
if (fillHorizontally) {
- c.drawRect(b.getWidth(), 0, c.getWidth(), fillVertically
- ? b.getHeight()
- : c.getHeight(),
- mFillBackgroundPaint);
+ c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
+ c.getWidth(), fillVertically
+ ? frame.bottom
+ : c.getHeight(),
+ mBackgroundPaint);
}
if (fillVertically) {
- c.drawRect(0, b.getHeight(), c.getWidth(), c.getHeight(), mFillBackgroundPaint);
+ c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
+ }
+ drawStatusBarBackground(c, frame, statusBarHeight);
+ drawNavigationBarBackground(c);
+ }
+
+ private int getStatusBarColorViewHeight() {
+ final boolean forceStatusBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+ return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+ }
+
+ @VisibleForTesting
+ void drawStatusBarBackground(Canvas c, Rect frame, int statusBarHeight) {
+ if (statusBarHeight > 0 && c.getWidth() > frame.right) {
+ final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
+ mContentInsets.right);
+ c.drawRect(frame.right, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
+ navigationBarRect);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
}
}
@@ -211,10 +432,10 @@
}
};
- private static class Window extends BaseIWindow {
+ @VisibleForTesting
+ static class Window extends BaseIWindow {
private TaskSnapshotSurface mOuter;
-
public void setOuter(TaskSnapshotSurface outer) {
mOuter = outer;
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 57fb81c..57eaa2b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -17,17 +17,15 @@
package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
import android.content.Context;
+import android.os.Handler;
import android.os.Trace;
import android.util.Slog;
import android.util.SparseArray;
@@ -36,6 +34,9 @@
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
+import com.android.server.DisplayThread;
+
import java.io.PrintWriter;
/**
@@ -82,20 +83,31 @@
// check if some got replaced and can be removed.
private boolean mRemoveReplacedWindows = false;
+ private long mCurrentFrameTime;
+ private final Runnable mAnimationTick;
+ private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
+
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
mWindowPlacerLocked = service.mWindowPlacerLocked;
+ final Handler handler = DisplayThread.getHandler();
- mAnimationFrameCallback = new Choreographer.FrameCallback() {
- public void doFrame(long frameTimeNs) {
- synchronized (mService.mWindowMap) {
- mService.mAnimationScheduled = false;
- animateLocked(frameTimeNs);
- }
+ // TODO: Multi-display: If displays have different vsync tick, have a separate tick per
+ // display.
+ mSfChoreographer = new SurfaceFlingerVsyncChoreographer(handler,
+ mService.getDefaultDisplayContentLocked().getDisplay());
+ mAnimationTick = () -> {
+ synchronized (mService.mWindowMap) {
+ mService.mAnimationScheduled = false;
+ animateLocked(mCurrentFrameTime);
}
};
+ mAnimationFrameCallback = frameTimeNs -> {
+ mCurrentFrameTime = frameTimeNs;
+ mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
+ };
}
void addDisplayLocked(final int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowContainerController.java b/services/core/java/com/android/server/wm/WindowContainerController.java
index 84ffc35..c4a6837 100644
--- a/services/core/java/com/android/server/wm/WindowContainerController.java
+++ b/services/core/java/com/android/server/wm/WindowContainerController.java
@@ -33,7 +33,7 @@
final WindowManagerService mService;
final RootWindowContainer mRoot;
- final HashMap<IBinder, WindowState> mWindowMap;
+ final WindowHashMap mWindowMap;
// The window container this controller owns.
E mContainer;
diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/services/core/java/com/android/server/wm/WindowHashMap.java
similarity index 65%
copy from core/java/com/android/internal/font/IFontManager.aidl
copy to services/core/java/com/android/server/wm/WindowHashMap.java
index 52a6262..49bba41 100644
--- a/core/java/com/android/internal/font/IFontManager.aidl
+++ b/services/core/java/com/android/server/wm/WindowHashMap.java
@@ -11,17 +11,18 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
*/
-package com.android.internal.font;
+package com.android.server.wm;
-import android.text.FontConfig;
+import android.os.IBinder;
+
+import java.util.HashMap;
/**
- * Interface to the font manager.
- * @hide
+ * Subclass of HashMap such that we can instruct the compiler to boost our thread priority when
+ * locking this class. See makefile.
*/
-interface IFontManager {
- FontConfig getSystemFonts();
+class WindowHashMap extends HashMap<IBinder, WindowState> {
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f1796de..1be0512 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
+import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -25,6 +26,11 @@
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_USER_HANDLE;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+import static android.os.Process.myPid;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -60,6 +66,8 @@
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.LockGuard.INDEX_WINDOW;
+import static com.android.server.LockGuard.installLock;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
@@ -125,7 +133,6 @@
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
import android.net.Uri;
-import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -139,7 +146,7 @@
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
-import android.os.Process;
+import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -151,10 +158,10 @@
import android.os.WorkSource;
import android.provider.Settings;
import android.util.ArraySet;
-import android.util.MergedConfiguration;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.MergedConfiguration;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -215,7 +222,7 @@
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.LockGuard;
+import com.android.server.ThreadPriorityBooster;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
@@ -239,10 +246,7 @@
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
-
-import static android.Manifest.permission.READ_FRAME_BUFFER;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@@ -408,7 +412,7 @@
* This is also used as the lock for all of our state.
* NOTE: Never call into methods that lock ActivityManagerService while holding this object.
*/
- final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
+ final WindowHashMap mWindowMap = new WindowHashMap();
/**
* List of window tokens that have finished starting their application,
@@ -848,6 +852,16 @@
// since they won't be notified through the app window animator.
final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
+ private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+ THREAD_PRIORITY_DISPLAY, INDEX_WINDOW);
+
+ static void boostPriorityForLockedSection() {
+ sThreadPriorityBooster.boost();
+ }
+
+ static void resetPriorityAfterLockedSection() {
+ sThreadPriorityBooster.reset();
+ }
void openSurfaceTransaction() {
synchronized (mWindowMap) {
@@ -936,7 +950,7 @@
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
- LockGuard.installLock(this, LockGuard.INDEX_WINDOW);
+ installLock(this, INDEX_WINDOW);
mRoot = new RootWindowContainer(this);
mContext = context;
mHaveInputMethods = haveInputMethods;
@@ -1581,7 +1595,7 @@
@Override
public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
final int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+ if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
throw new SecurityException("Only shell can call enableSurfaceTrace");
}
@@ -1593,8 +1607,8 @@
@Override
public void disableSurfaceTrace() {
final int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID &&
- callingUid != Process.SYSTEM_UID) {
+ if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
+ callingUid != SYSTEM_UID) {
throw new SecurityException("Only shell can call disableSurfaceTrace");
}
synchronized (mWindowMap) {
@@ -1608,7 +1622,7 @@
@Override
public void setScreenCaptureDisabled(int userId, boolean disabled) {
int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SYSTEM_UID) {
+ if (callingUid != SYSTEM_UID) {
throw new SecurityException("Only system can call setScreenCaptureDisabled.");
}
@@ -2264,7 +2278,7 @@
boolean checkCallingPermission(String permission, String func) {
// Quick check: if the calling permission is me, it's all okay.
- if (Binder.getCallingPid() == Process.myPid()) {
+ if (Binder.getCallingPid() == myPid()) {
return true;
}
@@ -2917,7 +2931,7 @@
}
// If this isn't coming from the system then don't allow disabling the lockscreen
// to bypass security.
- if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) {
+ if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
return;
}
@@ -7058,7 +7072,7 @@
throw new IllegalStateException("Magnification callbacks not set!");
}
}
- if (Binder.getCallingPid() != android.os.Process.myPid()) {
+ if (Binder.getCallingPid() != myPid()) {
spec.recycle();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6fd95a4..8098eea 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2395,6 +2395,9 @@
if (requestAnim) {
mService.scheduleAnimationLocked();
}
+ if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) {
+ mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
+ }
return true;
}
@@ -2437,6 +2440,9 @@
if (requestAnim) {
mService.scheduleAnimationLocked();
}
+ if (mService.mCurrentFocus == this) {
+ mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
+ }
return true;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 412cf81..a5eac46 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1017,12 +1017,6 @@
traceEnd();
}
- if (!disableNonCoreServices) {
- traceBeginAndSlog("StartFontServiceManager");
- mSystemServiceManager.startService(FontManagerService.Lifecycle.class);
- traceEnd();
- }
-
if (!disableNonCoreServices && !disableTextServices) {
traceBeginAndSlog("StartTextServicesManager");
mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
diff --git a/services/profile-classes b/services/profile-classes
index 1b304e1..b0d2da7 100644
--- a/services/profile-classes
+++ b/services/profile-classes
@@ -2481,7 +2481,6 @@
Landroid/text/FontConfig$Family$1;
Landroid/text/FontConfig$Font;
Landroid/text/FontConfig$Font$1;
-Landroid/text/FontManager;
Landroid/text/format/DateFormat;
Landroid/text/format/Time;
Landroid/text/format/Time$TimeCalculator;
@@ -3132,8 +3131,6 @@
Lcom/android/internal/content/PackageMonitor;
Lcom/android/internal/content/ReferrerIntent;
Lcom/android/internal/content/ReferrerIntent$1;
-Lcom/android/internal/font/IFontManager;
-Lcom/android/internal/font/IFontManager$Stub;
Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable;
Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable$AnimationScaleListState;
Lcom/android/internal/hardware/AmbientDisplayConfiguration;
@@ -4377,8 +4374,6 @@
Lcom/android/server/firewall/StringFilter$8;
Lcom/android/server/firewall/StringFilter$9;
Lcom/android/server/firewall/StringFilter$ValueProvider;
-Lcom/android/server/FontManagerService;
-Lcom/android/server/FontManagerService$Lifecycle;
Lcom/android/server/GestureLauncherService;
Lcom/android/server/GestureLauncherService$1;
Lcom/android/server/GestureLauncherService$2;
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/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index aab75ee..717ddf2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
@@ -24,15 +27,19 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.Surface;
-import org.junit.Before;
+import com.android.server.wm.TaskSnapshotSurface.Window;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,59 +55,174 @@
private TaskSnapshotSurface mSurface;
- @Before
- public void setUp() {
- mSurface = new TaskSnapshotSurface(null, null, null, Color.WHITE);
+ private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
+ int windowFlags, Rect taskBounds) {
+ final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+ final TaskSnapshot snapshot = new TaskSnapshot(buffer,
+ ORIENTATION_PORTRAIT, contentInsets, false, 1.0f);
+ mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
+ Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds);
+ }
+
+ private void setupSurface(int width, int height) {
+ setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, width, height));
}
@Test
public void fillEmptyBackground_fillHorizontally() throws Exception {
+ setupSurface(200, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(200);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
}
@Test
public void fillEmptyBackground_fillVertically() throws Exception {
+ setupSurface(100, 200);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(200);
- final Bitmap b = Bitmap.createBitmap(200, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
}
@Test
public void fillEmptyBackground_fillBoth() throws Exception {
+ setupSurface(200, 200);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(200);
when(mockCanvas.getHeight()).thenReturn(200);
- final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
}
@Test
public void fillEmptyBackground_dontFill_sameSize() throws Exception {
+ setupSurface(100, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
@Test
public void fillEmptyBackground_dontFill_bitmapLarger() throws Exception {
+ setupSurface(100, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
+
+ @Test
+ public void testCalculateSnapshotCrop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 100, 90), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_taskNotOnTop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 100));
+ assertEquals(new Rect(0, 10, 100, 90), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarLeft() {
+ setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(10, 0, 100, 100), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarRight() {
+ setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 90, 100), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 0, 10);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ assertEquals(new Rect(0, -10, 100, 70),
+ mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame_navBarLeft() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(10, 10, 0, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ assertEquals(new Rect(0, -10, 90, 80),
+ mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
+ }
+
+ @Test
+ public void testDrawStatusBarBackground() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100), 10);
+ verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
+ public void testDrawStatusBarBackground_nope() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100), 10);
+ verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground() {
+ final Rect insets = new Rect(0, 10, 0, 10);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_left() {
+ final Rect insets = new Rect(10, 10, 0, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_right() {
+ final Rect insets = new Rect(0, 10, 10, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
+ }
}
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
new file mode 100644
index 0000000..e4cbe93
--- /dev/null
+++ b/tests/WindowManagerStressTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := WindowManagerStressTest
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/WindowManagerStressTest/AndroidManifest.xml b/tests/WindowManagerStressTest/AndroidManifest.xml
new file mode 100644
index 0000000..17e0f15
--- /dev/null
+++ b/tests/WindowManagerStressTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.windowmanagerstresstest">
+
+ <application
+ android:allowBackup="false"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity android:name=".MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/WindowManagerStressTest/res/layout/activity_main.xml b/tests/WindowManagerStressTest/res/layout/activity_main.xml
new file mode 100644
index 0000000..6cf8269
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/layout/activity_main.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="test.amslam.MainActivity">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/run"
+ android:text="@string/run" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/output" />
+
+</LinearLayout>
diff --git a/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/values/colors.xml b/tests/WindowManagerStressTest/res/values/colors.xml
new file mode 100644
index 0000000..4270ca6
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/dimens.xml b/tests/WindowManagerStressTest/res/values/dimens.xml
new file mode 100644
index 0000000..ed4ccbc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/dimens.xml
@@ -0,0 +1,19 @@
+<!-- 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.
+-->
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/strings.xml b/tests/WindowManagerStressTest/res/values/strings.xml
new file mode 100644
index 0000000..cef05dc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+ <string name="app_name">WmSlam</string>
+ <string name="run">Run</string>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/styles.xml b/tests/WindowManagerStressTest/res/values/styles.xml
new file mode 100644
index 0000000..0983b25
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/styles.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<resources>
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="android:colorPrimary">@color/colorPrimary</item>
+ <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="android:colorAccent">@color/colorAccent</item>
+ </style>
+</resources>
diff --git a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
new file mode 100644
index 0000000..6b9bb31
--- /dev/null
+++ b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
@@ -0,0 +1,150 @@
+/*
+ * 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 test.windowmanagerstresstest;
+
+import android.app.Activity;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.MergedConfiguration;
+import android.view.Display;
+import android.view.IWindowSession;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
+import android.widget.TextView;
+
+import com.android.internal.view.BaseIWindow;
+
+import java.util.ArrayList;
+
+public class MainActivity extends Activity {
+
+ private static final String TAG = "WmSlam";
+
+ private TextView mOutput;
+ private volatile boolean finished;
+ private final ArrayList<BaseIWindow> mWindows = new ArrayList<>();
+ private final LayoutParams mLayoutParams = new LayoutParams();
+ private final Rect mTmpRect = new Rect();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mOutput = (TextView) findViewById(R.id.output);
+
+ findViewById(R.id.run).setOnClickListener(view -> {
+ view.setEnabled(false);
+ mOutput.setText("");
+ startBatch();
+ });
+ mLayoutParams.token = getActivityToken();
+ }
+
+ void startBatch() {
+ new Thread(() -> {
+ finished = false;
+ addWindows();
+ startCpuRunnables();
+ for (int i = 0; i < 5; i++) {
+ final long time = SystemClock.uptimeMillis();
+ slamWm();
+ log("Total: " + (SystemClock.uptimeMillis() - time) + " ms");
+ }
+ removeWindows();
+ finished = true;
+ }).start();
+ }
+
+ void startCpuRunnables() {
+ for (int i = 0; i < 10; i++) {
+ new Thread(mUseCpuRunnable).start();
+ }
+ }
+
+ private final Runnable mUseCpuRunnable = new Runnable() {
+ @Override
+ public void run() {
+ while (!finished) {
+ }
+ }
+ };
+
+ private void log(String text) {
+ mOutput.post(() -> mOutput.append(text + "\n"));
+ Log.d(TAG, text);
+ }
+
+ private void slamWm() {
+ ArrayList<Thread> threads = new ArrayList<>();
+ for (int i = 0; i < 20; i++) {
+ for (BaseIWindow window : mWindows) {
+ Thread t = new Thread(() -> {
+ try {
+ WindowManagerGlobal.getWindowSession().relayout(window,
+ window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, mTmpRect,
+ mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
+ new MergedConfiguration(), new Surface());
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ });
+ threads.add(t);
+ t.start();
+ }
+ }
+ for (Thread t : threads) {
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ void addWindows() {
+ for (int i = 0; i < 50; i++) {
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+ layoutParams.token = getActivityToken();
+ final BaseIWindow window = new BaseIWindow();
+ final IWindowSession session = WindowManagerGlobal.getWindowSession();
+ final Rect tmpRect = new Rect();
+ try {
+ final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq, layoutParams,
+ View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ mWindows.add(window);
+ }
+ }
+
+ void removeWindows() {
+ for (BaseIWindow window : mWindows) {
+ try {
+ WindowManagerGlobal.getWindowSession().remove(window);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
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;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index 7fe464a..a21fe68 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -26,6 +26,7 @@
import android.annotation.Nullable;
import android.content.res.AssetManager;
import android.content.res.BridgeAssetManager;
+import android.graphics.fonts.FontVariationAxis;
import android.text.FontConfig;
import java.awt.Font;
@@ -250,7 +251,7 @@
// ---- delegate methods ----
@LayoutlibDelegate
/*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex,
- FontConfig.Axis[] axes, int weight, int italic) {
+ FontVariationAxis[] axes, int weight, int italic) {
if (thisFontFamily.mBuilderPtr == 0) {
assert false : "Unable to call addFont after freezing.";
return false;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 80e3bad..c7818a3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.graphics.FontFamily_Delegate.FontVariant;
+import android.graphics.fonts.FontVariationAxis;
import android.text.FontConfig;
import java.awt.Font;
@@ -163,7 +164,7 @@
@LayoutlibDelegate
/*package*/ static synchronized long nativeCreateFromTypefaceWithVariation(long native_instance,
- List<FontConfig.Axis> axes) {
+ List<FontVariationAxis> axes) {
long newInstance = nativeCreateFromTypeface(native_instance, 0);
if (newInstance != 0) {