Merge "Deliver start service args with ParcelledListSlice." into oc-dev
diff --git a/Android.mk b/Android.mk
index 634272b..ee7d471 100644
--- a/Android.mk
+++ b/Android.mk
@@ -367,7 +367,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 \
@@ -1461,8 +1460,7 @@
LOCAL_SRC_FILES := \
$(call all-proto-files-under, core/proto) \
$(call all-proto-files-under, libs/incident/proto)
-LOCAL_SHARED_LIBRARIES := libprotobuf-cpp-full
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
# ==== c++ proto host library ==============================
include $(CLEAR_VARS)
diff --git a/api/current.txt b/api/current.txt
index af3ef9e..c5f4816 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3578,7 +3578,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
@@ -4358,7 +4358,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public android.app.ActionBar getActionBar();
method public final android.content.Context getContext();
method public android.view.View getCurrentFocus();
@@ -7044,6 +7044,7 @@
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();
@@ -8889,7 +8890,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";
@@ -10645,6 +10645,7 @@
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+ field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -13242,7 +13243,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);
@@ -13776,8 +13777,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);
@@ -14387,6 +14388,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 {
@@ -15982,11 +15998,11 @@
ctor public UsbRequest();
method public boolean cancel();
method public void close();
- method public boolean enqueue(java.nio.ByteBuffer);
method public java.lang.Object getClientData();
method public android.hardware.usb.UsbEndpoint getEndpoint();
method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
method public deprecated boolean queue(java.nio.ByteBuffer, int);
+ method public boolean queue(java.nio.ByteBuffer);
method public void setClientData(java.lang.Object);
}
@@ -22999,6 +23015,7 @@
method public void setProfile(android.media.CamcorderProfile);
method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
method public void setVideoEncodingBitRate(int);
+ method public void setVideoEncodingProfileLevel(int, int);
method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -24540,85 +24557,6 @@
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
- public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
- field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
- field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
- field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
- field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
- field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
- field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
- field public static final java.lang.String COLUMN_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 java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
- field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
- field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
- field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
- field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
- field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
- field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
- field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
- field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
- field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
- field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
- field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
- field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
- field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
- field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
- field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
- field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
- field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
- field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
- field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
- }
-
- 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";
}
@@ -24705,22 +24643,116 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_AUTHOR = "author";
+ field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+ field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+ field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+ field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+ field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+ field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+ field public static final java.lang.String COLUMN_LIVE = "live";
+ field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+ field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+ field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+ field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+ field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+ field public static final java.lang.String COLUMN_TYPE = "type";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -24749,32 +24781,126 @@
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 java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
- field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ 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
+ field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
}
public final class TvInputInfo implements android.os.Parcelable {
@@ -34395,14 +34521,15 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final java.lang.String WEIGHT = "font_weight";
}
public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -38624,6 +38751,7 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public final long getConnectTimeMillis();
+ method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
method public android.telecom.GatewayInfo getGatewayInfo();
@@ -41050,65 +41178,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);
}
@@ -41256,6 +41325,8 @@
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
public static final class Layout.Alignment extends java.lang.Enum {
@@ -41457,7 +41528,7 @@
method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
method public android.text.StaticLayout.Builder setIncludePad(boolean);
method public android.text.StaticLayout.Builder setIndents(int[], int[]);
- method public android.text.StaticLayout.Builder setJustify(boolean);
+ method public android.text.StaticLayout.Builder setJustificationMode(int);
method public android.text.StaticLayout.Builder setLineSpacing(float, float);
method public android.text.StaticLayout.Builder setMaxLines(int);
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46536,7 +46607,7 @@
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public boolean getAllowEnterTransitionOverlap();
method public boolean getAllowReturnTransitionOverlap();
method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -48661,7 +48732,7 @@
method public abstract boolean getOffscreenPreRaster();
method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
method public abstract java.lang.String getSansSerifFontFamily();
- method public abstract boolean getSaveFormData();
+ method public abstract deprecated boolean getSaveFormData();
method public abstract deprecated boolean getSavePassword();
method public abstract java.lang.String getSerifFontFamily();
method public abstract java.lang.String getStandardFontFamily();
@@ -48710,7 +48781,7 @@
method public abstract deprecated void setPluginState(android.webkit.WebSettings.PluginState);
method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
method public abstract void setSansSerifFontFamily(java.lang.String);
- method public abstract void setSaveFormData(boolean);
+ method public abstract deprecated void setSaveFormData(boolean);
method public abstract deprecated void setSavePassword(boolean);
method public abstract void setSerifFontFamily(java.lang.String);
method public abstract void setStandardFontFamily(java.lang.String);
@@ -49001,12 +49072,12 @@
public abstract class WebViewDatabase {
ctor public WebViewDatabase();
- method public abstract void clearFormData();
+ method public abstract deprecated void clearFormData();
method public abstract void clearHttpAuthUsernamePassword();
method public abstract deprecated void clearUsernamePassword();
method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
- method public abstract boolean hasFormData();
+ method public abstract deprecated boolean hasFormData();
method public abstract boolean hasHttpAuthUsernamePassword();
method public abstract deprecated boolean hasUsernamePassword();
method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -51267,7 +51338,7 @@
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
method public int getInputType();
- method public boolean getJustify();
+ method public int getJustificationMode();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
@@ -51362,7 +51433,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);
@@ -51380,7 +51451,7 @@
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
- method public void setJustify(boolean);
+ method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
method public void setLetterSpacing(float);
method public void setLineSpacing(float, float);
diff --git a/api/removed.txt b/api/removed.txt
index 42b2ae6..d20c08c 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -296,6 +296,10 @@
field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
}
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field public static final java.lang.String STYLE = "font_style";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 73cf776..9b295bf 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3702,7 +3702,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
@@ -4509,7 +4509,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public android.app.ActionBar getActionBar();
method public final android.content.Context getContext();
method public android.view.View getCurrentFocus();
@@ -4621,6 +4621,7 @@
method public android.database.Cursor query(android.app.DownloadManager.Query);
method public int remove(long...);
field public static final java.lang.String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
+ field public static final java.lang.String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
field public static final java.lang.String ACTION_NOTIFICATION_CLICKED = "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
field public static final java.lang.String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS";
field public static final java.lang.String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far";
@@ -7502,6 +7503,7 @@
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();
@@ -9386,7 +9388,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";
@@ -9797,6 +9798,7 @@
field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
field public static final java.lang.String ACTION_EDIT = "android.intent.action.EDIT";
+ field public static final deprecated java.lang.String ACTION_EPHEMERAL_RESOLVER_SETTINGS = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
@@ -9809,7 +9811,10 @@
field public static final java.lang.String ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
+ field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
+ field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
@@ -9868,6 +9873,8 @@
field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
field public static final java.lang.String ACTION_QUICK_VIEW = "android.intent.action.QUICK_VIEW";
field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
+ field public static final deprecated java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
@@ -9877,6 +9884,7 @@
field public static final java.lang.String ACTION_SEND = "android.intent.action.SEND";
field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
+ field public static final deprecated java.lang.String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
@@ -9951,6 +9959,8 @@
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
+ field public static final deprecated java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
+ field public static final deprecated java.lang.String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
field public static final deprecated java.lang.String EXTRA_CHANGED_COMPONENT_NAME = "android.intent.extra.changed_component_name";
field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
@@ -9960,7 +9970,14 @@
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_CONTENT_ANNOTATIONS = "android.intent.extra.CONTENT_ANNOTATIONS";
+ field public static final deprecated java.lang.String EXTRA_CSS_INDICATOR = "cssIndicator";
+ field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long";
+ field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_SHORT = "data-operator-alpha-short";
+ field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_NUMERIC = "data-operator-numeric";
+ field public static final deprecated java.lang.String EXTRA_DATA_RADIO_TECH = "dataRadioTechnology";
+ field public static final deprecated java.lang.String EXTRA_DATA_REG_STATE = "dataRegState";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
+ field public static final deprecated java.lang.String EXTRA_DATA_ROAMING_TYPE = "dataRoamingType";
field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
field public static final int EXTRA_DOCK_STATE_CAR = 2; // 0x2
field public static final int EXTRA_DOCK_STATE_DESK = 1; // 0x1
@@ -9969,6 +9986,7 @@
field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+ field public static final deprecated java.lang.String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
@@ -9976,10 +9994,18 @@
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
field public static final java.lang.String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_INTENT = "android.intent.extra.INTENT";
+ field public static final deprecated java.lang.String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION = "isDataRoamingFromRegistration";
+ field public static final deprecated java.lang.String EXTRA_IS_USING_CARRIER_AGGREGATION = "isUsingCarrierAggregation";
field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
+ field public static final deprecated java.lang.String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
+ field public static final deprecated java.lang.String EXTRA_MANUAL = "manual";
field public static final java.lang.String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
+ field public static final deprecated java.lang.String EXTRA_NETWORK_ID = "networkId";
field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+ field public static final deprecated java.lang.String EXTRA_OPERATOR_ALPHA_LONG = "operator-alpha-long";
+ field public static final deprecated java.lang.String EXTRA_OPERATOR_ALPHA_SHORT = "operator-alpha-short";
+ field public static final deprecated java.lang.String EXTRA_OPERATOR_NUMERIC = "operator-numeric";
field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
@@ -10011,11 +10037,15 @@
field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
+ field public static final deprecated java.lang.String EXTRA_SYSTEM_ID = "systemId";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
field public static final java.lang.String EXTRA_USER = "android.intent.extra.USER";
+ field public static final deprecated java.lang.String EXTRA_VOICE_RADIO_TECH = "radioTechnology";
+ field public static final deprecated java.lang.String EXTRA_VOICE_REG_STATE = "voiceRegState";
+ field public static final deprecated java.lang.String EXTRA_VOICE_ROAMING_TYPE = "voiceRoamingType";
field public static final int FILL_IN_ACTION = 1; // 0x1
field public static final int FILL_IN_CATEGORIES = 4; // 0x4
field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -11298,6 +11328,7 @@
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+ field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -13974,7 +14005,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);
@@ -14508,8 +14539,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);
@@ -15119,6 +15150,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 {
@@ -17442,11 +17488,11 @@
ctor public UsbRequest();
method public boolean cancel();
method public void close();
- method public boolean enqueue(java.nio.ByteBuffer);
method public java.lang.Object getClientData();
method public android.hardware.usb.UsbEndpoint getEndpoint();
method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
method public deprecated boolean queue(java.nio.ByteBuffer, int);
+ method public boolean queue(java.nio.ByteBuffer);
method public void setClientData(java.lang.Object);
}
@@ -22841,6 +22887,7 @@
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
method public void adjustVolume(int, int);
+ method public int dispatchAudioFocusChange(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy);
method public void dispatchMediaKeyEvent(android.view.KeyEvent);
method public int generateAudioSessionId();
method public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
@@ -24792,6 +24839,7 @@
method public void setProfile(android.media.CamcorderProfile);
method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
method public void setVideoEncodingBitRate(int);
+ method public void setVideoEncodingProfileLevel(int, int);
method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -25842,8 +25890,10 @@
public static abstract class AudioPolicy.AudioPolicyFocusListener {
ctor public AudioPolicy.AudioPolicyFocusListener();
+ method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
+ method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
}
public static abstract class AudioPolicy.AudioPolicyStatusListener {
@@ -25858,6 +25908,7 @@
method public android.media.audiopolicy.AudioPolicy build();
method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
+ method public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
method public android.media.audiopolicy.AudioPolicy.Builder setLooper(android.os.Looper) throws java.lang.IllegalArgumentException;
}
@@ -26481,85 +26532,6 @@
field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
}
- public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
- field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
- field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
- field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
- field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
- field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
- field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
- field public static final java.lang.String COLUMN_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 java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
- field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
- field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
- field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
- field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
- field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
- field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
- field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
- field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
- field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
- field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
- field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
- field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
- field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
- field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
- field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
- field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
- field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
- field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
- field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
- }
-
- 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";
}
@@ -26647,22 +26619,116 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_AUTHOR = "author";
+ field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+ field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+ field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+ field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+ field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+ field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+ field public static final java.lang.String COLUMN_LIVE = "live";
+ field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+ field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+ field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+ field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+ field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+ field public static final java.lang.String COLUMN_TYPE = "type";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -26691,32 +26757,126 @@
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 java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
- field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ 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
+ field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
}
public static final class TvContract.WatchedPrograms implements android.media.tv.TvContract.BaseTvColumns {
@@ -37300,14 +37460,15 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final java.lang.String WEIGHT = "font_weight";
}
public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -41782,6 +41943,7 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public final long getConnectTimeMillis();
+ method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
method public android.telecom.GatewayInfo getGatewayInfo();
@@ -44508,65 +44670,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);
}
@@ -44714,6 +44817,8 @@
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
public static final class Layout.Alignment extends java.lang.Enum {
@@ -44915,7 +45020,7 @@
method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
method public android.text.StaticLayout.Builder setIncludePad(boolean);
method public android.text.StaticLayout.Builder setIndents(int[], int[]);
- method public android.text.StaticLayout.Builder setJustify(boolean);
+ method public android.text.StaticLayout.Builder setJustificationMode(int);
method public android.text.StaticLayout.Builder setLineSpacing(float, float);
method public android.text.StaticLayout.Builder setMaxLines(int);
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -49995,7 +50100,7 @@
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public boolean getAllowEnterTransitionOverlap();
method public boolean getAllowReturnTransitionOverlap();
method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -52205,7 +52310,7 @@
method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
method public abstract deprecated boolean getPluginsEnabled();
method public abstract java.lang.String getSansSerifFontFamily();
- method public abstract boolean getSaveFormData();
+ method public abstract deprecated boolean getSaveFormData();
method public abstract deprecated boolean getSavePassword();
method public abstract java.lang.String getSerifFontFamily();
method public abstract java.lang.String getStandardFontFamily();
@@ -52260,7 +52365,7 @@
method public abstract deprecated void setPluginsEnabled(boolean);
method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
method public abstract void setSansSerifFontFamily(java.lang.String);
- method public abstract void setSaveFormData(boolean);
+ method public abstract deprecated void setSaveFormData(boolean);
method public abstract deprecated void setSavePassword(boolean);
method public abstract void setSerifFontFamily(java.lang.String);
method public abstract void setStandardFontFamily(java.lang.String);
@@ -52588,12 +52693,12 @@
public abstract class WebViewDatabase {
ctor public WebViewDatabase();
- method public abstract void clearFormData();
+ method public abstract deprecated void clearFormData();
method public abstract void clearHttpAuthUsernamePassword();
method public abstract deprecated void clearUsernamePassword();
method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
- method public abstract boolean hasFormData();
+ method public abstract deprecated boolean hasFormData();
method public abstract boolean hasHttpAuthUsernamePassword();
method public abstract deprecated boolean hasUsernamePassword();
method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -55093,7 +55198,7 @@
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
method public int getInputType();
- method public boolean getJustify();
+ method public int getJustificationMode();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
@@ -55188,7 +55293,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);
@@ -55206,7 +55311,7 @@
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
- method public void setJustify(boolean);
+ method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
method public void setLetterSpacing(float);
method public void setLineSpacing(float, float);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1bafe96..1effe9c 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -290,6 +290,10 @@
field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
}
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field public static final java.lang.String STYLE = "font_style";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 382f5fe..6db91be 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3580,7 +3580,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
@@ -4370,7 +4370,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public android.app.ActionBar getActionBar();
method public final android.content.Context getContext();
method public android.view.View getCurrentFocus();
@@ -7074,6 +7074,7 @@
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();
@@ -8921,7 +8922,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";
@@ -10684,6 +10684,7 @@
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+ field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -13292,7 +13293,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);
@@ -13826,8 +13827,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);
@@ -14438,6 +14439,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 {
@@ -16037,11 +16053,11 @@
ctor public UsbRequest();
method public boolean cancel();
method public void close();
- method public boolean enqueue(java.nio.ByteBuffer);
method public java.lang.Object getClientData();
method public android.hardware.usb.UsbEndpoint getEndpoint();
method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
method public deprecated boolean queue(java.nio.ByteBuffer, int);
+ method public boolean queue(java.nio.ByteBuffer);
method public void setClientData(java.lang.Object);
}
@@ -23112,6 +23128,7 @@
method public void setProfile(android.media.CamcorderProfile);
method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
method public void setVideoEncodingBitRate(int);
+ method public void setVideoEncodingProfileLevel(int, int);
method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -24653,85 +24670,6 @@
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
- public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
- field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
- field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
- field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
- field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
- field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
- field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
- field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
- field public static final java.lang.String COLUMN_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 java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
- field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
- field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
- field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
- field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
- field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
- field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
- field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
- field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
- field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
- field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
- field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
- field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
- field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
- field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
- field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
- field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
- field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
- field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
- field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
- field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
- }
-
- 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";
}
@@ -24818,22 +24756,116 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+ public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_AUTHOR = "author";
+ field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+ field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+ field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+ field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+ field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+ field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+ field public static final java.lang.String COLUMN_LIVE = "live";
+ field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+ field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+ field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+ field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+ field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+ field public static final java.lang.String COLUMN_TYPE = "type";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -24862,32 +24894,126 @@
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 java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
- field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
- field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ 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
+ field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
}
public final class TvInputInfo implements android.os.Parcelable {
@@ -34535,14 +34661,15 @@
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final java.lang.String STYLE = "font_style";
field public static final java.lang.String TTC_INDEX = "font_ttc_index";
field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ field public static final java.lang.String WEIGHT = "font_weight";
}
public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -38828,6 +38955,7 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public final long getConnectTimeMillis();
+ method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
method public android.telecom.GatewayInfo getGatewayInfo();
@@ -41258,65 +41386,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);
}
@@ -41464,6 +41533,8 @@
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+ field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
public static final class Layout.Alignment extends java.lang.Enum {
@@ -41665,7 +41736,7 @@
method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
method public android.text.StaticLayout.Builder setIncludePad(boolean);
method public android.text.StaticLayout.Builder setIndents(int[], int[]);
- method public android.text.StaticLayout.Builder setJustify(boolean);
+ method public android.text.StaticLayout.Builder setJustificationMode(int);
method public android.text.StaticLayout.Builder setLineSpacing(float, float);
method public android.text.StaticLayout.Builder setMaxLines(int);
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46918,7 +46989,7 @@
method public void clearFlags(int);
method public abstract void closeAllPanels();
method public abstract void closePanel(int);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public boolean getAllowEnterTransitionOverlap();
method public boolean getAllowReturnTransitionOverlap();
method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -49045,7 +49116,7 @@
method public abstract boolean getOffscreenPreRaster();
method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
method public abstract java.lang.String getSansSerifFontFamily();
- method public abstract boolean getSaveFormData();
+ method public abstract deprecated boolean getSaveFormData();
method public abstract deprecated boolean getSavePassword();
method public abstract java.lang.String getSerifFontFamily();
method public abstract java.lang.String getStandardFontFamily();
@@ -49094,7 +49165,7 @@
method public abstract deprecated void setPluginState(android.webkit.WebSettings.PluginState);
method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
method public abstract void setSansSerifFontFamily(java.lang.String);
- method public abstract void setSaveFormData(boolean);
+ method public abstract deprecated void setSaveFormData(boolean);
method public abstract deprecated void setSavePassword(boolean);
method public abstract void setSerifFontFamily(java.lang.String);
method public abstract void setStandardFontFamily(java.lang.String);
@@ -49385,12 +49456,12 @@
public abstract class WebViewDatabase {
ctor public WebViewDatabase();
- method public abstract void clearFormData();
+ method public abstract deprecated void clearFormData();
method public abstract void clearHttpAuthUsernamePassword();
method public abstract deprecated void clearUsernamePassword();
method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
- method public abstract boolean hasFormData();
+ method public abstract deprecated boolean hasFormData();
method public abstract boolean hasHttpAuthUsernamePassword();
method public abstract deprecated boolean hasUsernamePassword();
method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -51658,7 +51729,7 @@
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
method public int getInputType();
- method public boolean getJustify();
+ method public int getJustificationMode();
method public final android.text.method.KeyListener getKeyListener();
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
@@ -51753,7 +51824,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);
@@ -51771,7 +51842,7 @@
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void setInputType(int);
- method public void setJustify(boolean);
+ method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
method public void setLetterSpacing(float);
method public void setLineSpacing(float, float);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 42b2ae6..d20c08c 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -296,6 +296,10 @@
field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
}
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field public static final java.lang.String STYLE = "font_style";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 3a92b9e..0e2c13e 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -26,7 +26,8 @@
libGLESv1_CM \
libgui \
libOpenSLES \
- libtinyalsa
+ libtinyalsa \
+ libbase
LOCAL_MODULE:= bootanimation
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a6d2986..7394490 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -38,6 +38,8 @@
#include <utils/Log.h>
#include <utils/SystemClock.h>
+#include <android-base/properties.h>
+
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -67,6 +69,9 @@
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
+static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
+static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";
+
static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
static const char SYSTEM_TIME_DIR_NAME[] = "time";
static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
@@ -106,7 +111,13 @@
mSession = new SurfaceComposerClient();
// If the system has already booted, the animation is not being used for a boot.
- mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
+ mSystemBoot = !android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false);
+ std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
+ if (powerCtl.empty()) {
+ mShuttingDown = false;
+ } else {
+ mShuttingDown = true;
+ }
}
void BootAnimation::onFirstRef() {
@@ -314,16 +325,23 @@
char decrypt[PROPERTY_VALUE_MAX];
property_get("vold.decrypt", decrypt, "");
- bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
+ bool encryptedAnimation = atoi(decrypt) != 0 ||
+ !strcmp("trigger_restart_min_framework", decrypt);
- if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
+ if (!mShuttingDown && encryptedAnimation &&
+ (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
+ return NO_ERROR;
}
- else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) {
- mZipFileName = OEM_BOOTANIMATION_FILE;
- }
- else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) {
- mZipFileName = SYSTEM_BOOTANIMATION_FILE;
+ static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
+ static const char* shutdownFiles[] =
+ {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+
+ for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
+ if (access(f, R_OK) == 0) {
+ mZipFileName = f;
+ return NO_ERROR;
+ }
}
return NO_ERROR;
}
@@ -352,7 +370,8 @@
bool BootAnimation::android()
{
- ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
+ ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
@@ -878,7 +897,8 @@
const int animationX = (mWidth - animation.width) / 2;
const int animationY = (mHeight - animation.height) / 2;
- ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
+ ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
@@ -1047,7 +1067,9 @@
if (!mSystemBoot) {
return false;
}
-
+ if (mShuttingDown) { // no audio while shutting down
+ return false;
+ }
// Read the system property to see if we should play the sound.
// If it's not present, default to allowed.
if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
@@ -1073,7 +1095,7 @@
if (mTimeIsAccurate) {
return true;
}
-
+ if (mShuttingDown) return true;
struct stat statResult;
if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) {
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f1fc98e..181ef1c 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -163,6 +163,7 @@
bool mTimeIsAccurate;
bool mTimeFormat12Hour;
bool mSystemBoot;
+ bool mShuttingDown;
String8 mZipFileName;
SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread = nullptr;
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 7344ba7..469c964 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -1,7 +1,7 @@
service bootanim /system/bin/bootanimation
- class core
+ class core animation
user graphics
group graphics audio
disabled
oneshot
- writepid /dev/stune/top-app/tasks
\ No newline at end of file
+ writepid /dev/stune/top-app/tasks
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..c0505eb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2443,13 +2443,20 @@
}
/**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link #onCreate}.
+ * Finds a view that was identified by the {@code android:id} XML attribute
+ * that was processed in {@link #onCreate}.
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @return The view if found or null otherwise.
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
@Nullable
- public View findViewById(@IdRes int id) {
+ public <T extends View> T findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
@@ -4159,14 +4166,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/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d8e5742..7299d6b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -222,6 +222,7 @@
private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
private ContextImpl mSystemContext;
+ private ContextImpl mSystemUiContext;
static volatile IPackageManager sPackageManager;
@@ -2195,9 +2196,19 @@
}
}
+ public ContextImpl getSystemUiContext() {
+ synchronized (this) {
+ if (mSystemUiContext == null) {
+ mSystemUiContext = ContextImpl.createSystemUiContext(this);
+ }
+ return mSystemUiContext;
+ }
+ }
+
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
synchronized (this) {
getSystemContext().installSystemApplicationInfo(info, classLoader);
+ getSystemUiContext().installSystemApplicationInfo(info, classLoader);
// give ourselves a default profiler
mProfiler = new Profiler();
@@ -5036,6 +5047,11 @@
if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
systemTheme.rebase();
}
+
+ final Theme systemUiTheme = getSystemUiContext().getTheme();
+ if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
+ systemUiTheme.rebase();
+ }
}
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
@@ -5091,9 +5107,10 @@
// Trigger a regular Configuration change event, only with a different assetsSeq number
// so that we actually call through to all components.
+ // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to
+ // store configurations per-process.
Configuration newConfig = new Configuration();
- newConfig.unset();
- newConfig.assetsSeq = mConfiguration.assetsSeq + 1;
+ newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
handleConfigurationChanged(newConfig, null);
// Schedule all activities to reload
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 461f9cc..a6838f8b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1352,7 +1352,7 @@
public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
throws NameNotFoundException {
if (app.packageName.equals("system")) {
- return mContext.mMainThread.getSystemContext().getResources();
+ return mContext.mMainThread.getSystemUiContext().getResources();
}
final boolean sameUid = (app.uid == Process.myUid());
final Resources r = mContext.mMainThread.getTopLevelResources(
@@ -1383,7 +1383,7 @@
"Call does not support special user #" + userId);
}
if ("system".equals(appPackageName)) {
- return mContext.mMainThread.getSystemContext().getResources();
+ return mContext.mMainThread.getSystemUiContext().getResources();
}
try {
ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, sDefaultFlags, userId);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5a7246a..75f9d67 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2218,6 +2218,18 @@
return context;
}
+ /**
+ * System Context to be used for UI. This Context has resources that can be themed.
+ */
+ static ContextImpl createSystemUiContext(ActivityThread mainThread) {
+ LoadedApk packageInfo = new LoadedApk(mainThread);
+ ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
+ null);
+ context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
+ packageInfo.getCompatibilityInfo()));
+ return context;
+ }
+
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 72ccf72..943c572 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -498,14 +498,22 @@
}
/**
- * Finds a child view with the given identifier. Returns null if the
- * specified child view does not exist or the dialog has not yet been fully
- * created (for example, via {@link #show()} or {@link #create()}).
+ * Finds the first descendant view with the given ID or {@code null} if the
+ * ID is invalid (< 0), there is no matching view in the hierarchy, or the
+ * dialog has not yet been fully created (for example, via {@link #show()}
+ * or {@link #create()}).
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @param id the identifier of the view to find
- * @return The view with the given id or null.
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
- public @Nullable View findViewById(@IdRes int id) {
+ @Nullable
+ public <T extends View> T findViewById(@IdRes int id) {
return mWindow.findViewById(id);
}
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 462f66f..b89c165 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -321,6 +322,11 @@
*/
public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
+ /** {@hide} */
+ @SystemApi
+ public static final String ACTION_DOWNLOAD_COMPLETED =
+ "android.intent.action.DOWNLOAD_COMPLETED";
+
/**
* columns to request from DownloadProvider.
* @hide
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 279b900..399987f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1128,8 +1128,13 @@
newState = Fragment.CREATED;
}
if (f.mRemoving && newState > f.mState) {
- // While removing a fragment, we can't change it to a higher state.
- newState = f.mState;
+ if (f.mState == Fragment.INITIALIZING && f.isInBackStack()) {
+ // Allow the fragment to be created so that it can be saved later.
+ newState = Fragment.CREATED;
+ } else {
+ // While removing a fragment, we can't change it to a higher state.
+ newState = f.mState;
+ }
}
// Defer start if requested; don't allow it to move to STARTED or higher
// if it's not already started.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3d66135..161dd25 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3793,9 +3793,9 @@
// Ambient view does not have these
bindHeaderText(contentView);
bindHeaderChronometerAndTime(contentView);
- bindExpandButton(contentView);
bindProfileBadge(contentView);
}
+ bindExpandButton(contentView);
}
private void bindExpandButton(RemoteViews contentView) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index b42df5e..489a0f0 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -984,7 +984,7 @@
final ResourcesKey key = mResourceImpls.keyAt(i);
final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
- if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
+ if (impl != null && (key.mResDir == null || key.mResDir.equals(baseCodePath))) {
updatedResourceKeys.put(impl, new ResourcesKey(
key.mResDir,
key.mSplitResDirs,
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/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2f0a630..82ad825 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -697,8 +697,8 @@
"android.app.extra.PROVISIONING_ORGANIZATION_NAME";
/**
- * A String extra holding a url to the website of the device's provider. The website can be
- * opened in a browser during provisioning.
+ * A String extra holding a url to the website of the device provider so the user can open it
+ * during provisioning. If the url is not HTTPS, an error will be shown.
*
* <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}
*
@@ -2768,9 +2768,11 @@
* or clears the lockscreen password.
* <p>
* <em>This token is highly sensitive and should be treated at the same level as user
- * credentials. In particular, NEVER store this token on device in plaintext, especially in
- * Device-Encrypted storage if the token will be used to reset password on FBE devices before
- * user unlocks.
+ * credentials. In particular, NEVER store this token on device in plaintext. Do not store
+ * the plaintext token in device-encrypted storage if it will be needed to reset password on
+ * file-based encryption devices before user unlocks. Consider carefully how any password token
+ * will be stored on your server and who will need access to them. Tokens may be the subject of
+ * legal access requests.
* </em>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 7d2db5c..fe51633 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -27,9 +27,6 @@
import android.view.ViewStructure.HtmlInfo.Builder;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -920,15 +917,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
- @Deprecated
- public AutoFillId getAutoFillId() {
- return AutoFillId.forDaRealId(mAutofillId);
- }
-
- /**
* Gets the id that can be used to autofill the view contents.
*
* <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
@@ -939,26 +927,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
- */
- @Deprecated
- public AutoFillType getAutoFillType() {
- switch (getAutofillType()) {
- case View.AUTOFILL_TYPE_TEXT:
- return AutoFillType.forText();
- case View.AUTOFILL_TYPE_TOGGLE:
- return AutoFillType.forToggle();
- case View.AUTOFILL_TYPE_LIST:
- return AutoFillType.forList();
- case View.AUTOFILL_TYPE_DATE:
- return AutoFillType.forDate();
- default:
- return null;
- }
- }
-
- /**
* Gets the the type of value that can be used to autofill the view contents.
*
* <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
@@ -982,15 +950,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
- @Deprecated
- public AutoFillValue getAutoFillValue() {
- return AutoFillValue.forDaRealValue(mAutofillValue);
- }
-
- /**
* Gets the the value of this view.
*
* <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 74a39e8..9f35e85 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -710,9 +710,9 @@
* user may have a corporate profile. In this case the parent user profile has a
* child profile, the corporate one.
*
- * @param profile The profile for which to get providers. Passing null is equivaled
- * to passing only the current user handle.
- * @return The intalled providers.
+ * @param profile The profile for which to get providers. Passing null is equivalent
+ * to querying for only the calling user.
+ * @return The installed providers.
*
* @see android.os.Process#myUserHandle()
* @see android.os.UserManager#getUserProfiles()
@@ -722,7 +722,31 @@
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
- profile);
+ profile, null);
+ }
+
+ /**
+ * Gets the AppWidget providers for the given package and user profile. User
+ * profile can only be the current user or a profile of the current user. For
+ * example, the current user may have a corporate profile. In this case the
+ * parent user profile has a child profile, the corporate one.
+ *
+ * @param packageName The package for which to get providers. If null, this method is
+ * equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}.
+ * @param profile The profile for which to get providers. Passing null is equivalent
+ * to querying for only the calling user.
+ * @return The installed providers.
+ *
+ * @see android.os.Process#myUserHandle()
+ * @see android.os.UserManager#getUserProfiles()
+ */
+ public List<AppWidgetProviderInfo> getInstalledProvidersForPackage(@Nullable String packageName,
+ @Nullable UserHandle profile) {
+ if (mService == null) {
+ return Collections.emptyList();
+ }
+ return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+ profile, packageName);
}
/**
@@ -733,7 +757,7 @@
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
- null);
+ null, null);
}
/**
@@ -752,7 +776,7 @@
if (mService == null) {
return Collections.emptyList();
}
- return getInstalledProvidersForProfile(categoryFilter, null);
+ return getInstalledProvidersForProfile(categoryFilter, null, null);
}
/**
@@ -766,6 +790,7 @@
* @param profile A profile of the current user which to be queried. The user
* is itself also a profile. If null, the providers only for the current user
* are returned.
+ * @param packageName If specified, will only return providers from the given package.
* @return The intalled providers.
*
* @see android.os.Process#myUserHandle()
@@ -774,7 +799,7 @@
* @hide
*/
public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
- UserHandle profile) {
+ @Nullable UserHandle profile, @Nullable String packageName) {
if (mService == null) {
return Collections.emptyList();
}
@@ -785,7 +810,7 @@
try {
ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
- categoryFilter, profile.getIdentifier());
+ categoryFilter, profile.getIdentifier(), packageName);
if (providers == null) {
return Collections.emptyList();
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index dbbfe30..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
*/
@@ -4631,4 +4626,18 @@
public Handler getMainThreadHandler() {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
+
+ /**
+ * Throws an exception if the Context is using system resources,
+ * which are non-runtime-overlay-themable and may show inconsistent UI.
+ * @hide
+ */
+ public void assertRuntimeOverlayThemable() {
+ // Resources.getSystem() is a singleton and the only Resources not managed by
+ // ResourcesManager; therefore Resources.getSystem() is not themable.
+ if (getResources() == Resources.getSystem()) {
+ throw new IllegalArgumentException("Non-UI context used to display UI; "
+ + "get a UI context from ActivityThread#getSystemUiContext()");
+ }
+ }
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index da887af..5415eb5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1505,22 +1505,38 @@
public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
/**
- * Activity Action: Launch ephemeral installer.
- * <p>
- * Input: The data must be a http: URI that the ephemeral application is registered
- * to handle.
+ * @hide
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_INSTALL_INSTANT_APP_PACKAGE}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
+ = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ /**
+ * Activity Action: Launch instant application installer.
* <p class="note">
* This is a protected intent that can only be sent by the system.
* </p>
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
- = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ public static final String ACTION_INSTALL_INSTANT_APP_PACKAGE
+ = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
/**
- * Service Action: Resolve ephemeral application.
+ * @hide
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_RESOLVE_INSTANT_APP_PACKAGE}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
+ = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ /**
+ * Service Action: Resolve instant application.
* <p>
* The system will have a persistent connection to this service.
* This is a protected intent that can only be sent by the system.
@@ -1528,12 +1544,22 @@
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.SERVICE_ACTION)
- public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
- = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE
+ = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
/**
- * Activity Action: Launch ephemeral settings.
+ * @hide
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_INSTANT_APP_RESOLVER_SETTINGS}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
+ = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+ /**
+ * Activity Action: Launch instant app settings.
*
* <p class="note">
* This is a protected intent that can only be sent by the system.
@@ -1541,9 +1567,10 @@
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
- = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+ public static final String ACTION_INSTANT_APP_RESOLVER_SETTINGS
+ = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
/**
* Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
@@ -3479,6 +3506,261 @@
public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
/**
+ * Broadcast Action: indicate that the phone service state has changed.
+ * The intent will have the following extra values:</p>
+ * <p>
+ * @see #EXTRA_VOICE_REG_STATE
+ * @see #EXTRA_DATA_REG_STATE
+ * @see #EXTRA_VOICE_ROAMING_TYPE
+ * @see #EXTRA_DATA_ROAMING_TYPE
+ * @see #EXTRA_OPERATOR_ALPHA_LONG
+ * @see #EXTRA_OPERATOR_ALPHA_SHORT
+ * @see #EXTRA_OPERATOR_NUMERIC
+ * @see #EXTRA_DATA_OPERATOR_ALPHA_LONG
+ * @see #EXTRA_DATA_OPERATOR_ALPHA_SHORT
+ * @see #EXTRA_DATA_OPERATOR_NUMERIC
+ * @see #EXTRA_MANUAL
+ * @see #EXTRA_VOICE_RADIO_TECH
+ * @see #EXTRA_DATA_RADIO_TECH
+ * @see #EXTRA_CSS_INDICATOR
+ * @see #EXTRA_NETWORK_ID
+ * @see #EXTRA_SYSTEM_ID
+ * @see #EXTRA_CDMA_ROAMING_INDICATOR
+ * @see #EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR
+ * @see #EXTRA_EMERGENCY_ONLY
+ * @see #EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION
+ * @see #EXTRA_IS_USING_CARRIER_AGGREGATION
+ * @see #EXTRA_LTE_EARFCN_RSRP_BOOST
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
+
+ /**
+ * An int extra used with {@link #ACTION_SERVICE_STATE} which indicates voice registration
+ * state.
+ * @see android.telephony.ServiceState#STATE_EMERGENCY_ONLY
+ * @see android.telephony.ServiceState#STATE_IN_SERVICE
+ * @see android.telephony.ServiceState#STATE_OUT_OF_SERVICE
+ * @see android.telephony.ServiceState#STATE_POWER_OFF
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_VOICE_REG_STATE = "voiceRegState";
+
+ /**
+ * An int extra used with {@link #ACTION_SERVICE_STATE} which indicates data registration state.
+ * @see android.telephony.ServiceState#STATE_EMERGENCY_ONLY
+ * @see android.telephony.ServiceState#STATE_IN_SERVICE
+ * @see android.telephony.ServiceState#STATE_OUT_OF_SERVICE
+ * @see android.telephony.ServiceState#STATE_POWER_OFF
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_REG_STATE = "dataRegState";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which indicates the voice roaming
+ * type.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_VOICE_ROAMING_TYPE = "voiceRoamingType";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which indicates the data roaming
+ * type.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_ROAMING_TYPE = "dataRoamingType";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered voice operator name in long alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_OPERATOR_ALPHA_LONG = "operator-alpha-long";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered voice operator name in short alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_OPERATOR_ALPHA_SHORT = "operator-alpha-short";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} containing the MCC
+ * (Mobile Country Code, 3 digits) and MNC (Mobile Network code, 2-3 digits) for the mobile
+ * network.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_OPERATOR_NUMERIC = "operator-numeric";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered data operator name in long alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+ * registered data operator name in short alphanumeric format.
+ * {@code null} if the operator name is not known or unregistered.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_OPERATOR_ALPHA_SHORT = "data-operator-alpha-short";
+
+ /**
+ * A string extra used with {@link #ACTION_SERVICE_STATE} containing the MCC
+ * (Mobile Country Code, 3 digits) and MNC (Mobile Network code, 2-3 digits) for the
+ * data operator.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_OPERATOR_NUMERIC = "data-operator-numeric";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates whether the current
+ * network selection mode is manual.
+ * Will be {@code true} if manual mode, {@code false} if automatic mode.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_MANUAL = "manual";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the current voice
+ * radio technology.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_VOICE_RADIO_TECH = "radioTechnology";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the current data
+ * radio technology.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_DATA_RADIO_TECH = "dataRadioTechnology";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which represents concurrent service
+ * support on CDMA network.
+ * Will be {@code true} if support, {@code false} otherwise.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_CSS_INDICATOR = "cssIndicator";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the CDMA network
+ * id. {@code Integer.MAX_VALUE} if unknown.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_NETWORK_ID = "networkId";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the CDMA system id.
+ * {@code Integer.MAX_VALUE} if unknown.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_SYSTEM_ID = "systemId";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} represents the TSB-58 roaming
+ * indicator if registered on a CDMA or EVDO system or {@code -1} if not.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} represents the default roaming
+ * indicator from the PRL if registered on a CDMA or EVDO system {@code -1} if not.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates if under emergency
+ * only mode.
+ * {@code true} if in emergency only mode, {@code false} otherwise.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates whether data network
+ * registration state is roaming.
+ * {@code true} if registration indicates roaming, {@code false} otherwise
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION =
+ "isDataRoamingFromRegistration";
+
+ /**
+ * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates if carrier
+ * aggregation is in use.
+ * {@code true} if carrier aggregation is in use, {@code false} otherwise.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_IS_USING_CARRIER_AGGREGATION = "isUsingCarrierAggregation";
+
+ /**
+ * An integer extra used with {@link #ACTION_SERVICE_STATE} representing the offset which
+ * is reduced from the rsrp threshold while calculating signal strength level.
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
+
+ /**
* The name of the extra used to define the text to be processed, as a
* CharSequence. Note that this may be a styled CharSequence, so you must use
* {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to retrieve it.
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 912ce3d..4d76755 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -419,7 +419,7 @@
*/
private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
- Log.e(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
+ Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
}
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 136c13b..50e3e68 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1688,6 +1688,10 @@
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
+ /** {@hide} */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CTS = "android.software.cts";
+
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports one or more methods of
@@ -2158,7 +2162,6 @@
* {@link #hasSystemFeature}: The device supports only leanback UI. Only
* applications designed for this experience should be run, though this is
* not enforced by the system.
- * @hide
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
@@ -6244,7 +6247,7 @@
* Return the {@link ComponentName} of the activity providing Settings for the Instant App
* resolver.
*
- * @see {@link android.content.intent#ACTION_EPHEMERAL_RESOLVER_SETTINGS}
+ * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
* @hide
*/
@SystemApi
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index b276008..e845359 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -102,6 +102,16 @@
int displayId, DisplayInfo info);
/**
+ * Get current display info without override from WindowManager.
+ * Current implementation of LogicalDisplay#getDisplayInfoLocked() always returns display info
+ * with overrides from WM if set. This method can be used for getting real display size without
+ * overrides to determine if real changes to display metrics happened.
+ * @param displayId Id of the target display.
+ * @param outInfo {@link DisplayInfo} to fill.
+ */
+ public abstract void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo);
+
+ /**
* Called by the window manager to perform traversals while holding a
* surface flinger transaction.
*/
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index badb344..239a2df 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -60,9 +60,11 @@
// Prevent the connection from being finalized
private UsbDeviceConnection mConnection;
- /** Whether this buffer was {@link #enqueue enqueued (new behavior)} or {@link #queue queued
- * (deprecared behavior)}. */
- private boolean mIsUsingEnqueue;
+ /**
+ * Whether this buffer was {@link #queue(ByteBuffer) queued using the new behavior} or
+ * {@link #queue(ByteBuffer, int) queued using the deprecated behavior}.
+ */
+ private boolean mIsUsingNewQueue;
/** Temporary buffer than might be used while buffer is enqueued */
private ByteBuffer mTempBuffer;
@@ -172,7 +174,7 @@
*
* @return true if the queueing operation succeeded
*
- * @deprecated Use {@link #enqueue(ByteBuffer)} instead.
+ * @deprecated Use {@link #queue(ByteBuffer)} instead.
*/
@Deprecated
public boolean queue(ByteBuffer buffer, int length) {
@@ -219,23 +221,23 @@
*
* @return true if the queueing operation succeeded
*/
- public boolean enqueue(@Nullable ByteBuffer buffer) {
+ public boolean queue(@Nullable ByteBuffer buffer) {
// Request need to be initialized
Preconditions.checkState(mNativeContext != 0, "request is not initialized");
- // Request can not be currently enqueued
- Preconditions.checkState(!mIsUsingEnqueue, "request is currently enqueued");
+ // Request can not be currently queued
+ Preconditions.checkState(!mIsUsingNewQueue, "this request is currently queued");
boolean isSend = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
- boolean wasEnqueued;
+ boolean wasQueued;
synchronized (mLock) {
mBuffer = buffer;
if (buffer == null) {
// Null buffers enqueue empty USB requests which is supported
- mIsUsingEnqueue = true;
- wasEnqueued = native_enqueue(null, 0, 0);
+ mIsUsingNewQueue = true;
+ wasQueued = native_queue(null, 0, 0);
} else {
// Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
@@ -260,18 +262,18 @@
buffer = mTempBuffer;
}
- mIsUsingEnqueue = true;
- wasEnqueued = native_enqueue(buffer, buffer.position(), buffer.remaining());
+ mIsUsingNewQueue = true;
+ wasQueued = native_queue(buffer, buffer.position(), buffer.remaining());
}
}
- if (!wasEnqueued) {
- mIsUsingEnqueue = false;
+ if (!wasQueued) {
+ mIsUsingNewQueue = false;
mTempBuffer = null;
mBuffer = null;
}
- return wasEnqueued;
+ return wasQueued;
}
/* package */ void dequeue() {
@@ -279,9 +281,9 @@
int bytesTransferred;
synchronized (mLock) {
- if (mIsUsingEnqueue) {
+ if (mIsUsingNewQueue) {
bytesTransferred = native_dequeue_direct();
- mIsUsingEnqueue = false;
+ mIsUsingNewQueue = false;
if (mBuffer == null) {
// Nothing to do
@@ -332,7 +334,7 @@
private native boolean native_init(UsbDeviceConnection connection, int ep_address,
int ep_attributes, int ep_max_packet_size, int ep_interval);
private native void native_close();
- private native boolean native_enqueue(ByteBuffer buffer, int offset, int length);
+ private native boolean native_queue(ByteBuffer buffer, int offset, int length);
private native boolean native_queue_array(byte[] buffer, int length, boolean out);
private native int native_dequeue_array(byte[] buffer, int length, boolean out);
private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out);
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 495340d..63bbd96 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -38,9 +38,6 @@
boolean isUidForeground(int uid);
- /** Higher priority listener before general event dispatch */
- void setConnectivityListener(INetworkPolicyListener listener);
-
void registerListener(INetworkPolicyListener listener);
void unregisterListener(INetworkPolicyListener listener);
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index e5d73e0..b5af766 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -59,19 +59,14 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.FuseAppLoop;
-import com.android.internal.os.FuseAppLoop.UnmountedException;
import com.android.internal.os.FuseUnavailableMountException;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -84,7 +79,6 @@
import java.util.Objects;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
-import libcore.io.IoUtils;
/**
* StorageManager is the interface to the systems storage service. The storage
@@ -186,15 +180,6 @@
private static volatile IStorageManager sStorageManager = null;
- // TODO: the location of the primary storage block varies from device to device, so we need to
- // try the most likely candidates - a long-term solution would be a device-specific vold
- // function that returns the calculated size.
- private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
- "/sys/block/mmcblk0/size",
- "/sys/block/sda/size"
- };
- private static final int INTERNAL_STORAGE_SECTOR_SIZE = 512;
-
private final Context mContext;
private final ContentResolver mResolver;
@@ -1011,38 +996,13 @@
/** {@hide} */
public static Pair<String, Long> getPrimaryStoragePathAndSize() {
- for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
- final long numberBlocks = readLong(path);
- if (numberBlocks > 0) {
- return new Pair<>(path,
- FileUtils.roundStorageSize(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
- }
- }
- return null;
+ return Pair.create(null,
+ FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace()));
}
-
/** {@hide} */
public long getPrimaryStorageSize() {
- final Pair<String, Long> pair = getPrimaryStoragePathAndSize();
- return pair == null ? 0 : pair.second.longValue();
- }
-
- private static long readLong(String path) {
- try (final FileInputStream fis = new FileInputStream(path);
- final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
- return Long.parseLong(reader.readLine());
- } catch (FileNotFoundException e) {
- // This is expected since we are trying to parse multiple paths.
- Slog.i(TAG, "readLong(): Path doesn't exist: " + path + ": " + e);
- return 0;
- } catch (NumberFormatException e) {
- Slog.e(TAG, "readLong(): Could not parse " + path + ": " + e);
- return 0;
- } catch (Exception e) {
- Slog.e(TAG, "readLong(): Unknown exception while opening " + path + ": " + e);
- return 0;
- }
+ return FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace());
}
/** @removed */
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index a280e59..9d83bd7 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -114,7 +114,7 @@
* download's content: uri is specified in the intent's data.
*/
public static final String ACTION_DOWNLOAD_COMPLETED =
- "android.intent.action.DOWNLOAD_COMPLETED";
+ DownloadManager.ACTION_DOWNLOAD_COMPLETED;
/**
* Broadcast Action: this is sent by the download manager to the app
@@ -127,7 +127,7 @@
* successfully.
*/
public static final String ACTION_NOTIFICATION_CLICKED =
- "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
+ DownloadManager.ACTION_NOTIFICATION_CLICKED;
/**
* The name of the column containing the URI of the data being downloaded.
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index fd9d4db..4deb4ab 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -72,15 +72,28 @@
*/
public static final String VARIATION_SETTINGS = "font_variation_settings";
/**
- * Constant used to request data from a font provider. The cursor returned from the query
- * should have this column populated with the int style for the resulting font. This should
- * be one of {@link android.graphics.Typeface#NORMAL},
- * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC} or
- * {@link android.graphics.Typeface#BOLD_ITALIC}
+ * DO NOT USE THIS COLUMN.
+ * This column is kept for preventing demo apps.
+ * TODO: Remove once nobody uses this column.
+ * @hide
+ * @removed
*/
public static final String STYLE = "font_style";
/**
* Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated with the int weight for the resulting font. This value
+ * should be between 100 and 900. The most common values are 400 for regular weight and 700
+ * for bold weight.
+ */
+ public static final String WEIGHT = "font_weight";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated with the int italic for the resulting font. This should
+ * be 0 for regular style and 1 for italic.
+ */
+ public static final String ITALIC = "font_italic";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
* should have this column populated to indicate the result status of the
* query. This will be checked before any other data in the cursor. Possible values are
* {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND},
@@ -274,7 +287,7 @@
.build();
try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE,
- Columns.RESULT_CODE },
+ Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
"query = ?", new String[] { request.getQuery() }, null);) {
// TODO: Should we restrict the amount of fonts that can be returned?
// TODO: Write documentation explaining that all results should be from the same family.
@@ -285,6 +298,8 @@
final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID);
final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX);
final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
+ final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT);
+ final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC);
final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
while (cursor.moveToNext()) {
resultCode = resultCodeColumnIndex != -1
@@ -313,9 +328,22 @@
? cursor.getInt(ttcIndexColumnIndex) : 0;
final String variationSettings = vsColumnIndex != -1
? cursor.getString(vsColumnIndex) : null;
- final int style = styleColumnIndex != -1
- ? cursor.getInt(styleColumnIndex) : Typeface.NORMAL;
- result.add(new FontResult(pfd, ttcIndex, variationSettings, style));
+ // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
+ int weight;
+ boolean italic;
+ if (weightColumnIndex != -1 && italicColumnIndex != -1) {
+ weight = cursor.getInt(weightColumnIndex);
+ italic = cursor.getInt(italicColumnIndex) == 1;
+ } else if (styleColumnIndex != -1) {
+ final int style = cursor.getInt(styleColumnIndex);
+ weight = (style & Typeface.BOLD) != 0 ? 700 : 400;
+ italic = (style & Typeface.ITALIC) != 0;
+ } else {
+ weight = 400;
+ italic = false;
+ }
+ result.add(
+ new FontResult(pfd, ttcIndex, variationSettings, weight, italic));
} catch (FileNotFoundException e) {
Log.e(TAG, "FileNotFoundException raised when interacting with content "
+ "provider " + authority, e);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e2100bd..660d53a 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10324,6 +10324,10 @@
INSTANT_APP_SETTINGS.add(DEVELOPMENT_FORCE_RTL);
INSTANT_APP_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES);
INSTANT_APP_SETTINGS.add(AIRPLANE_MODE_ON);
+ INSTANT_APP_SETTINGS.add(WINDOW_ANIMATION_SCALE);
+ INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE);
+ INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE);
+ INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES);
}
/**
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
deleted file mode 100644
index c26f679..0000000
--- a/core/java/android/service/autofill/AutoFillService.java
+++ /dev/null
@@ -1,24 +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.service.autofill;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use AutofillService
- */
-@Deprecated
-public abstract class AutoFillService extends AutofillService {
-}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 6f17d0e..9f8a621 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -71,7 +71,7 @@
* Name under which a AutoFillService component publishes information about itself.
* This meta-data should reference an XML resource containing a
* <code><{@link
- * android.R.styleable#AutoFillService autofill-service}></code> tag.
+ * android.R.styleable#AutofillService autofill-service}></code> tag.
* This is a a sample XML file configuring an AutoFillService:
* <pre> <autofill-service
* android:settingsActivity="foo.bar.SettingsActivity"
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index f6d40db..0f4824e 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -36,7 +36,6 @@
import java.io.IOException;
-// TODO(b/33197203 , b/33802548): add CTS tests
/**
* {@link ServiceInfo} and meta-data about an {@link AutofillService}.
*
@@ -75,15 +74,8 @@
mServiceInfo = si;
final TypedArray metaDataArray = getMetaDataArray(pm, si);
if (metaDataArray != null) {
- // TODO(b/35956626): inline newSettingsActivity once clients migrate
- final String newSettingsActivity =
- metaDataArray.getString(R.styleable.AutofillService_settingsActivity);
- if (newSettingsActivity != null) {
- mSettingsActivity = newSettingsActivity;
- } else {
- mSettingsActivity =
- metaDataArray.getString(R.styleable.AutoFillService_settingsActivity);
- }
+ mSettingsActivity = metaDataArray
+ .getString(R.styleable.AutofillService_settingsActivity);
metaDataArray.recycle();
} else {
mSettingsActivity = null;
@@ -96,16 +88,11 @@
@Nullable
private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) {
// Check for permissions.
- // TODO(b/35956626): remove check for BIND_AUTO_FILL once clients migrate
- if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)
- && !Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
+ if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)) {
Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTOFILL);
return null;
}
- // TODO(b/35956626): remove once clients migrate
- final boolean oldStyle = !Manifest.permission.BIND_AUTOFILL.equals(si.permission);
-
// Get the AutoFill metadata, if declared.
XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA);
if (parser == null) {
@@ -141,8 +128,7 @@
return null;
}
- return oldStyle ? res.obtainAttributes(attrs, R.styleable.AutoFillService)
- : res.obtainAttributes(attrs, R.styleable.AutofillService);
+ return res.obtainAttributes(attrs, R.styleable.AutofillService);
} finally {
parser.close();
}
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index e27fa06..e77bd0d 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -23,8 +23,6 @@
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;
@@ -78,11 +76,6 @@
}
/** @hide */
- public @Nullable RemoteViews getPresentation() {
- return mPresentation;
- }
-
- /** @hide */
public @Nullable IntentSender getAuthentication() {
return mAuthentication;
}
@@ -180,15 +173,6 @@
}
/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use other setValue()
- */
- @Deprecated
- public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
- return setValue(id.getDaRealId(), value.getDaRealValue());
- }
-
- /**
* Sets the value of a field.
*
* @param id id returned by {@link
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 6213d27..95608a5 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -25,7 +25,6 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -269,26 +268,6 @@
return this;
}
-
- /**
- * @hide
- */
- // TODO(b/33197203): temporary fix to runtime crash
- public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
- throwIfDestroyed();
-
- if (ids == null || ids.length == 0) {
- return this;
- }
- if (mRequiredIds == null) {
- mRequiredIds = new AutofillId[ids.length];
- }
- for (int i = 0; i < ids.length; i++) {
- mRequiredIds[i] = ids[i].getDaRealId();
- }
- return this;
- }
-
/**
* Sets an optional description to be shown in the UI when the user is asked to save.
*
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 1e9deeb..6208c53 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -85,7 +85,7 @@
this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
spacingmult, spacingadd, includepad,
StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE,
- false /* justify */, ellipsize, ellipsizedWidth);
+ Layout.JUSTIFICATION_MODE_NONE, ellipsize, ellipsizedWidth);
}
/**
@@ -102,7 +102,7 @@
int width, Alignment align, TextDirectionHeuristic textDir,
float spacingmult, float spacingadd,
boolean includepad, int breakStrategy, int hyphenationFrequency,
- boolean justify, TextUtils.TruncateAt ellipsize,
+ int justificationMode, TextUtils.TruncateAt ellipsize,
int ellipsizedWidth) {
super((ellipsize == null)
? display
@@ -128,7 +128,7 @@
mIncludePad = includepad;
mBreakStrategy = breakStrategy;
- mJustify = justify;
+ mJustificationMode = justificationMode;
mHyphenationFrequency = hyphenationFrequency;
/*
@@ -303,7 +303,7 @@
.setEllipsize(mEllipsizeAt)
.setBreakStrategy(mBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency)
- .setJustify(mJustify);
+ .setJustificationMode(mJustificationMode);
reflowed.generate(b, false, true);
int n = reflowed.getLineCount();
// If the new layout has a blank line at the end, but it is not
@@ -811,7 +811,7 @@
private TextUtils.TruncateAt mEllipsizeAt;
private int mBreakStrategy;
private int mHyphenationFrequency;
- private boolean mJustify;
+ private int mJustificationMode;
private PackedIntVector mInts;
private PackedObjectVector<Directions> mObjects;
diff --git a/core/java/android/text/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/android/view/autofill/AutoFillId.aidl b/core/java/android/text/FontVariationAxis.aidl
similarity index 83%
rename from core/java/android/view/autofill/AutoFillId.aidl
rename to core/java/android/text/FontVariationAxis.aidl
index fc57ce7..d5d52c2 100644
--- a/core/java/android/view/autofill/AutoFillId.aidl
+++ b/core/java/android/text/FontVariationAxis.aidl
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-package android.view.autofill;
+package android.text;
-// @deprecated TODO(b/35956626): remove once clients use AutofillId
-parcelable AutoFillId;
\ No newline at end of file
+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/Display.java b/core/java/android/view/Display.java
index 5494377..6dedbde 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -50,7 +50,7 @@
* <li>The real display area specifies the part of the display that contains content
* including the system decorations. Even so, the real display area may be smaller than the
* physical size of the display if the window manager is emulating a smaller display
- * using (adb shell am display-size). Use the following methods to query the
+ * using (adb shell wm size). Use the following methods to query the
* real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
* </ul>
* </p><p>
@@ -947,7 +947,7 @@
* The size is adjusted based on the current rotation of the display.
* </p><p>
* The real size may be smaller than the physical size of the screen when the
- * window manager is emulating a smaller display (using adb shell am display-size).
+ * window manager is emulating a smaller display (using adb shell wm size).
* </p>
*
* @param outSize Set to the real size of the display.
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index ae1ee42..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>();
@@ -118,7 +120,7 @@
* @return the "effective" root of {@param focused}
*/
private ViewGroup getEffectiveRoot(ViewGroup root, View focused) {
- if (focused == null) {
+ if (focused == null || focused == root) {
return root;
}
ViewParent effective = focused.getParent();
@@ -150,6 +152,12 @@
@Nullable View currentCluster,
@View.FocusDirection int direction) {
View next = null;
+ if (currentCluster != null) {
+ next = findNextUserSpecifiedKeyboardNavigationCluster(root, currentCluster, direction);
+ if (next != null) {
+ return next;
+ }
+ }
final ArrayList<View> clusters = mTempList;
try {
@@ -165,6 +173,16 @@
return next;
}
+ private View findNextUserSpecifiedKeyboardNavigationCluster(View root, View currentCluster,
+ int direction) {
+ View userSetNextCluster =
+ currentCluster.findUserSetNextKeyboardNavigationCluster(root, direction);
+ if (userSetNextCluster != null && userSetNextCluster.hasFocusable()) {
+ return userSetNextCluster;
+ }
+ return null;
+ }
+
private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
// check for user specified next focus
View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
@@ -238,6 +256,13 @@
View currentCluster,
List<View> clusters,
@View.FocusDirection int direction) {
+ try {
+ // Note: This sort is stable.
+ mUserSpecifiedClusterComparator.setFocusables(clusters);
+ Collections.sort(clusters, mUserSpecifiedClusterComparator);
+ } finally {
+ mUserSpecifiedClusterComparator.recycle();
+ }
final int count = clusters.size();
switch (direction) {
@@ -802,6 +827,15 @@
private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
+ private final NextIdGetter mNextIdGetter;
+
+ public interface NextIdGetter {
+ int get(View view);
+ }
+
+ UserSpecifiedFocusComparator(NextIdGetter nextIdGetter) {
+ mNextIdGetter = nextIdGetter;
+ }
public void recycle() {
mFocusables.clear();
@@ -810,14 +844,14 @@
mOriginalOrdinal.clear();
}
- public void setFocusables(ArrayList<View> focusables) {
+ public void setFocusables(List<View> focusables) {
for (int i = focusables.size() - 1; i >= 0; i--) {
final View view = focusables.get(i);
final int id = view.getId();
if (isValidId(id)) {
mFocusables.put(id, view);
}
- final int nextId = view.getNextFocusForwardId();
+ final int nextId = mNextIdGetter.get(view);
if (isValidId(nextId)) {
mIsConnectedTo.put(nextId, true);
}
@@ -825,7 +859,7 @@
for (int i = focusables.size() - 1; i >= 0; i--) {
final View view = focusables.get(i);
- final int nextId = view.getNextFocusForwardId();
+ final int nextId = mNextIdGetter.get(view);
if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
setHeadOfChain(view);
}
@@ -838,7 +872,7 @@
private void setHeadOfChain(View head) {
for (View view = head; view != null;
- view = mFocusables.get(view.getNextFocusForwardId())) {
+ view = mFocusables.get(mNextIdGetter.get(view))) {
final View otherHead = mHeadsOfChains.get(view);
if (otherHead != null) {
if (otherHead == head) {
@@ -866,7 +900,7 @@
return -1; // first is the head, it should be first
} else if (second == firstHead) {
return 1; // second is the head, it should be first
- } else if (isValidId(first.getNextFocusForwardId())) {
+ } else if (isValidId(mNextIdGetter.get(first))) {
return -1; // first is not the end of the chain
} else {
return 1; // first is end of chain
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b12a767..4ffcd95 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -707,13 +707,16 @@
* @attr ref android.R.styleable#View_isScrollContainer
* @attr ref android.R.styleable#View_focusable
* @attr ref android.R.styleable#View_focusableInTouchMode
+ * @attr ref android.R.styleable#View_focusedByDefault
* @attr ref android.R.styleable#View_hapticFeedbackEnabled
* @attr ref android.R.styleable#View_keepScreenOn
+ * @attr ref android.R.styleable#View_keyboardNavigationCluster
* @attr ref android.R.styleable#View_layerType
* @attr ref android.R.styleable#View_layoutDirection
* @attr ref android.R.styleable#View_longClickable
* @attr ref android.R.styleable#View_minHeight
* @attr ref android.R.styleable#View_minWidth
+ * @attr ref android.R.styleable#View_nextClusterForward
* @attr ref android.R.styleable#View_nextFocusDown
* @attr ref android.R.styleable#View_nextFocusLeft
* @attr ref android.R.styleable#View_nextFocusRight
@@ -4076,7 +4079,9 @@
int mNextFocusForwardId = View.NO_ID;
/**
- * User-specified next keyboard navigation cluster.
+ * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
+ *
+ * @see #findUserSetNextKeyboardNavigationCluster(View, int)
*/
int mNextClusterForwardId = View.NO_ID;
@@ -9968,6 +9973,29 @@
return null;
}
+ /**
+ * If a user manually specified the next keyboard-navigation cluster for a particular direction,
+ * use the root to look up the view.
+ *
+ * @param root the root view of the hierarchy containing this view
+ * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
+ * @return the user-specified next cluster, or {@code null} if there is none
+ */
+ View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
+ switch (direction) {
+ case FOCUS_FORWARD:
+ if (mNextClusterForwardId == View.NO_ID) return null;
+ return findViewInsideOutShouldExist(root, mNextClusterForwardId);
+ case FOCUS_BACKWARD: {
+ if (mID == View.NO_ID) return null;
+ final int id = mID;
+ return root.findViewByPredicateInsideOut(this,
+ (Predicate<View>) t -> t.mNextClusterForwardId == id);
+ }
+ }
+ return null;
+ }
+
private View findViewInsideOutShouldExist(View root, int id) {
if (mMatchIdPredicate == null) {
mMatchIdPredicate = new MatchIdPredicate();
@@ -20780,11 +20808,18 @@
}
/**
- * Look for a child view with the given id. If this view has the given
- * id, return this view.
+ * Finds the first descendant view with the given ID, the view itself if
+ * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
+ * (< 0) or there is no matching view in the hierarchy.
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @param id The id to search for.
- * @return The view that has the given id in the hierarchy or null
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c250226..9e1ceee 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1258,15 +1258,18 @@
return;
}
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
+ int count = 0;
+ final View[] visibleChildren = new View[mChildrenCount];
+ for (int i = 0; i < mChildrenCount; ++i) {
+ final View child = mChildren[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.addKeyboardNavigationClusters(views, direction);
+ visibleChildren[count++] = child;
}
}
+ Arrays.sort(visibleChildren, 0, count, FocusFinder.getFocusComparator(this, false));
+ for (int i = 0; i < count; ++i) {
+ visibleChildren[i].addKeyboardNavigationClusters(views, direction);
+ }
}
/**
@@ -7344,6 +7347,7 @@
/** @hide */
protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
+ requestLayout();
}
/** @hide */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2e201bf..58ef0af 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4660,6 +4660,7 @@
if (cluster != null && cluster.isRootNamespace()) {
// the default cluster. Try to find a non-clustered view to focus.
if (cluster.restoreFocusNotInCluster()) {
+ playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
return true;
}
// otherwise skip to next actual cluster
@@ -4667,6 +4668,7 @@
}
if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
+ playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
return true;
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0053caa..6dd8ecf 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1308,15 +1308,22 @@
}
/**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link android.app.Activity#onCreate}. This will
- * implicitly call {@link #getDecorView} for you, with all of the
- * associated side-effects.
+ * Finds a view that was identified by the {@code android:id} XML attribute
+ * that was processed in {@link android.app.Activity#onCreate}. This will
+ * implicitly call {@link #getDecorView} with all of the associated
+ * side-effects.
+ * <p>
+ * <strong>Note:</strong> In most cases -- depending on compiler support --
+ * the resulting view is automatically cast to the target class type. If
+ * the target class type is unconstrained, an explicit cast may be
+ * necessary.
*
- * @return The view if found or null otherwise.
+ * @param id the ID to search for
+ * @return a view with given ID if found, or {@code null} otherwise
+ * @see View#findViewById(int)
*/
@Nullable
- public View findViewById(@IdRes int id) {
+ public <T extends View> T findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
diff --git a/core/java/android/view/autofill/AutoFillId.java b/core/java/android/view/autofill/AutoFillId.java
deleted file mode 100644
index 081fb02..0000000
--- a/core/java/android/view/autofill/AutoFillId.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.view.autofill;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
-@Deprecated
-public final class AutoFillId implements Parcelable {
-
- private final AutofillId mRealId;
-
- /** @hide */
- public AutoFillId(AutofillId daRealId) {
- this.mRealId = daRealId;
- }
-
- @Override
- public int hashCode() {
- return mRealId.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- final AutoFillId other = (AutoFillId) obj;
- return mRealId.equals(other.mRealId);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mRealId, 0);
- }
-
- private AutoFillId(Parcel parcel) {
- mRealId = parcel.readParcelable(null);
- }
-
- /** @hide */
- public AutofillId getDaRealId() {
- return mRealId;
- }
-
- /** @hide */
- public static AutoFillId forDaRealId(AutofillId id) {
- return id == null ? null : new AutoFillId(id);
- }
-
- public static final Parcelable.Creator<AutoFillId> CREATOR =
- new Parcelable.Creator<AutoFillId>() {
- @Override
- public AutoFillId createFromParcel(Parcel source) {
- return new AutoFillId(source);
- }
-
- @Override
- public AutoFillId[] newArray(int size) {
- return new AutoFillId[size];
- }
- };
-}
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
deleted file mode 100644
index c508ba4..0000000
--- a/core/java/android/view/autofill/AutoFillType.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * Defines the type of a object that can be used to autofill a {@link View} so the
- * {@link android.service.autofill.AutofillService} can use the proper {@link AutofillValue} to
- * fill it.
- *
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
-@Deprecated
-public final class AutoFillType implements Parcelable {
-
- // Cached instance for types that don't have subtype; it uses the "lazy initialization holder
- // class idiom" (Effective Java, Item 71) to avoid memory utilization when autofill is not
- // enabled.
- private static class DefaultTypesHolder {
- static final AutoFillType TEXT = new AutoFillType(TYPE_TEXT);
- static final AutoFillType TOGGLE = new AutoFillType(TYPE_TOGGLE);
- static final AutoFillType LIST = new AutoFillType(TYPE_LIST);
- static final AutoFillType DATE = new AutoFillType(TYPE_DATE);
- }
-
- private static final int TYPE_TEXT = 1;
- private static final int TYPE_TOGGLE = 2;
- private static final int TYPE_LIST = 3;
- private static final int TYPE_DATE = 4;
-
- private final int mType;
-
- private AutoFillType(int type) {
- mType = type;
- }
-
- /**
- * Checks if this is a type for a text field, which is filled by a {@link CharSequence}.
- */
- public boolean isText() {
- return mType == TYPE_TEXT;
- }
-
- /**
- * Checks if this is a a type for a togglable field, which is filled by a {@code boolean}.
- */
- public boolean isToggle() {
- return mType == TYPE_TOGGLE;
- }
-
- /**
- * Checks if this is a type for a selection list field, which is filled by a {@code integer}
- * representing the element index inside the list (starting at {@code 0}.
- */
- public boolean isList() {
- return mType == TYPE_LIST;
- }
-
- /**
- * Checks if this is a type for a date and time, which is represented by a long representing
- * the number of milliseconds since the standard base time known as "the epoch", namely
- * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
- */
- public boolean isDate() {
- return mType == TYPE_DATE;
- }
-
- /////////////////////////////////////
- // Object "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- return "AutoFillType [type=" + mType + "]";
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + mType;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- final AutoFillType other = (AutoFillType) obj;
- if (mType != other.mType) return false;
- return true;
- }
-
- /////////////////////////////////////
- // Parcelable "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(mType);
- }
-
- private AutoFillType(Parcel parcel) {
- mType = parcel.readInt();
- }
-
- public static final Parcelable.Creator<AutoFillType> CREATOR =
- new Parcelable.Creator<AutoFillType>() {
- @Override
- public AutoFillType createFromParcel(Parcel source) {
- return new AutoFillType(source);
- }
-
- @Override
- public AutoFillType[] newArray(int size) {
- return new AutoFillType[size];
- }
- };
-
- ////////////////////
- // Factory methods //
- ////////////////////
-
- /**
- * Creates a text field type, which is filled by a {@link CharSequence}.
- *
- * <p>See {@link #isText()} for more info.
- */
- public static AutoFillType forText() {
- return DefaultTypesHolder.TEXT;
- }
-
- /**
- * Creates a type that can be toggled which is filled by a {@code boolean}.
- *
- * <p>See {@link #isToggle()} for more info.
- */
- public static AutoFillType forToggle() {
- return DefaultTypesHolder.TOGGLE;
- }
-
- /**
- * Creates a selection list, which is filled by a {@code integer} representing the element index
- * inside the list (starting at {@code 0}.
- *
- * <p>See {@link #isList()} for more info.
- */
- public static AutoFillType forList() {
- return DefaultTypesHolder.LIST;
- }
-
- /**
- * Creates a type that represents a date.
- *
- * <p>See {@link #isDate()} for more info.
- */
- public static AutoFillType forDate() {
- return DefaultTypesHolder.DATE;
- }
-}
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
deleted file mode 100644
index 4774d8f..0000000
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use AutofillValue
- */
-@Deprecated
-public final class AutoFillValue implements Parcelable {
- private final AutofillValue mRealValue;
-
- private AutoFillValue(AutofillValue daRealValue) {
- this.mRealValue = daRealValue;
- }
-
- /**
- * Gets the value to autofill a text field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
- */
- public CharSequence getTextValue() {
- return mRealValue.getTextValue();
- }
-
- /**
- * Gets the value to autofill a toggable field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
- */
- public boolean getToggleValue() {
- return mRealValue.getToggleValue();
- }
-
- /**
- * Gets the value to autofill a selection list field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
- */
- public int getListValue() {
- return mRealValue.getListValue();
- }
-
- /**
- * Gets the value to autofill a date field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
- */
- public long getDateValue() {
- return mRealValue.getDateValue();
- }
-
- /////////////////////////////////////
- // Object "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public int hashCode() {
- return mRealValue.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- final AutoFillValue other = (AutoFillValue) obj;
- return mRealValue.equals(other.mRealValue);
- }
-
- @Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- return mRealValue.toString();
- }
-
- /////////////////////////////////////
- // Parcelable "contract" methods. //
- /////////////////////////////////////
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mRealValue, 0);
- }
-
- private AutoFillValue(Parcel parcel) {
- mRealValue = parcel.readParcelable(null);
- }
-
- public static final Parcelable.Creator<AutoFillValue> CREATOR =
- new Parcelable.Creator<AutoFillValue>() {
- @Override
- public AutoFillValue createFromParcel(Parcel source) {
- return new AutoFillValue(source);
- }
-
- @Override
- public AutoFillValue[] newArray(int size) {
- return new AutoFillValue[size];
- }
- };
-
- ////////////////////
- // Factory methods //
- ////////////////////
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
- */
- @Nullable
- public static AutoFillValue forText(@Nullable CharSequence value) {
- return value == null ? null : new AutoFillValue(AutofillValue.forText(value));
- }
-
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a toggable
- * field.
- *
- * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
- */
- public static AutoFillValue forToggle(boolean value) {
- return new AutoFillValue(AutofillValue.forToggle(value));
- }
-
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a selection
- * list.
- *
- * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
- */
- public static AutoFillValue forList(int value) {
- return new AutoFillValue(AutofillValue.forList(value));
- }
-
- /**
- * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a date.
- *
- * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
- */
- public static AutoFillValue forDate(long date) {
- return new AutoFillValue(AutofillValue.forDate(date));
- }
-
- /** @hide */
- public static AutoFillValue forDaRealValue(AutofillValue daRealValue) {
- return new AutoFillValue(daRealValue);
- }
-
- /** @hide */
- public AutofillValue getDaRealValue() {
- return mRealValue;
- }
-}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 636fa7d..61920bd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -411,8 +411,16 @@
public abstract boolean getUseWebViewBackgroundForOverscrollBackground();
/**
- * Sets whether the WebView should save form data. The default is true.
+ * Sets whether the WebView should save form data. In Android O, the
+ * platform has implemented a fully functional Autofill feature to store
+ * form data. Therefore, the Webview form data save feature is disabled.
+ *
+ * Note that the feature will continue to be supported on older versions of
+ * Android as before.
+ *
+ * This function does not have any effect.
*/
+ @Deprecated
public abstract void setSaveFormData(boolean save);
/**
@@ -421,6 +429,7 @@
* @return whether the WebView saves form data
* @see #setSaveFormData
*/
+ @Deprecated
public abstract boolean getSaveFormData();
/**
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 87d3c7b..982c57b 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -143,6 +143,7 @@
* @return whether there is any saved data for web forms
* @see #clearFormData
*/
+ @Deprecated
public abstract boolean hasFormData();
/**
@@ -150,5 +151,6 @@
*
* @see #hasFormData
*/
+ @Deprecated
public abstract void clearFormData();
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index da00d9c..0bf2460 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1443,7 +1443,7 @@
@Override
public void requestChildFocus(View child, View focused) {
- if (focused.getRevealOnFocusHint()) {
+ if (focused != null && focused.getRevealOnFocusHint()) {
if (!mIsLayoutDirty) {
scrollToChild(focused);
} else {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 0a9e361..8fc4f50 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1468,7 +1468,7 @@
@Override
public void requestChildFocus(View child, View focused) {
- if (focused.getRevealOnFocusHint()) {
+ if (focused != null && focused.getRevealOnFocusHint()) {
if (!mIsLayoutDirty) {
scrollToChild(focused);
} else {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 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/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index f987a9f..caf35b3 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -55,8 +55,8 @@
in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
- ParceledListSlice getInstalledProvidersForProfile(int categoryFilter,
- int profileId);
+ ParceledListSlice getInstalledProvidersForProfile(int categoryFilter, int profileId,
+ String packageName);
AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
boolean hasBindAppWidgetPermission(in String packageName, int userId);
void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);
diff --git a/core/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/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 4e68602..3010dc1 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -245,8 +245,7 @@
}
sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
- addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
- return true;
+ return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
}
static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
diff --git a/core/jni/android/graphics/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_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 4b7e0dd..01fe078 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -167,7 +167,7 @@
}
static jboolean
-android_hardware_UsbRequest_enqueue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
+android_hardware_UsbRequest_queue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
jint length)
{
struct usb_request* request = get_request_from_object(env, thiz);
@@ -226,8 +226,8 @@
{"native_init", "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
(void *)android_hardware_UsbRequest_init},
{"native_close", "()V", (void *)android_hardware_UsbRequest_close},
- {"native_enqueue", "(Ljava/nio/ByteBuffer;II)Z",
- (void *)android_hardware_UsbRequest_enqueue},
+ {"native_queue", "(Ljava/nio/ByteBuffer;II)Z",
+ (void *)android_hardware_UsbRequest_queue},
{"native_queue_array", "([BIZ)Z", (void *)android_hardware_UsbRequest_queue_array},
{"native_dequeue_array", "([BIZ)I", (void *)android_hardware_UsbRequest_dequeue_array},
{"native_queue_direct", "(Ljava/nio/ByteBuffer;IZ)Z",
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 80f9d57..7121194 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -182,7 +182,7 @@
err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
if (err != NO_ERROR) return err;
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
+ sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
uint32_t grallocBufWidth = buf->getWidth();
uint32_t grallocBufHeight = buf->getHeight();
uint32_t grallocBufStride = buf->getStride();
diff --git a/core/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/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0ab27f2..b95258b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -346,6 +346,11 @@
return false;
}
+ // Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
+ if (mount_mode == MOUNT_EXTERNAL_NONE) {
+ return true;
+ }
+
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
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 ffcb8476..7922250 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -528,6 +528,7 @@
<protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
<protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
<protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
+ <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
<protected-broadcast android:name="android.content.pm.action.SESSION_COMMITTED" />
<protected-broadcast android:name="android.os.action.USER_RESTRICTIONS_CHANGED" />
@@ -3346,7 +3347,8 @@
android:documentLaunchMode="never"
android:relinquishTaskIdentity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
<intent-filter>
<action android:name="android.intent.action.CHOOSER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3360,7 +3362,8 @@
android:documentLaunchMode="never"
android:relinquishTaskIdentity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
<intent-filter>
<action android:name="android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3421,7 +3424,8 @@
android:exported="true"
android:theme="@style/Theme.DeviceDefault.Light.Dialog"
android:label="@string/choose_account_label"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.ChooseTypeAndAccountActivity"
@@ -3429,14 +3433,16 @@
android:exported="true"
android:theme="@style/Theme.DeviceDefault.Light.Dialog"
android:label="@string/choose_account_label"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.ChooseAccountTypeActivity"
android:excludeFromRecents="true"
android:theme="@style/Theme.DeviceDefault.Light.Dialog"
android:label="@string/choose_account_label"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.accounts.CantAddAccountActivity"
@@ -3450,7 +3456,8 @@
android:excludeFromRecents="true"
android:exported="true"
android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
- android:process=":ui">
+ android:process=":ui"
+ android:visibleToInstantApps="true">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index a165621..5a2bf4e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -17,27 +17,24 @@
<NotificationHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:theme="@style/Theme.Material.Notification"
android:id="@+id/notification_header"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="@dimen/notification_header_height"
android:clipChildren="false"
- android:paddingTop="@dimen/notification_header_padding_top"
- android:paddingBottom="@dimen/notification_header_padding_bottom"
- android:layout_marginBottom="5dp"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="16dp">
+ style="?attr/notificationHeaderStyle">
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
- android:layout_width="@dimen/notification_header_icon_size"
- android:layout_height="@dimen/notification_header_icon_size"
+ android:layout_width="?attr/notificationHeaderIconSize"
+ android:layout_height="?attr/notificationHeaderIconSize"
android:layout_marginEnd="3dp"
/>
<TextView
android:id="@+id/app_name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="3dp"
android:layout_marginEnd="2dp"
android:singleLine="true"
@@ -46,7 +43,7 @@
android:id="@+id/header_text_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/notification_header_divider_symbol"
@@ -55,7 +52,7 @@
android:id="@+id/header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:visibility="gone"
@@ -64,7 +61,7 @@
android:id="@+id/time_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/notification_header_divider_symbol"
diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml
index e2c68b5..026bc6e 100644
--- a/core/res/res/layout/notification_template_material_ambient.xml
+++ b/core/res/res/layout/notification_template_material_ambient.xml
@@ -20,8 +20,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="ambient"
+ android:paddingStart="@dimen/notification_extra_margin_ambient"
+ android:paddingEnd="@dimen/notification_extra_margin_ambient"
>
- <include layout="@layout/notification_template_header" />
+ <include layout="@layout/notification_template_header"
+ android:theme="@style/Theme.Material.Notification.Ambient" />
<LinearLayout
android:id="@+id/notification_action_list_margin_target"
@@ -52,7 +55,7 @@
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:textSize="20sp"
- android:textColor="#e6fafafa"
+ android:textColor="#ffffffff"
/>
<TextView android:id="@+id/text"
android:layout_width="match_parent"
@@ -63,7 +66,7 @@
android:gravity="top"
android:visibility="gone"
android:textSize="16sp"
- android:textColor="#ccfafafa"
+ android:textColor="#eeffffff"
android:layout_marginTop="4dp"
/>
</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 554f50c..d26d952 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7739,13 +7739,6 @@
<attr name="settingsActivity" />
</declare-styleable>
- <!-- TODO(b/35956626): temporary until clients change to AutofillService -->
- <declare-styleable name="AutoFillService">
- <!-- Fully qualified class name of an activity that allows the user to modify
- the settings for this service. -->
- <attr name="settingsActivity" />
- </declare-styleable>
-
<!-- =============================== -->
<!-- Contacts meta-data attributes -->
<!-- =============================== -->
@@ -8566,6 +8559,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">
@@ -8630,5 +8628,12 @@
<attr name="stackFromEnd" format="boolean" />
</declare-styleable>
+ <!-- @hide -->
+ <declare-styleable name="NotificationTheme">
+ <attr name="notificationHeaderStyle" format="reference" />
+ <attr name="notificationHeaderTextAppearance" format="reference" />
+ <attr name="notificationHeaderIconSize" format="dimension" />
+ </declare-styleable>
+
<attr name="lockPatternStyle" format="reference" />
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 85ecaff..221e308 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2822,4 +2822,11 @@
<!-- Whether the device supports quick settings and its associated APIs -->
<bool name="config_quickSettingsSupported">true</bool>
+
+ <!-- The component name, flattened to a string, for the default autofill service
+ to enabled for an user. This service must be trusted, as it can be activated
+ without explicit consent of the user. If no autofill service with the
+ specified name exists on the device, autofill will be disabled by default.
+ -->
+ <string name="config_defaultAutofillService" translatable="false"></string>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 1129647..c5316c6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -165,6 +165,9 @@
-->
<dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
+ <!-- The additional margin on the sides of the ambient view. -->
+ <dimen name="notification_extra_margin_ambient">16dp</dimen>
+
<!-- The height of the notification action list -->
<dimen name="notification_action_list_height">56dp</dimen>
@@ -188,6 +191,9 @@
<!-- size (width and height) of the icon in the notification header -->
<dimen name="notification_header_icon_size">18dp</dimen>
+ <!-- size (width and height) of the icon in the notification header -->
+ <dimen name="notification_header_icon_size_ambient">20dp</dimen>
+
<!-- Height of a small notification in the status bar -->
<dimen name="notification_min_height">92dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 831cf89..11286f3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3172,7 +3172,7 @@
<string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
<!-- Notification title when an application is displaying ui on-top of other apps
[CHAR LIMIT=30] -->
- <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps.</string>
+ <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
<!-- Notification body when an application is displaying ui on-top of other apps
[CHAR LIMIT=NONE] -->
<string name="alert_windows_notification_message">If you don’t want <xliff:g id="name" example="Google Maps">%s</xliff:g> to use this feature, tap to open settings and turn it off.</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8f061a3..ec16611 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -488,6 +488,10 @@
<style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />
+ <style name="TextAppearance.Material.Notification.Info.Ambient">
+ <item name="textSize">@dimen/notification_text_size</item>
+ </style>
+
<style name="TextAppearance.Material.Notification.Emphasis">
<item name="textColor">#66000000</item>
</style>
@@ -1283,4 +1287,12 @@
<style name="DialogWindowTitle.Material.Light" />
+ <style name="Notification.Header" parent="">
+ <item name="paddingTop">@dimen/notification_header_padding_top</item>
+ <item name="paddingBottom">@dimen/notification_header_padding_bottom</item>
+ <item name="layout_marginBottom">5dp</item>
+ <item name="paddingStart">@dimen/notification_content_margin_start</item>
+ <item name="paddingEnd">16dp</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ae05a69..c12116a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2944,6 +2944,7 @@
<java-symbol type="string" name="notification_channel_alerts" />
<java-symbol type="string" name="notification_channel_retail_mode" />
<java-symbol type="string" name="notification_channel_usb" />
+ <java-symbol type="string" name="config_defaultAutofillService" />
<!-- ETWS primary messages -->
<java-symbol type="string" name="etws_primary_default_message_earthquake" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 008c817..9dafa7a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1321,6 +1321,19 @@
<item name="windowNoTitle">true</item>
</style>
+ <!-- Theme for inflating notifications -->
+ <style name="Theme.Material.Notification" parent="">
+ <item name="notificationHeaderStyle">@style/Notification.Header</item>
+ <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info</item>
+ <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size</item>
+ </style>
+
+ <!-- Theme for inflating ambient notification -->
+ <style name="Theme.Material.Notification.Ambient">
+ <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info.Ambient</item>
+ <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size_ambient</item>
+ </style>
+
<!-- Default theme for Settings and activities launched from Settings. -->
<style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar">
<item name="colorPrimary">@color/primary_material_settings_light</item>
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
index 6c1ce44..22bfea1 100644
--- a/core/res/res/xml/time_zones_by_country.xml
+++ b/core/res/res/xml/time_zones_by_country.xml
@@ -31,11 +31,11 @@
<!-- ANTIGUA AND BARBUDA, -4:00 -->
- <timezone code="ag">America/Port_of_Spain</timezone>
+ <timezone code="ag">America/Antigua</timezone>
<!-- ANGUILLA, -4:00 -->
- <timezone code="ai">America/Port_of_Spain</timezone>
+ <timezone code="ai">America/Anguilla</timezone>
<!-- ALBANIA, 1:00 -->
@@ -47,11 +47,11 @@
<!-- ANGOLA, 1:00 -->
- <timezone code="ao">Africa/Lagos</timezone>
+ <timezone code="ao">Africa/Luanda</timezone>
<!-- ANTARCTICA, 12:00 -->
- <timezone code="aq">Pacific/Auckland</timezone>
+ <timezone code="aq">Antarctica/McMurdo</timezone>
<!-- ANTARCTICA, 10:00 -->
@@ -144,11 +144,11 @@
<!-- ARUBA, -4:00 -->
- <timezone code="aw">America/Curacao</timezone>
+ <timezone code="aw">America/Aruba</timezone>
<!-- ALAND ISLANDS, 2:00 -->
- <timezone code="ax">Europe/Helsinki</timezone>
+ <timezone code="ax">Europe/Mariehamn</timezone>
<!-- AZERBAIJAN, 4:00 -->
@@ -156,7 +156,7 @@
<!-- BOSNIA AND HERZEGOVINA, 1:00 -->
- <timezone code="ba">Europe/Belgrade</timezone>
+ <timezone code="ba">Europe/Sarajevo</timezone>
<!-- BARBADOS, -4:00 -->
@@ -172,7 +172,7 @@
<!-- BURKINA FASO, 0:00 -->
- <timezone code="bf">Africa/Abidjan</timezone>
+ <timezone code="bf">Africa/Ouagadougou</timezone>
<!-- BULGARIA, 2:00 -->
@@ -180,19 +180,19 @@
<!-- BAHRAIN, 3:00 -->
- <timezone code="bh">Asia/Qatar</timezone>
+ <timezone code="bh">Asia/Bahrain</timezone>
<!-- BURUNDI, 2:00 -->
- <timezone code="bi">Africa/Maputo</timezone>
+ <timezone code="bi">Africa/Bujumbura</timezone>
<!-- BENIN, 1:00 -->
- <timezone code="bj">Africa/Lagos</timezone>
+ <timezone code="bj">Africa/Porto-Novo</timezone>
<!-- Saint Barthélemy, -4:00 -->
- <timezone code="bl">America/Port_of_Spain</timezone>
+ <timezone code="bl">America/St_Barthelemy</timezone>
<!-- BERMUDA, -4:00 -->
@@ -208,7 +208,7 @@
<!-- Caribbean Netherlands, -4:00 -->
- <timezone code="bq">America/Curacao</timezone>
+ <timezone code="bq">America/Kralendijk</timezone>
<!-- BRAZIL, -2:00 -->
@@ -248,7 +248,7 @@
<!-- BOTSWANA, 2:00 -->
- <timezone code="bw">Africa/Maputo</timezone>
+ <timezone code="bw">Africa/Gaborone</timezone>
<!-- BELARUS, 3:00 -->
@@ -310,19 +310,19 @@
<!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 2:00 -->
- <timezone code="cd">Africa/Maputo</timezone>
+ <timezone code="cd">Africa/Lubumbashi</timezone>
<!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 1:00 -->
- <timezone code="cd">Africa/Lagos</timezone>
+ <timezone code="cd">Africa/Kinshasa</timezone>
<!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
- <timezone code="cf">Africa/Lagos</timezone>
+ <timezone code="cf">Africa/Bangui</timezone>
<!-- CONGO, 1:00 -->
- <timezone code="cg">Africa/Lagos</timezone>
+ <timezone code="cg">Africa/Brazzaville</timezone>
<!-- SWITZERLAND, 1:00 -->
@@ -350,7 +350,7 @@
<!-- CAMEROON, 1:00 -->
- <timezone code="cm">Africa/Lagos</timezone>
+ <timezone code="cm">Africa/Douala</timezone>
<!-- CHINA, 8:00 -->
@@ -388,6 +388,10 @@
<timezone code="cy">Asia/Nicosia</timezone>
+ <!-- CYPRUS, 3:00 -->
+
+ <timezone code="cy">Asia/Famagusta</timezone>
+
<!-- CZECH REPUBLIC, 1:00 -->
<timezone code="cz">Europe/Prague</timezone>
@@ -395,11 +399,11 @@
<!-- GERMANY, 1:00 -->
<timezone code="de">Europe/Berlin</timezone>
- <timezone code="de">Europe/Zurich</timezone>
+ <timezone code="de">Europe/Busingen</timezone>
<!-- DJIBOUTI, 3:00 -->
- <timezone code="dj">Africa/Nairobi</timezone>
+ <timezone code="dj">Africa/Djibouti</timezone>
<!-- DENMARK, 1:00 -->
@@ -407,7 +411,7 @@
<!-- DOMINICA, -4:00 -->
- <timezone code="dm">America/Port_of_Spain</timezone>
+ <timezone code="dm">America/Dominica</timezone>
<!-- DOMINICAN REPUBLIC, -4:00 -->
@@ -439,7 +443,7 @@
<!-- ERITREA, 3:00 -->
- <timezone code="er">Africa/Nairobi</timezone>
+ <timezone code="er">Africa/Asmara</timezone>
<!-- SPAIN, 1:00 -->
@@ -452,7 +456,7 @@
<!-- ETHIOPIA, 3:00 -->
- <timezone code="et">Africa/Nairobi</timezone>
+ <timezone code="et">Africa/Addis_Ababa</timezone>
<!-- FINLAND, 2:00 -->
@@ -468,7 +472,7 @@
<!-- MICRONESIA, FEDERATED STATES OF, 11:00 -->
- <timezone code="fm">Pacific/Ponape</timezone>
+ <timezone code="fm">Pacific/Pohnpei</timezone>
<timezone code="fm">Pacific/Kosrae</timezone>
<!-- MICRONESIA, FEDERATED STATES OF, 10:00 -->
@@ -485,7 +489,7 @@
<!-- GABON, 1:00 -->
- <timezone code="ga">Africa/Lagos</timezone>
+ <timezone code="ga">Africa/Libreville</timezone>
<!-- UNITED KINGDOM, 0:00 -->
@@ -493,7 +497,7 @@
<!-- GRENADA, -4:00 -->
- <timezone code="gd">America/Port_of_Spain</timezone>
+ <timezone code="gd">America/Grenada</timezone>
<!-- GEORGIA, 4:00 -->
@@ -505,7 +509,7 @@
<!-- GUERNSEY, 0:00 -->
- <timezone code="gg">Europe/London</timezone>
+ <timezone code="gg">Europe/Guernsey</timezone>
<!-- GHANA, 0:00 -->
@@ -533,19 +537,19 @@
<!-- GAMBIA, 0:00 -->
- <timezone code="gm">Africa/Abidjan</timezone>
+ <timezone code="gm">Africa/Banjul</timezone>
<!-- GUINEA, 0:00 -->
- <timezone code="gn">Africa/Abidjan</timezone>
+ <timezone code="gn">Africa/Conakry</timezone>
<!-- GUADELOUPE, -4:00 -->
- <timezone code="gp">America/Port_of_Spain</timezone>
+ <timezone code="gp">America/Guadeloupe</timezone>
<!-- EQUATORIAL GUINEA, 1:00 -->
- <timezone code="gq">Africa/Lagos</timezone>
+ <timezone code="gq">Africa/Malabo</timezone>
<!-- GREECE, 2:00 -->
@@ -581,7 +585,7 @@
<!-- CROATIA, 1:00 -->
- <timezone code="hr">Europe/Belgrade</timezone>
+ <timezone code="hr">Europe/Zagreb</timezone>
<!-- HAITI, -5:00 -->
@@ -614,7 +618,7 @@
<!-- ISLE OF MAN, 0:00 -->
- <timezone code="im">Europe/London</timezone>
+ <timezone code="im">Europe/Isle_of_Man</timezone>
<!-- INDIA, 5:30 -->
@@ -642,7 +646,7 @@
<!-- JERSEY, 0:00 -->
- <timezone code="je">Europe/London</timezone>
+ <timezone code="je">Europe/Jersey</timezone>
<!-- JAMAICA, -5:00 -->
@@ -666,7 +670,7 @@
<!-- CAMBODIA, 7:00 -->
- <timezone code="kh">Asia/Bangkok</timezone>
+ <timezone code="kh">Asia/Phnom_Penh</timezone>
<!-- KIRIBATI, 14:00 -->
@@ -682,11 +686,11 @@
<!-- COMOROS, 3:00 -->
- <timezone code="km">Africa/Nairobi</timezone>
+ <timezone code="km">Indian/Comoro</timezone>
<!-- SAINT KITTS AND NEVIS, -4:00 -->
- <timezone code="kn">America/Port_of_Spain</timezone>
+ <timezone code="kn">America/St_Kitts</timezone>
<!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
@@ -698,11 +702,11 @@
<!-- KUWAIT, 3:00 -->
- <timezone code="kw">Asia/Riyadh</timezone>
+ <timezone code="kw">Asia/Kuwait</timezone>
<!-- CAYMAN ISLANDS, -5:00 -->
- <timezone code="ky">America/Panama</timezone>
+ <timezone code="ky">America/Cayman</timezone>
<!-- KAZAKHSTAN, 6:00 -->
@@ -714,10 +718,11 @@
<timezone code="kz">Asia/Aqtau</timezone>
<timezone code="kz">Asia/Oral</timezone>
<timezone code="kz">Asia/Aqtobe</timezone>
+ <timezone code="kz">Asia/Atyrau</timezone>
<!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
- <timezone code="la">Asia/Bangkok</timezone>
+ <timezone code="la">Asia/Vientiane</timezone>
<!-- LEBANON, 2:00 -->
@@ -725,11 +730,11 @@
<!-- SAINT LUCIA, -4:00 -->
- <timezone code="lc">America/Port_of_Spain</timezone>
+ <timezone code="lc">America/St_Lucia</timezone>
<!-- LIECHTENSTEIN, 1:00 -->
- <timezone code="li">Europe/Zurich</timezone>
+ <timezone code="li">Europe/Vaduz</timezone>
<!-- SRI LANKA, 5:30 -->
@@ -741,7 +746,7 @@
<!-- LESOTHO, 2:00 -->
- <timezone code="ls">Africa/Johannesburg</timezone>
+ <timezone code="ls">Africa/Maseru</timezone>
<!-- LITHUANIA, 2:00 -->
@@ -773,15 +778,15 @@
<!-- MONTENEGRO, 1:00 -->
- <timezone code="me">Europe/Belgrade</timezone>
+ <timezone code="me">Europe/Podgorica</timezone>
<!-- Collectivity of Saint Martin, -4:00 -->
- <timezone code="mf">America/Port_of_Spain</timezone>
+ <timezone code="mf">America/Marigot</timezone>
<!-- MADAGASCAR, 3:00 -->
- <timezone code="mg">Africa/Nairobi</timezone>
+ <timezone code="mg">Indian/Antananarivo</timezone>
<!-- MARSHALL ISLANDS, 12:00 -->
@@ -790,11 +795,11 @@
<!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
- <timezone code="mk">Europe/Belgrade</timezone>
+ <timezone code="mk">Europe/Skopje</timezone>
<!-- MALI, 0:00 -->
- <timezone code="ml">Africa/Abidjan</timezone>
+ <timezone code="ml">Africa/Bamako</timezone>
<!-- MYANMAR, 6:30 -->
@@ -815,7 +820,7 @@
<!-- NORTHERN MARIANA ISLANDS, 10:00 -->
- <timezone code="mp">Pacific/Guam</timezone>
+ <timezone code="mp">Pacific/Saipan</timezone>
<!-- MARTINIQUE, -4:00 -->
@@ -823,11 +828,11 @@
<!-- MAURITANIA, 0:00 -->
- <timezone code="mr">Africa/Abidjan</timezone>
+ <timezone code="mr">Africa/Nouakchott</timezone>
<!-- MONTSERRAT, -4:00 -->
- <timezone code="ms">America/Port_of_Spain</timezone>
+ <timezone code="ms">America/Montserrat</timezone>
<!-- MALTA, 1:00 -->
@@ -843,7 +848,7 @@
<!-- MALAWI, 2:00 -->
- <timezone code="mw">Africa/Maputo</timezone>
+ <timezone code="mw">Africa/Blantyre</timezone>
<!-- MEXICO, -6:00 -->
@@ -887,7 +892,7 @@
<!-- NIGER, 1:00 -->
- <timezone code="ne">Africa/Lagos</timezone>
+ <timezone code="ne">Africa/Niamey</timezone>
<!-- NORFOLK ISLAND, 11:30 -->
@@ -911,7 +916,7 @@
<!-- NEPAL, 5:45 -->
- <timezone code="np">Asia/Katmandu</timezone>
+ <timezone code="np">Asia/Kathmandu</timezone>
<!-- NAURU, 12:00 -->
@@ -931,7 +936,7 @@
<!-- OMAN, 4:00 -->
- <timezone code="om">Asia/Dubai</timezone>
+ <timezone code="om">Asia/Muscat</timezone>
<!-- PANAMA, -5:00 -->
@@ -1070,6 +1075,7 @@
<timezone code="ru">Europe/Samara</timezone>
<timezone code="ru">Europe/Astrakhan</timezone>
<timezone code="ru">Europe/Ulyanovsk</timezone>
+ <timezone code="ru">Europe/Saratov</timezone>
<!-- RUSSIAN FEDERATION, 3:00 -->
@@ -1084,7 +1090,7 @@
<!-- RWANDA, 2:00 -->
- <timezone code="rw">Africa/Maputo</timezone>
+ <timezone code="rw">Africa/Kigali</timezone>
<!-- SAUDI ARABIA, 3:00 -->
@@ -1112,35 +1118,35 @@
<!-- SAINT HELENA, 0:00 -->
- <timezone code="sh">Africa/Abidjan</timezone>
+ <timezone code="sh">Atlantic/St_Helena</timezone>
<!-- SLOVENIA, 1:00 -->
- <timezone code="si">Europe/Belgrade</timezone>
+ <timezone code="si">Europe/Ljubljana</timezone>
<!-- SVALBARD AND JAN MAYEN, 1:00 -->
- <timezone code="sj">Europe/Oslo</timezone>
+ <timezone code="sj">Arctic/Longyearbyen</timezone>
<!-- SLOVAKIA, 1:00 -->
- <timezone code="sk">Europe/Prague</timezone>
+ <timezone code="sk">Europe/Bratislava</timezone>
<!-- SIERRA LEONE, 0:00 -->
- <timezone code="sl">Africa/Abidjan</timezone>
+ <timezone code="sl">Africa/Freetown</timezone>
<!-- SAN MARINO, 1:00 -->
- <timezone code="sm">Europe/Rome</timezone>
+ <timezone code="sm">Europe/San_Marino</timezone>
<!-- SENEGAL, 0:00 -->
- <timezone code="sn">Africa/Abidjan</timezone>
+ <timezone code="sn">Africa/Dakar</timezone>
<!-- SOMALIA, 3:00 -->
- <timezone code="so">Africa/Nairobi</timezone>
+ <timezone code="so">Africa/Mogadishu</timezone>
<!-- SURINAME, -3:00 -->
@@ -1148,11 +1154,11 @@
<!-- South Sudan, 3:00 -->
- <timezone code="ss">Africa/Khartoum</timezone>
+ <timezone code="ss">Africa/Juba</timezone>
<!-- SAO TOME AND PRINCIPE, 0:00 -->
- <timezone code="st">Africa/Abidjan</timezone>
+ <timezone code="st">Africa/Sao_Tome</timezone>
<!-- EL SALVADOR, -6:00 -->
@@ -1160,7 +1166,7 @@
<!-- Sint Maarten, -4:00 -->
- <timezone code="sx">America/Curacao</timezone>
+ <timezone code="sx">America/Lower_Princes</timezone>
<!-- SYRIAN ARAB REPUBLIC, 2:00 -->
@@ -1168,7 +1174,7 @@
<!-- SWAZILAND, 2:00 -->
- <timezone code="sz">Africa/Johannesburg</timezone>
+ <timezone code="sz">Africa/Mbabane</timezone>
<!-- TURKS AND CAICOS ISLANDS, -4:00 -->
@@ -1182,13 +1188,9 @@
<timezone code="tf">Indian/Kerguelen</timezone>
- <!-- FRENCH SOUTHERN TERRITORIES, 4:00 -->
-
- <timezone code="tf">Indian/Reunion</timezone>
-
<!-- TOGO, 0:00 -->
- <timezone code="tg">Africa/Abidjan</timezone>
+ <timezone code="tg">Africa/Lome</timezone>
<!-- THAILAND, 7:00 -->
@@ -1236,7 +1238,7 @@
<!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
- <timezone code="tz">Africa/Nairobi</timezone>
+ <timezone code="tz">Africa/Dar_es_Salaam</timezone>
<!-- UKRAINE, 2:00 -->
@@ -1246,19 +1248,15 @@
<!-- UGANDA, 3:00 -->
- <timezone code="ug">Africa/Nairobi</timezone>
+ <timezone code="ug">Africa/Kampala</timezone>
<!-- UNITED STATES MINOR OUTLYING ISLANDS, 12:00 -->
<timezone code="um">Pacific/Wake</timezone>
- <!-- UNITED STATES MINOR OUTLYING ISLANDS, -10:00 -->
-
- <timezone code="um">Pacific/Honolulu</timezone>
-
<!-- UNITED STATES MINOR OUTLYING ISLANDS, -11:00 -->
- <timezone code="um">Pacific/Pago_Pago</timezone>
+ <timezone code="um">Pacific/Midway</timezone>
<!-- UNITED STATES, -5:00 -->
@@ -1318,11 +1316,11 @@
<!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
- <timezone code="va">Europe/Rome</timezone>
+ <timezone code="va">Europe/Vatican</timezone>
<!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
- <timezone code="vc">America/Port_of_Spain</timezone>
+ <timezone code="vc">America/St_Vincent</timezone>
<!-- VENEZUELA, -4:00 -->
@@ -1330,16 +1328,15 @@
<!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
- <timezone code="vg">America/Port_of_Spain</timezone>
+ <timezone code="vg">America/Tortola</timezone>
<!-- VIRGIN ISLANDS, U.S., -4:00 -->
- <timezone code="vi">America/Port_of_Spain</timezone>
+ <timezone code="vi">America/St_Thomas</timezone>
<!-- VIET NAM, 7:00 -->
<timezone code="vn">Asia/Ho_Chi_Minh</timezone>
- <timezone code="vn">Asia/Bangkok</timezone>
<!-- VANUATU, 11:00 -->
@@ -1355,11 +1352,11 @@
<!-- YEMEN, 3:00 -->
- <timezone code="ye">Asia/Riyadh</timezone>
+ <timezone code="ye">Asia/Aden</timezone>
<!-- MAYOTTE, 3:00 -->
- <timezone code="yt">Africa/Nairobi</timezone>
+ <timezone code="yt">Indian/Mayotte</timezone>
<!-- SOUTH AFRICA, 2:00 -->
@@ -1367,9 +1364,9 @@
<!-- ZAMBIA, 2:00 -->
- <timezone code="zm">Africa/Maputo</timezone>
+ <timezone code="zm">Africa/Lusaka</timezone>
<!-- ZIMBABWE, 2:00 -->
- <timezone code="zw">Africa/Maputo</timezone>
+ <timezone code="zw">Africa/Harare</timezone>
</timezones>
diff --git a/core/tests/coretests/src/android/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/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index 6820e92..1dd3ef6 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -94,7 +94,8 @@
FontResult fontResult = resultList.get(0);
assertEquals(TestFontsProvider.TTC_INDEX, fontResult.getTtcIndex());
assertEquals(TestFontsProvider.VARIATION_SETTINGS, fontResult.getFontVariationSettings());
- assertEquals(TestFontsProvider.STYLE, fontResult.getStyle());
+ assertEquals(TestFontsProvider.NORMAL_WEIGHT, fontResult.getWeight());
+ assertEquals(TestFontsProvider.ITALIC, fontResult.getItalic());
assertNotNull(fontResult.getFileDescriptor());
}
@@ -115,7 +116,8 @@
FontResult fontResult = resultList.get(0);
assertEquals(0, fontResult.getTtcIndex());
assertNull(fontResult.getFontVariationSettings());
- assertEquals(Typeface.NORMAL, fontResult.getStyle());
+ assertEquals(400, fontResult.getWeight());
+ assertFalse(fontResult.getItalic());
assertNotNull(fontResult.getFileDescriptor());
}
@@ -146,10 +148,10 @@
public void testGetFontFromProvider_resultFontNotFoundSecondRow() {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0,
FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
mProvider.setCustomCursor(cursor);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
@@ -160,13 +162,12 @@
public void testGetFontFromProvider_resultFontNotFoundOtherRow() {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0,
FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
mProvider.setCustomCursor(cursor);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
@@ -176,10 +177,10 @@
public void testGetFontFromProvider_resultCodeIsNegativeNumber() {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
- FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL, -5});
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, -5});
mProvider.setCustomCursor(cursor);
mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
diff --git a/core/tests/coretests/src/android/provider/TestFontsProvider.java b/core/tests/coretests/src/android/provider/TestFontsProvider.java
index 13f5318..46906df 100644
--- a/core/tests/coretests/src/android/provider/TestFontsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestFontsProvider.java
@@ -37,7 +37,8 @@
static final String AUTHORITY = "android.provider.TestFontsProvider";
static final int TTC_INDEX = 2;
static final String VARIATION_SETTINGS = "'wdth' 1";
- static final int STYLE = Typeface.BOLD;
+ static final int NORMAL_WEIGHT = 400;
+ static final boolean ITALIC = false;
private ParcelFileDescriptor mPfd;
private boolean mReturnAllFields = true;
@@ -81,8 +82,9 @@
if (mReturnAllFields) {
cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, STYLE, mResultCode });
+ FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+ FontsContract.Columns.RESULT_CODE });
+ cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, 400, 0, mResultCode });
} else {
cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID });
cursor.addRow(new Object[] { 1 });
diff --git a/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/etc/platform.xml b/data/etc/platform.xml
index 344f3c8..86ab3dc 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -181,6 +181,9 @@
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
+ <!-- STOPSHIP(b/36856786): Revert this once it is fixed properly -->
+ <allow-in-power-save package="com.google.android.apps.enterprise.dmagent" />
+
<!-- These are the packages that are white-listed to be able to run as system user -->
<system-user-whitelisted-app package="com.android.settings" />
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..5afe5e9 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;
@@ -356,13 +357,17 @@
long fontSize = fileChannel.size();
ByteBuffer fontBuffer = fileChannel.map(
FileChannel.MapMode.READ_ONLY, 0, fontSize);
- int style = result.getStyle();
- int weight = (style & BOLD) != 0 ? 700 : 400;
- final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(
- result.getFontVariationSettings());
+ int weight = result.getWeight();
+ int italic = result.getItalic() ? Builder.ITALIC : Builder.NORMAL;
+ 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.toArray(new FontConfig.Axis[axes.size()]), weight,
- (style & ITALIC) == 0 ? Builder.NORMAL : Builder.ITALIC)) {
+ axes, weight, 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/FontResult.java b/graphics/java/android/graphics/fonts/FontResult.java
index 3ef99fd..20e736e 100644
--- a/graphics/java/android/graphics/fonts/FontResult.java
+++ b/graphics/java/android/graphics/fonts/FontResult.java
@@ -35,7 +35,8 @@
private final ParcelFileDescriptor mFileDescriptor;
private final int mTtcIndex;
private final String mFontVariationSettings;
- private final int mStyle;
+ private final int mWeight;
+ private final boolean mItalic;
/**
* Creates a FontResult with all the information needed about a provided font.
@@ -45,16 +46,16 @@
* will fail to load in the client application.
* @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
* @param fontVariationSettings If providing a variation font, the settings for it. May be null.
- * @param style One of {@link android.graphics.Typeface#NORMAL},
- * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC}
- * or {@link android.graphics.Typeface#BOLD_ITALIC}
+ * @param weight An integer that indicates the font weight.
+ * @param italic A boolean that indicates the font is italic style or not.
*/
public FontResult(@NonNull ParcelFileDescriptor fileDescriptor, int ttcIndex,
- @Nullable String fontVariationSettings, int style) {
+ @Nullable String fontVariationSettings, int weight, boolean italic) {
mFileDescriptor = Preconditions.checkNotNull(fileDescriptor);
mTtcIndex = ttcIndex;
mFontVariationSettings = fontVariationSettings;
- mStyle = style;
+ mWeight = weight;
+ mItalic = italic;
}
public ParcelFileDescriptor getFileDescriptor() {
@@ -69,8 +70,12 @@
return mFontVariationSettings;
}
- public int getStyle() {
- return mStyle;
+ public int getWeight() {
+ return mWeight;
+ }
+
+ public boolean getItalic() {
+ return mItalic;
}
@Override
@@ -83,14 +88,16 @@
dest.writeParcelable(mFileDescriptor, flags);
dest.writeInt(mTtcIndex);
dest.writeString(mFontVariationSettings);
- dest.writeInt(mStyle);
+ dest.writeInt(mWeight);
+ dest.writeBoolean(mItalic);
}
private FontResult(Parcel in) {
mFileDescriptor = in.readParcelable(null);
mTtcIndex = in.readInt();
mFontVariationSettings = in.readString();
- mStyle = in.readInt();
+ mWeight = in.readInt();
+ mItalic = in.readBoolean();
}
public static final Parcelable.Creator<FontResult> CREATOR =
diff --git a/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/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 2ead5c5..d26eb59 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -162,7 +162,7 @@
SkAutoCanvasRestore acr(canvas, true);
SkMatrix shadowMatrix;
- mat4 hwuiMatrix(caster->getRecordedMatrix());
+ mat4 hwuiMatrix;
// TODO we don't pass the optional boolean to treat it as a 4x4 matrix
caster->getRenderNode()->applyViewPropertyTransforms(hwuiMatrix);
hwuiMatrix.copyTo(shadowMatrix);
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 652954b..686d06f 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -941,3 +941,67 @@
EXPECT_EQ(2, canvas.mDrawCounter);
}
+
+TEST(ReorderBarrierDrawable, testShadowMatrix) {
+ static const int CANVAS_WIDTH = 100;
+ static const int CANVAS_HEIGHT = 100;
+ static const float TRANSLATE_X = 11.0f;
+ static const float TRANSLATE_Y = 22.0f;
+ static const float CASTER_X = 40.0f;
+ static const float CASTER_Y = 40.0f;
+ static const float CASTER_WIDTH = 20.0f;
+ static const float CASTER_HEIGHT = 20.0f;
+
+
+ class ShadowTestCanvas : public SkCanvas {
+ public:
+ ShadowTestCanvas(int width, int height) : SkCanvas(width, height) {}
+ int getIndex() { return mDrawCounter; }
+
+ virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
+ // expect to draw 2 RenderNodeDrawable, 1 StartReorderBarrierDrawable,
+ // 1 EndReorderBarrierDrawable
+ mDrawCounter++;
+ SkCanvas::onDrawDrawable(drawable, matrix);
+ }
+
+ virtual void didTranslate(SkScalar dx, SkScalar dy) override {
+ mDrawCounter++;
+ EXPECT_EQ(dx, TRANSLATE_X);
+ EXPECT_EQ(dy, TRANSLATE_Y);
+ }
+
+ virtual void didConcat(const SkMatrix& matrix) override {
+ // This function is invoked by EndReorderBarrierDrawable::drawShadow to apply shadow
+ // matrix.
+ mDrawCounter++;
+ EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X, CASTER_Y), matrix);
+ EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X+TRANSLATE_X, CASTER_Y+TRANSLATE_Y),
+ getTotalMatrix());
+ }
+ protected:
+ int mDrawCounter = 0;
+ };
+
+ auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.translate(TRANSLATE_X, TRANSLATE_Y);
+ canvas.insertReorderBarrier(true);
+
+ auto node = TestUtils::createSkiaNode(CASTER_X, CASTER_Y, CASTER_X + CASTER_WIDTH,
+ CASTER_Y + CASTER_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ props.setElevation(42);
+ props.mutableOutline().setRoundRect(0, 0, 20, 20, 5, 1);
+ props.mutableOutline().setShouldClip(true);
+ });
+ canvas.drawRenderNode(node.get());
+ canvas.insertReorderBarrier(false);
+ });
+
+ //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+ ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
+ RenderNodeDrawable drawable(parent.get(), &canvas, false);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(6, canvas.getIndex());
+}
\ No newline at end of file
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c7796cd..4adbf79 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2540,6 +2540,44 @@
/**
* @hide
+ * Notifies an application with a focus listener of gain or loss of audio focus.
+ * This method can only be used by owners of an {@link AudioPolicy} configured with
+ * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to true.
+ * @param afi the recipient of the focus change, that has previously requested audio focus, and
+ * that was received by the {@code AudioPolicy} through
+ * {@link AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(AudioFocusInfo, int)}.
+ * @param focusChange one of focus gain types ({@link #AUDIOFOCUS_GAIN},
+ * {@link #AUDIOFOCUS_GAIN_TRANSIENT}, {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} or
+ * {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE})
+ * or one of the focus loss types ({@link AudioManager#AUDIOFOCUS_LOSS},
+ * {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT},
+ * or {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}).
+ * <br>For the focus gain, the change type should be the same as the app requested.
+ * @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
+ * @return {@link #AUDIOFOCUS_REQUEST_GRANTED} if the dispatch was successfully sent, or
+ * {@link #AUDIOFOCUS_REQUEST_FAILED} if the focus client didn't have a listener, or
+ * if there was an error sending the request.
+ * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
+ */
+ @SystemApi
+ public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
+ @NonNull AudioPolicy ap) {
+ if (afi == null) {
+ throw new NullPointerException("Illegal null AudioFocusInfo");
+ }
+ if (ap == null) {
+ throw new NullPointerException("Illegal null AudioPolicy");
+ }
+ final IAudioService service = getService();
+ try {
+ return service.dispatchFocusChange(afi, focusChange, ap.cb());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
* Used internally by telephony package to abandon audio focus, typically after a call or
* when ringing ends and the call is rejected or not answered.
* Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
@@ -2548,7 +2586,7 @@
final IAudioService service = getService();
try {
service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID,
- null /*AudioAttributes, legacy behavior*/);
+ null /*AudioAttributes, legacy behavior*/, getContext().getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2579,7 +2617,7 @@
final IAudioService service = getService();
try {
status = service.abandonAudioFocus(mAudioFocusDispatcher,
- getIdForAudioFocusListener(l), aa);
+ getIdForAudioFocusListener(l), aa, getContext().getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2787,7 +2825,7 @@
final IAudioService service = getService();
try {
String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
- policy.hasFocusListener());
+ policy.hasFocusListener(), policy.isFocusPolicy());
if (regId == null) {
return ERROR;
} else {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5855984..884d41e 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -20,6 +20,7 @@
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.media.AudioAttributes;
+import android.media.AudioFocusInfo;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioRecordingConfiguration;
import android.media.AudioRoutesInfo;
@@ -122,7 +123,8 @@
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
IAudioPolicyCallback pcb);
- int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa);
+ int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa,
+ in String callingPackageName);
void unregisterAudioFocusClient(String clientId);
@@ -164,7 +166,7 @@
boolean isHdmiSystemAudioSupported();
String registerAudioPolicy(in AudioPolicyConfig policyConfig,
- in IAudioPolicyCallback pcb, boolean hasFocusListener);
+ in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy);
oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
@@ -196,5 +198,8 @@
int getFocusRampTimeMs(in int focusGain, in AudioAttributes attr);
+ int dispatchFocusChange(in AudioFocusInfo afi, in int focusChange,
+ in IAudioPolicyCallback pcb);
+
// WARNING: read warning at top of file, it is recommended to add new methods at the end
}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index cdc1d60..4675e32 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -746,14 +746,19 @@
}
/**
- * Sets the video encoding profile for recording. Call this method before prepare().
- * Prepare() may perform additional checks on the parameter to make sure whether the
- * specified profile and level are applicable, and sometimes the passed profile or
- * level will be discarded due to codec capablity or to ensure the video recording
- * can proceed smoothly based on the capabilities of the platform.
- * @hide
+ * Sets the desired video encoding profile and level for recording. The profile and level
+ * must be valid for the video encoder set by {@link #setVideoEncoder}. This method can
+ * called before or after {@link #setVideoEncoder} but it must be called before {@link #prepare}.
+ * {@code prepare()} may perform additional checks on the parameter to make sure that the specified
+ * profile and level are applicable, and sometimes the passed profile or level will be
+ * discarded due to codec capablity or to ensure the video recording can proceed smoothly
+ * based on the capabilities of the platform. <br>Application can also use the
+ * {@link MediaCodecInfo.CodecCapabilities#profileLevels} to query applicable combination of profile
+ * and level for the corresponding format. Note that the requested profile/level may not be supported by
+ * the codec that is actually being used by this MediaRecorder instance.
* @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}.
* @param level declared in {@link MediaCodecInfo.CodecProfileLevel}.
+ * @throws IllegalArgumentException when an invalid profile or level value is used.
*/
public void setVideoEncodingProfileLevel(int profile, int level) {
if (profile <= 0) {
@@ -1281,3 +1286,4 @@
@Override
protected void finalize() { native_finalize(); }
}
+
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 423b467..61d642f 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -68,6 +68,7 @@
private int mStatus;
private String mRegistrationId;
private AudioPolicyStatusListener mStatusListener;
+ private boolean mIsFocusPolicy;
/**
* The behavior of a policy with regards to audio focus where it relies on the application
@@ -96,12 +97,14 @@
public AudioPolicyConfig getConfig() { return mConfig; }
/** @hide */
public boolean hasFocusListener() { return mFocusListener != null; }
+ /** @hide */
+ public boolean isFocusPolicy() { return mIsFocusPolicy; }
/**
* The parameter is guaranteed non-null through the Builder
*/
private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
- AudioPolicyFocusListener fl, AudioPolicyStatusListener sl) {
+ AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy) {
mConfig = config;
mStatus = POLICY_STATUS_UNREGISTERED;
mContext = context;
@@ -116,10 +119,12 @@
}
mFocusListener = fl;
mStatusListener = sl;
+ mIsFocusPolicy = isFocusPolicy;
}
/**
- * Builder class for {@link AudioPolicy} objects
+ * Builder class for {@link AudioPolicy} objects.
+ * By default the policy to be created doesn't govern audio focus decisions.
*/
@SystemApi
public static class Builder {
@@ -128,6 +133,7 @@
private Looper mLooper;
private AudioPolicyFocusListener mFocusListener;
private AudioPolicyStatusListener mStatusListener;
+ private boolean mIsFocusPolicy = false;
/**
* Constructs a new Builder with no audio mixes.
@@ -179,6 +185,21 @@
}
/**
+ * Declares whether this policy will grant and deny audio focus through
+ * the {@link AudioPolicy.AudioPolicyStatusListener}.
+ * If set to {@code true}, it is mandatory to set an
+ * {@link AudioPolicy.AudioPolicyStatusListener} in order to successfully build
+ * an {@code AudioPolicy} instance.
+ * @param enforce true if the policy will govern audio focus decisions.
+ * @return the same Builder instance.
+ */
+ @SystemApi
+ public Builder setIsAudioFocusPolicy(boolean isFocusPolicy) {
+ mIsFocusPolicy = isFocusPolicy;
+ return this;
+ }
+
+ /**
* Sets the audio policy status listener.
* @param l a {@link AudioPolicy.AudioPolicyStatusListener}
*/
@@ -187,6 +208,14 @@
mStatusListener = l;
}
+ /**
+ * Combines all of the attributes that have been set on this {@code Builder} and returns a
+ * new {@link AudioPolicy} object.
+ * @return a new {@code AudioPolicy} object.
+ * @throws IllegalStateException if there is no
+ * {@link AudioPolicy.AudioPolicyStatusListener} but the policy was configured
+ * as an audio focus policy with {@link #setIsAudioFocusPolicy(boolean)}.
+ */
@SystemApi
public AudioPolicy build() {
if (mStatusListener != null) {
@@ -195,8 +224,12 @@
mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY;
}
}
+ if (mIsFocusPolicy && mFocusListener == null) {
+ throw new IllegalStateException("Cannot be a focus policy without "
+ + "an AudioPolicyFocusListener");
+ }
return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
- mFocusListener, mStatusListener);
+ mFocusListener, mStatusListener, mIsFocusPolicy);
}
}
@@ -402,6 +435,24 @@
public static abstract class AudioPolicyFocusListener {
public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {}
public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {}
+ /**
+ * Called whenever an application requests audio focus.
+ * Only ever called if the {@link AudioPolicy} was built with
+ * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
+ * @param afi information about the focus request and the requester
+ * @param requestResult the result that was returned synchronously by the framework to the
+ * application, {@link #AUDIOFOCUS_REQUEST_FAILED},or
+ * {@link #AUDIOFOCUS_REQUEST_DELAYED}.
+ */
+ public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {}
+ /**
+ * Called whenever an application abandons audio focus.
+ * Only ever called if the {@link AudioPolicy} was built with
+ * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
+ * @param afi information about the focus request being abandoned and the original
+ * requester.
+ */
+ public void onAudioFocusAbandon(AudioFocusInfo afi) {}
}
private void onPolicyStatusChange() {
@@ -439,6 +490,22 @@
}
}
+ public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
+ sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
+ if (DEBUG) {
+ Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
+ + afi.getClientId() + "reqRes=" + requestResult);
+ }
+ }
+
+ public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
+ sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
+ if (DEBUG) {
+ Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
+ + afi.getClientId());
+ }
+ }
+
public void notifyMixStateUpdate(String regId, int state) {
for (AudioMix mix : mConfig.getMixes()) {
if (mix.getRegistration().equals(regId)) {
@@ -459,6 +526,8 @@
private final static int MSG_FOCUS_GRANT = 1;
private final static int MSG_FOCUS_LOSS = 2;
private final static int MSG_MIX_STATE_UPDATE = 3;
+ private final static int MSG_FOCUS_REQUEST = 4;
+ private final static int MSG_FOCUS_ABANDON = 5;
private class EventHandler extends Handler {
public EventHandler(AudioPolicy ap, Looper looper) {
@@ -488,6 +557,20 @@
mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
}
break;
+ case MSG_FOCUS_REQUEST:
+ if (mFocusListener != null) {
+ mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
+ } else { // should never be null, but don't crash
+ Log.e(TAG, "Invalid null focus listener for focus request event");
+ }
+ break;
+ case MSG_FOCUS_ABANDON:
+ if (mFocusListener != null) { // should never be null
+ mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj);
+ } else { // should never be null, but don't crash
+ Log.e(TAG, "Invalid null focus listener for focus abandon event");
+ }
+ break;
default:
Log.e(TAG, "Unknown event " + msg.what);
}
diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
index ad8af15..86abbb4 100644
--- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
+++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
@@ -22,9 +22,12 @@
*/
oneway interface IAudioPolicyCallback {
- // callbacks for audio focus
+ // callbacks for audio focus listening
void notifyAudioFocusGrant(in AudioFocusInfo afi, int requestResult);
void notifyAudioFocusLoss(in AudioFocusInfo afi, boolean wasNotified);
+ // callback for audio focus policy
+ void notifyAudioFocusRequest(in AudioFocusInfo afi, int requestResult);
+ void notifyAudioFocusAbandon(in AudioFocusInfo afi);
// callback for mix activity status update
void notifyMixStateUpdate(in String regId, int state);
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index fc60571..0b27d18 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -16,6 +16,7 @@
package android.media.tv;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
@@ -567,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.
*
@@ -835,12 +837,13 @@
}
/**
- * 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 */
- @StringDef({
+ @IntDef({
TYPE_MOVIE,
TYPE_TV_SERIES,
TYPE_TV_SEASON,
@@ -862,87 +865,87 @@
*
* @see #COLUMN_TYPE
*/
- String TYPE_MOVIE = "TYPE_MOVIE";
+ int TYPE_MOVIE = 0;
/**
* The program type for TV series.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+ int TYPE_TV_SERIES = 1;
/**
* The program type for TV season.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+ int TYPE_TV_SEASON = 2;
/**
* The program type for TV episode.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+ int TYPE_TV_EPISODE = 3;
/**
* The program type for clip.
*
* @see #COLUMN_TYPE
*/
- String TYPE_CLIP = "TYPE_CLIP";
+ int TYPE_CLIP = 4;
/**
* The program type for event.
*
* @see #COLUMN_TYPE
*/
- String TYPE_EVENT = "TYPE_EVENT";
+ int TYPE_EVENT = 5;
/**
* The program type for channel.
*
* @see #COLUMN_TYPE
*/
- String TYPE_CHANNEL = "TYPE_CHANNEL";
+ int TYPE_CHANNEL = 6;
/**
* The program type for track.
*
* @see #COLUMN_TYPE
*/
- String TYPE_TRACK = "TYPE_TRACK";
+ int TYPE_TRACK = 7;
/**
* The program type for album.
*
* @see #COLUMN_TYPE
*/
- String TYPE_ALBUM = "TYPE_ALBUM";
+ int TYPE_ALBUM = 8;
/**
* The program type for artist.
*
* @see #COLUMN_TYPE
*/
- String TYPE_ARTIST = "TYPE_ARTIST";
+ int TYPE_ARTIST = 9;
/**
* The program type for playlist.
*
* @see #COLUMN_TYPE
*/
- String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+ int TYPE_PLAYLIST = 10;
/**
* The program type for station.
*
* @see #COLUMN_TYPE
*/
- String TYPE_STATION = "TYPE_STATION";
+ int TYPE_STATION = 11;
/** @hide */
- @StringDef({
+ @IntDef({
ASPECT_RATIO_16_9,
ASPECT_RATIO_3_2,
ASPECT_RATIO_1_1,
@@ -957,7 +960,7 @@
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+ int ASPECT_RATIO_16_9 = 0;
/**
* The aspect ratio for 3:2.
@@ -965,7 +968,7 @@
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+ int ASPECT_RATIO_3_2 = 1;
/**
* The aspect ratio for 1:1.
@@ -973,7 +976,7 @@
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+ int ASPECT_RATIO_1_1 = 2;
/**
* The aspect ratio for 2:3.
@@ -981,10 +984,10 @@
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+ int ASPECT_RATIO_2_3 = 3;
/** @hide */
- @StringDef({
+ @IntDef({
AVAILABILITY_AVAILABLE,
AVAILABILITY_FREE_WITH_SUBSCRIPTION,
AVAILABILITY_PAID_CONTENT,
@@ -997,15 +1000,14 @@
*
* @see #COLUMN_AVAILABILITY
*/
- String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+ int AVAILABILITY_AVAILABLE = 0;
/**
* The availability for "free with subscription".
*
* @see #COLUMN_AVAILABILITY
*/
- String AVAILABILITY_FREE_WITH_SUBSCRIPTION =
- "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+ int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1;
/**
* The availability for "paid content, either to-own or rental
@@ -1013,72 +1015,72 @@
*
* @see #COLUMN_AVAILABILITY
*/
- String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+ int AVAILABILITY_PAID_CONTENT = 2;
/** @hide */
- @StringDef({
+ @IntDef({
+ INTERACTION_TYPE_VIEWS,
INTERACTION_TYPE_LISTENS,
INTERACTION_TYPE_FOLLOWERS,
INTERACTION_TYPE_FANS,
INTERACTION_TYPE_LIKES,
INTERACTION_TYPE_THUMBS,
- INTERACTION_TYPE_VIEWS,
INTERACTION_TYPE_VIEWERS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InteractionType {}
/**
+ * The interaction type for "views".
+ *
+ * @see #COLUMN_INTERACTION_TYPE
+ */
+ int INTERACTION_TYPE_VIEWS = 0;
+
+ /**
* The interaction type for "listens".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+ int INTERACTION_TYPE_LISTENS = 1;
/**
* The interaction type for "followers".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+ int INTERACTION_TYPE_FOLLOWERS = 2;
/**
* The interaction type for "fans".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+ int INTERACTION_TYPE_FANS = 3;
/**
* The interaction type for "likes".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+ int INTERACTION_TYPE_LIKES = 4;
/**
* The interaction type for "thumbs".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-
- /**
- * The interaction type for "views".
- *
- * @see #COLUMN_INTERACTION_TYPE
- */
- String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+ int INTERACTION_TYPE_THUMBS = 5;
/**
* The interaction type for "viewers".
*
* @see #COLUMN_INTERACTION_TYPE
*/
- String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+ int INTERACTION_TYPE_VIEWERS = 6;
/** @hide */
- @StringDef({
+ @IntDef({
REVIEW_RATING_STYLE_STARS,
REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
REVIEW_RATING_STYLE_PERCENTAGE,
@@ -1091,23 +1093,21 @@
*
* @see #COLUMN_REVIEW_RATING_STYLE
*/
- String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+ int REVIEW_RATING_STYLE_STARS = 0;
/**
* The review rating style for thumbs-up and thumbs-down rating.
*
* @see #COLUMN_REVIEW_RATING_STYLE
*/
- String REVIEW_RATING_STYLE_THUMBS_UP_DOWN =
- "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+ int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1;
/**
* The review rating style for 0 to 100 point system.
*
* @see #COLUMN_REVIEW_RATING_STYLE
*/
- String REVIEW_RATING_STYLE_PERCENTAGE =
- "REVIEW_RATING_STYLE_PERCENTAGE";
+ int REVIEW_RATING_STYLE_PERCENTAGE = 2;
/**
* The type of this program content.
@@ -1129,7 +1129,7 @@
* <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
* channel.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_TYPE = "type";
@@ -1142,7 +1142,7 @@
* {@link #ASPECT_RATIO_1_1}, and
* {@link #ASPECT_RATIO_2_3}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
@@ -1155,7 +1155,7 @@
* {@link #ASPECT_RATIO_1_1}, and
* {@link #ASPECT_RATIO_2_3}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
@@ -1188,7 +1188,7 @@
* {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
* {@link #AVAILABILITY_PAID_CONTENT}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_AVAILABILITY = "availability";
@@ -1327,15 +1327,15 @@
* The type of interaction for this TV program.
*
* <p> The value should match one of the followings:
+ * {@link #INTERACTION_TYPE_VIEWS},
* {@link #INTERACTION_TYPE_LISTENS},
* {@link #INTERACTION_TYPE_FOLLOWERS},
* {@link #INTERACTION_TYPE_FANS},
* {@link #INTERACTION_TYPE_LIKES},
- * {@link #INTERACTION_TYPE_THUMBS},
- * {@link #INTERACTION_TYPE_VIEWS}, and
+ * {@link #INTERACTION_TYPE_THUMBS}, and
* {@link #INTERACTION_TYPE_VIEWERS}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
* @see #COLUMN_INTERACTION_COUNT
*/
String COLUMN_INTERACTION_TYPE = "interaction_type";
@@ -1363,7 +1363,7 @@
* <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
* {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
* @see #COLUMN_REVIEW_RATING
*/
String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
@@ -2229,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 + "/"
@@ -2543,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 + "/"
@@ -2665,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 + "/"
@@ -2711,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 + "/"
@@ -2724,7 +2726,7 @@
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
/** @hide */
- @StringDef({
+ @IntDef({
WATCH_NEXT_TYPE_CONTINUE,
WATCH_NEXT_TYPE_NEXT,
WATCH_NEXT_TYPE_NEW,
@@ -2739,7 +2741,7 @@
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+ public static final int WATCH_NEXT_TYPE_CONTINUE = 0;
/**
* The watch next type for NEXT. Use this type when the user has watched one or more
@@ -2749,7 +2751,7 @@
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+ public static final int WATCH_NEXT_TYPE_NEXT = 1;
/**
* The watch next type for NEW. Use this type when the user had watched all of the available
@@ -2759,7 +2761,7 @@
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+ public static final int WATCH_NEXT_TYPE_NEW = 2;
/**
* The watch next type for WATCHLIST. Use this type when the user has elected to explicitly
@@ -2768,7 +2770,7 @@
*
* @see #COLUMN_WATCH_NEXT_TYPE
*/
- public static final String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+ public static final int WATCH_NEXT_TYPE_WATCHLIST = 3;
/**
* The "watch next" type of this program content.
@@ -2781,7 +2783,7 @@
*
* <p>This is a required field.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index d5d9fc9..0149d76 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -342,7 +342,7 @@
}
// New GraphicBuffer object doesn't own the handle, thus the native buffer
// won't be freed when this object is destroyed.
- sp<GraphicBuffer> buffer(new GraphicBuffer(anb, /*keepOwnership*/false));
+ sp<GraphicBuffer> buffer(GraphicBuffer::from(anb));
// Note that:
// 1. No need to lock buffer now, will only lock it when the first getPlanes() is called.
diff --git a/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/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index f9342b7..fa5c3ff 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -6,6 +6,7 @@
<string name="no_data_notification_id">Your mobile data has been deactivated</string>
<string name="portal_notification_detail">Tap to visit the %s website</string>
<string name="no_data_notification_detail">Please contact your service provider %s</string>
+ <string name="mobile_data_status_notification_channel_name">Mobile data status</string>
<string name="action_bar_label">Sign in to mobile network</string>
<string name="ssl_error_warning">The network you’re trying to join has security issues.</string>
<string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 73ff3a9..7fd1601 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -16,6 +16,7 @@
package com.android.carrierdefaultapp;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -35,6 +36,7 @@
private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
+ private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status";
private static final int PORTAL_NOTIFICATION_ID = 0;
private static final int NO_DATA_NOTIFICATION_ID = 1;
private static boolean ENABLE = true;
@@ -150,9 +152,18 @@
private static Notification getNotification(Context context, int titleId, int textId,
PendingIntent pendingIntent) {
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ final NotificationManager notificationManager = context.getSystemService(
+ NotificationManager.class);
final Resources resources = context.getResources();
final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
resources.getString(R.string.android_system_label));
+ /* Creates the notification channel and registers it with NotificationManager. If a channel
+ * with the same ID is already registered, NotificationManager will ignore this call.
+ */
+ notificationManager.createNotificationChannel(new NotificationChannel(
+ NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
+ resources.getString(R.string.mobile_data_status_notification_channel_name),
+ NotificationManager.IMPORTANCE_DEFAULT));
Notification.Builder builder = new Notification.Builder(context)
.setContentTitle(resources.getString(titleId))
.setContentText(String.format(resources.getString(textId),
@@ -167,7 +178,8 @@
.setLocalOnly(true)
.setWhen(System.currentTimeMillis())
.setShowWhen(false)
- .setExtras(extras);
+ .setExtras(extras)
+ .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS);
if (pendingIntent != null) {
builder.setContentIntent(pendingIntent);
diff --git a/packages/SettingsLib/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/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index c2ce7c9..8833fb8c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -1394,7 +1394,9 @@
@Override
public boolean filterApp(AppEntry entry) {
- if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ if (AppUtils.isInstant(entry.info)) {
+ return false;
+ } else if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
return true;
} else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
return true;
@@ -1407,6 +1409,23 @@
}
};
+ /**
+ * Displays a combined list with "downloaded" and "visible in launcher" apps only.
+ */
+ public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT = new AppFilter() {
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return AppUtils.isInstant(entry.info)
+ || FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(entry);
+ }
+
+ };
+
public static final AppFilter FILTER_THIRD_PARTY = new AppFilter() {
@Override
public void init() {
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/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index a3ae926..abd4e29 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -103,7 +103,7 @@
*/
public String getName(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
- if (cachedDevice != null) {
+ if (cachedDevice != null && cachedDevice.getName() != null) {
return cachedDevice.getName();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index 40abb6c..88f133c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -41,8 +41,8 @@
long privateTotalBytes = 0;
for (VolumeInfo info : sm.getVolumes()) {
if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
- privateTotalBytes += stats.getTotalBytes(info.getFsUuid());
- privateFreeBytes += stats.getFreeBytes(info.getFsUuid());
+ privateTotalBytes += sm.getTotalBytes(stats, info);
+ privateFreeBytes += sm.getFreeBytes(stats, info);
}
}
return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
index 320494c..11060e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -16,6 +16,7 @@
package com.android.settingslib.deviceinfo;
+import android.app.usage.StorageStatsManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
@@ -46,4 +47,14 @@
public VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume) {
return mStorageManager.findEmulatedForPrivate(privateVolume);
}
+
+ @Override
+ public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) {
+ return stats.getTotalBytes(volume.getFsUuid());
+ }
+
+ @Override
+ public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) {
+ return stats.getFreeBytes(volume.getFsUuid());
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
index 646c42f..e5d85d1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -16,6 +16,7 @@
package com.android.settingslib.deviceinfo;
+import android.app.usage.StorageStatsManager;
import android.os.storage.VolumeInfo;
import java.util.List;
@@ -39,4 +40,18 @@
* Returns the emulated volume for a given private volume.
*/
VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume);
+
+ /**
+ * Returns the total bytes for a given storage volume.
+ *
+ * @pre The volume is a private volume and is readable.
+ */
+ long getTotalBytes(StorageStatsManager stats, VolumeInfo volume);
+
+ /**
+ * Returns the free bytes for a given storage volume.
+ *
+ * @pre The volume is a private volume and is readable.
+ */
+ long getFreeBytes(StorageStatsManager stats, VolumeInfo volume);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
new file mode 100755
index 0000000..1bbc878b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.inputmethod;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.Toast;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.settingslib.R;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import java.text.Collator;
+import java.util.List;
+
+/**
+ * Input method preference.
+ *
+ * This preference represents an IME. It is used for two purposes. 1) An instance with a switch
+ * is used to enable or disable the IME. 2) An instance without a switch is used to invoke the
+ * setting activity of the IME.
+ */
+public class InputMethodPreference extends RestrictedSwitchPreference implements OnPreferenceClickListener,
+ OnPreferenceChangeListener {
+ private static final String TAG = InputMethodPreference.class.getSimpleName();
+ private static final String EMPTY_TEXT = "";
+ private static final int NO_WIDGET = 0;
+
+ public interface OnSavePreferenceListener {
+ /**
+ * Called when this preference needs to be saved its state.
+ *
+ * Note that this preference is non-persistent and needs explicitly to be saved its state.
+ * Because changing one IME state may change other IMEs' state, this is a place to update
+ * other IMEs' state as well.
+ *
+ * @param pref This preference.
+ */
+ void onSaveInputMethodPreference(InputMethodPreference pref);
+ }
+
+ private final InputMethodInfo mImi;
+ private final boolean mHasPriorityInSorting;
+ private final OnSavePreferenceListener mOnSaveListener;
+ private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
+ private final boolean mIsAllowedByOrganization;
+
+ private AlertDialog mDialog = null;
+
+ /**
+ * A preference entry of an input method.
+ *
+ * @param context The Context this is associated with.
+ * @param imi The {@link InputMethodInfo} of this preference.
+ * @param isImeEnabler true if this preference is the IME enabler that has enable/disable
+ * switches for all available IMEs, not the list of enabled IMEs.
+ * @param isAllowedByOrganization false if the IME has been disabled by a device or profile
+ * owner.
+ * @param onSaveListener The listener called when this preference has been changed and needs
+ * to save the state to shared preference.
+ */
+ public InputMethodPreference(final Context context, final InputMethodInfo imi,
+ final boolean isImeEnabler, final boolean isAllowedByOrganization,
+ final OnSavePreferenceListener onSaveListener) {
+ super(context);
+ setPersistent(false);
+ mImi = imi;
+ mIsAllowedByOrganization = isAllowedByOrganization;
+ mOnSaveListener = onSaveListener;
+ if (!isImeEnabler) {
+ // Remove switch widget.
+ setWidgetLayoutResource(NO_WIDGET);
+ }
+ // Disable on/off switch texts.
+ setSwitchTextOn(EMPTY_TEXT);
+ setSwitchTextOff(EMPTY_TEXT);
+ setKey(imi.getId());
+ setTitle(imi.loadLabel(context.getPackageManager()));
+ final String settingsActivity = imi.getSettingsActivity();
+ if (TextUtils.isEmpty(settingsActivity)) {
+ setIntent(null);
+ } else {
+ // Set an intent to invoke settings activity of an input method.
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(imi.getPackageName(), settingsActivity);
+ setIntent(intent);
+ }
+ mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(context);
+ mHasPriorityInSorting = InputMethodUtils.isSystemIme(imi)
+ && mInputMethodSettingValues.isValidSystemNonAuxAsciiCapableIme(imi, context);
+ setOnPreferenceClickListener(this);
+ setOnPreferenceChangeListener(this);
+ }
+
+ public InputMethodInfo getInputMethodInfo() {
+ return mImi;
+ }
+
+ private boolean isImeEnabler() {
+ // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the
+ // switch widget at constructor.
+ return getWidgetLayoutResource() != NO_WIDGET;
+ }
+
+ @Override
+ public boolean onPreferenceChange(final Preference preference, final Object newValue) {
+ // Always returns false to prevent default behavior.
+ // See {@link TwoStatePreference#onClick()}.
+ if (!isImeEnabler()) {
+ // Prevent disabling an IME because this preference is for invoking a settings activity.
+ return false;
+ }
+ if (isChecked()) {
+ // Disable this IME.
+ setCheckedInternal(false);
+ return false;
+ }
+ if (InputMethodUtils.isSystemIme(mImi)) {
+ // Enable a system IME. No need to show a security warning dialog,
+ // but we might need to prompt if it's not Direct Boot aware.
+ // TV doesn't doesn't need to worry about this, but other platforms should show
+ // a warning.
+ if (mImi.getServiceInfo().directBootAware || isTv()) {
+ setCheckedInternal(true);
+ } else if (!isTv()){
+ showDirectBootWarnDialog();
+ }
+ } else {
+ // Once security is confirmed, we might prompt if the IME isn't
+ // Direct Boot aware.
+ showSecurityWarnDialog();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onPreferenceClick(final Preference preference) {
+ // Always returns true to prevent invoking an intent without catching exceptions.
+ // See {@link Preference#performClick(PreferenceScreen)}/
+ if (isImeEnabler()) {
+ // Prevent invoking a settings activity because this preference is for enabling and
+ // disabling an input method.
+ return true;
+ }
+ final Context context = getContext();
+ try {
+ final Intent intent = getIntent();
+ if (intent != null) {
+ // Invoke a settings activity of an input method.
+ context.startActivity(intent);
+ }
+ } catch (final ActivityNotFoundException e) {
+ Log.d(TAG, "IME's Settings Activity Not Found", e);
+ final String message = context.getString(
+ R.string.failed_to_open_app_settings_toast,
+ mImi.loadLabel(context.getPackageManager()));
+ Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+ }
+ return true;
+ }
+
+ public void updatePreferenceViews() {
+ final boolean isAlwaysChecked = mInputMethodSettingValues.isAlwaysCheckedIme(
+ mImi, getContext());
+ // When this preference has a switch and an input method should be always enabled,
+ // this preference should be disabled to prevent accidentally disabling an input method.
+ // This preference should also be disabled in case the admin does not allow this input
+ // method.
+ if (isAlwaysChecked && isImeEnabler()) {
+ setDisabledByAdmin(null);
+ setEnabled(false);
+ } else if (!mIsAllowedByOrganization) {
+ EnforcedAdmin admin =
+ RestrictedLockUtils.checkIfInputMethodDisallowed(getContext(),
+ mImi.getPackageName(), UserHandle.myUserId());
+ setDisabledByAdmin(admin);
+ } else {
+ setEnabled(true);
+ }
+ setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
+ if (!isDisabledByAdmin()) {
+ setSummary(getSummaryString());
+ }
+ }
+
+ private InputMethodManager getInputMethodManager() {
+ return (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+
+ private String getSummaryString() {
+ final InputMethodManager imm = getInputMethodManager();
+ final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
+ return InputMethodAndSubtypeUtil.getSubtypeLocaleNameListAsSentence(
+ subtypes, getContext(), mImi);
+ }
+
+ private void setCheckedInternal(boolean checked) {
+ super.setChecked(checked);
+ mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
+ notifyChanged();
+ }
+
+ private void showSecurityWarnDialog() {
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ final Context context = getContext();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setCancelable(true /* cancelable */);
+ builder.setTitle(android.R.string.dialog_alert_title);
+ final CharSequence label = mImi.getServiceInfo().applicationInfo.loadLabel(
+ context.getPackageManager());
+ builder.setMessage(context.getString(R.string.ime_security_warning, label));
+ builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
+ // The user confirmed to enable a 3rd party IME, but we might
+ // need to prompt if it's not Direct Boot aware.
+ // TV doesn't doesn't need to worry about this, but other platforms should show
+ // a warning.
+ if (mImi.getServiceInfo().directBootAware || isTv()) {
+ setCheckedInternal(true);
+ } else {
+ showDirectBootWarnDialog();
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+ // The user canceled to enable a 3rd party IME.
+ setCheckedInternal(false);
+ });
+ mDialog = builder.create();
+ mDialog.show();
+ }
+
+ private boolean isTv() {
+ return (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION;
+ }
+
+ private void showDirectBootWarnDialog() {
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ final Context context = getContext();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setCancelable(true /* cancelable */);
+ builder.setMessage(context.getText(R.string.direct_boot_unaware_dialog_message));
+ builder.setPositiveButton(android.R.string.ok, (dialog, which) -> setCheckedInternal(true));
+ builder.setNegativeButton(android.R.string.cancel,
+ (dialog, which) -> setCheckedInternal(false));
+ mDialog = builder.create();
+ mDialog.show();
+ }
+
+ public int compareTo(final InputMethodPreference rhs, final Collator collator) {
+ if (this == rhs) {
+ return 0;
+ }
+ if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
+ final CharSequence t0 = getTitle();
+ final CharSequence t1 = rhs.getTitle();
+ if (TextUtils.isEmpty(t0)) {
+ return 1;
+ }
+ if (TextUtils.isEmpty(t1)) {
+ return -1;
+ }
+ return collator.compare(t0.toString(), t1.toString());
+ }
+ // Prefer always checked system IMEs
+ return mHasPriorityInSorting ? -1 : 1;
+ }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index e204a3a..6a029f0 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -110,6 +110,70 @@
}
@Test
+ public void testDownloadAndLauncherAndInstantAcceptsCorrectApps() {
+ // should include instant apps
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+ when(mEntry.info.isInstantApp()).thenReturn(true);
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+
+ // should included updated system apps
+ when(mEntry.info.isInstantApp()).thenReturn(false);
+ mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+
+ // should not include system apps other than the home app
+ mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isFalse();
+
+ // should include the home app
+ mEntry.isHomeApp = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+
+ // should include any System app with a launcher entry
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+ .isTrue();
+ }
+
+ @Test
+ public void testDownloadAndLauncherAcceptsCorrectApps() {
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+
+ // should included updated system apps
+ when(mEntry.info.isInstantApp()).thenReturn(false);
+ mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isTrue();
+
+ // should not include system apps other than the home app
+ mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = false;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isFalse();
+
+ // should include the home app
+ mEntry.isHomeApp = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isTrue();
+
+ // should include any System app with a launcher entry
+ mEntry.isHomeApp = false;
+ mEntry.hasLauncherEntry = true;
+ assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+ .isTrue();
+ }
+
+ @Test
public void testInstantFilterAcceptsInstantApp() {
when(mEntry.info.isInstantApp()).thenReturn(true);
assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isTrue();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 0d0ddf2..1f559e4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2798,7 +2798,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 143;
+ private static final int SETTINGS_VERSION = 144;
private final int mUserId;
@@ -3324,7 +3324,7 @@
}
if (currentVersion == 141) {
- // Version 141: We added the notion of a default and whether the system set
+ // Version 142: We added the notion of a default and whether the system set
// the setting. This is used for resetting the internal state and we need
// to make sure this value is updated for the existing settings, otherwise
// we would delete system set settings while they should stay unmodified.
@@ -3344,7 +3344,7 @@
}
if (currentVersion == 142) {
- // Version 142: Set a default value for Wi-Fi wakeup feature.
+ // Version 143: Set a default value for Wi-Fi wakeup feature.
if (userId == UserHandle.USER_SYSTEM) {
final SettingsState globalSettings = getGlobalSettingsLocked();
Setting currentSetting = globalSettings.getSettingLocked(
@@ -3361,6 +3361,27 @@
currentVersion = 143;
}
+ if (currentVersion == 143) {
+ // Version 144: Set a default value for Autofill service.
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting currentSetting = secureSettings
+ .getSettingLocked(Settings.Secure.AUTOFILL_SERVICE);
+ if (currentSetting.isNull()) {
+ final String defaultValue = getContext().getResources().getString(
+ com.android.internal.R.string.config_defaultAutofillService);
+ if (defaultValue != null) {
+ Slog.d(LOG_TAG, "Setting [" + defaultValue + "] as Autofill Service "
+ + "for user " + userId);
+ secureSettings.insertSettingLocked(Settings.Secure.AUTOFILL_SERVICE,
+ defaultValue, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
+ currentVersion = 144;
+ }
+
+ // vXXX: Add new settings above this point.
+
if (currentVersion != newVersion) {
Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
+ newVersion + " left it at "
@@ -3372,8 +3393,6 @@
}
}
- // vXXX: Add new settings above this point.
-
// Return the current version.
return currentVersion;
}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ad39f54..a8cf3da 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1962,4 +1962,31 @@
<!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
<string name="mobile_data">Mobile data</string>
+ <!-- Label for when wifi is off in QS detail panel [CHAR LIMIT=NONE] -->
+ <string name="wifi_is_off">Wi-Fi is off</string>
+
+ <!-- Label for when bluetooth is off in QS detail panel [CHAR LIMIT=NONE] -->
+ <string name="bt_is_off">Bluetooth is off</string>
+
+ <!-- Label for when Do not disturb is off in QS detail panel [CHAR LIMIT=NONE] -->
+ <string name="dnd_is_off">Do Not Disturb is off</string>
+
+ <!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] -->
+ <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>). Keep current settings?</string>
+
+ <!-- Prompt for when Do not disturb is on from app in QS [CHAR LIMIT=NONE] -->
+ <string name="qs_dnd_prompt_app">Do Not Disturb was turned on by an app (<xliff:g name="app">%s</xliff:g>). Keep current settings?</string>
+
+ <!-- Prompt for when Do not disturb is on from automatic rule or app in QS [CHAR LIMIT=NONE] -->
+ <string name="qs_dnd_prompt_auto_rule_app">Do Not Disturb was turned on by an automatic rule or app. Keep current settings?</string>
+
+ <!-- Description of Do Not Disturb option in QS that ends at the specified time[CHAR LIMIT=20] -->
+ <string name="qs_dnd_until">Until <xliff:g name="time">%s</xliff:g></string>
+
+ <!-- Do Not Disturb button to keep the current settings [CHAR LIMIT=20] -->
+ <string name="qs_dnd_keep">Keep</string>
+
+ <!-- Do Not Disturb button to change the current settings [CHAR LIMIT=20] -->
+ <string name="qs_dnd_replace">Replace</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 2655837..80b4da8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -34,9 +34,11 @@
import android.widget.TextClock;
import android.widget.TextView;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ChargingView;
+import java.util.Arrays;
import java.util.Locale;
public class KeyguardStatusView extends GridLayout {
@@ -53,6 +55,10 @@
private ViewGroup mClockContainer;
private ChargingView mBatteryDoze;
+ private View[] mVisibleInDoze;
+ private boolean mPulsing;
+ private boolean mDark;
+
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -117,6 +123,7 @@
mClockView.setShowCurrentUserTime(true);
mOwnerInfo = (TextView) findViewById(R.id.owner_info);
mBatteryDoze = (ChargingView) findViewById(R.id.battery_doze);
+ mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
setEnableMarquee(shouldMarquee);
@@ -273,14 +280,28 @@
}
public void setDark(boolean dark) {
+ mDark = dark;
+
final int N = mClockContainer.getChildCount();
for (int i = 0; i < N; i++) {
View child = mClockContainer.getChildAt(i);
- if (child == mClockView || child == mBatteryDoze) {
+ if (ArrayUtils.contains(mVisibleInDoze, child)) {
continue;
}
child.setAlpha(dark ? 0 : 1);
}
+ updateDozeVisibleViews();
mBatteryDoze.setDark(dark);
}
+
+ public void setPulsing(boolean pulsing) {
+ mPulsing = pulsing;
+ updateDozeVisibleViews();
+ }
+
+ private void updateDozeVisibleViews() {
+ for (View child : mVisibleInDoze) {
+ child.setAlpha(mDark && mPulsing ? 0.5f : 1);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index bcf1957..fbd9f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -86,6 +86,7 @@
private static final float DISABLED_ACTION_ALPHA = 0.54f;
private boolean mMenuVisible;
+ private boolean mAllowMenuTimeout = true;
private final List<RemoteAction> mActions = new ArrayList<>();
private View mViewRoot;
private Drawable mBackgroundDrawable;
@@ -190,7 +191,9 @@
@Override
public void onUserInteraction() {
- repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+ if (mAllowMenuTimeout) {
+ repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+ }
}
@Override
@@ -255,6 +258,7 @@
}
private void showMenu(Rect stackBounds, Rect movementBounds, boolean allowMenuTimeout) {
+ mAllowMenuTimeout = allowMenuTimeout;
if (!mMenuVisible) {
updateActionViews(stackBounds);
if (mMenuContainerAnimator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 9efe224..d2a2919 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -242,7 +242,7 @@
mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
mDetailSettingsButton.setOnClickListener(v -> {
Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
- mDetailAdapter.getMetricsCategory());
+ adapter.getMetricsCategory());
Dependency.get(ActivityStarter.class)
.postStartActivityDismissingKeyguard(settingsIntent, 0);
});
diff --git a/packages/SystemUI/src/com/android/systemui/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/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 21a0dc9..8298f35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -228,6 +228,7 @@
// Settings button.
final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
if (mAppUid >= 0 && onSettingsClick != null) {
+ settingsButton.setVisibility(View.VISIBLE);
final int appUidF = mAppUid;
settingsButton.setOnClickListener(
(View view) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 5055dda..bb82b60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -120,6 +120,9 @@
@Override
public void createMenu(ViewGroup parent) {
mParent = (ExpandableNotificationRow) parent;
+ if (mMenuContainer != null) {
+ mMenuContainer.removeAllViews();
+ }
mMenuContainer = new FrameLayout(mContext);
for (int i = 0; i < mMenuItems.size(); i++) {
addMenuView(mMenuItems.get(i), mMenuContainer);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8da17fa..8042321 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -23,7 +23,6 @@
import android.view.View;
import android.view.ViewGroup;
-import com.android.internal.widget.CachingIconView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
@@ -127,12 +126,8 @@
super.setDark(dark, fade, delay);
if (mDark == dark) return;
mDark = dark;
- if (fade) {
- mViewInvertHelper.fade(dark, delay);
- } else {
- mViewInvertHelper.update(dark);
- }
- mShelfIcons.setAmbient(dark);
+ mShelfIcons.setDark(dark, fade, delay);
+ updateInteractiveness();
}
@Override
@@ -167,7 +162,7 @@
openedAmount = Math.min(1.0f, openedAmount);
mShelfState.openedAmount = openedAmount;
mShelfState.clipTopAmount = 0;
- mShelfState.alpha = 1.0f;
+ mShelfState.alpha = mAmbientState.isPulsing() ? 0 : 1;
mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
mShelfState.shadowAlpha = 1.0f;
mShelfState.hideSensitive = false;
@@ -576,7 +571,8 @@
}
private void updateInteractiveness() {
- mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf;
+ mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf
+ && !mDark;
setClickable(mInteractive);
setFocusable(mInteractive);
setImportantForAccessibility(mInteractive ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
@@ -602,6 +598,11 @@
}
@Override
+ public boolean hasOverlappingRendering() {
+ return false; // Shelf only uses alpha for transitions where the difference can't be seen.
+ }
+
+ @Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
updateRelativeOffset();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index b9c8a78..92bfae9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -27,6 +27,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -46,6 +47,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
import com.android.systemui.statusbar.notification.NotificationUtils;
import java.text.NumberFormat;
@@ -99,7 +101,6 @@
private int mDensity;
private float mIconScale = 1.0f;
private final Paint mDotPaint = new Paint();
- private boolean mDotVisible;
private float mDotRadius;
private int mStaticDotRadius;
private int mVisibleState = STATE_ICON;
@@ -110,6 +111,8 @@
private OnVisibilityChangedListener mOnVisibilityChangedListener;
private int mDrawableColor;
private int mIconColor;
+ private int mDecorColor;
+ private float mDarkAmount;
private ValueAnimator mColorAnimator;
private int mCurrentSetColor = NO_COLOR;
private int mAnimationStartColor = NO_COLOR;
@@ -119,6 +122,7 @@
animation.getAnimatedFraction());
setColorInternal(newColor);
};
+ private final NotificationIconDozeHelper mDozer;
public StatusBarIconView(Context context, String slot, Notification notification) {
this(context, slot, notification, false);
@@ -127,6 +131,7 @@
public StatusBarIconView(Context context, String slot, Notification notification,
boolean blocked) {
super(context);
+ mDozer = new NotificationIconDozeHelper(context);
mBlocked = blocked;
mSlot = slot;
mNumberPain = new Paint();
@@ -190,6 +195,7 @@
public StatusBarIconView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mDozer = new NotificationIconDozeHelper(context);
mBlocked = false;
mAlwaysScaleIcon = true;
updateIconScale();
@@ -466,7 +472,19 @@
* to the drawable.
*/
public void setDecorColor(int iconTint) {
- mDotPaint.setColor(iconTint);
+ mDecorColor = iconTint;
+ updateDecorColor();
+ }
+
+ private void updateDecorColor() {
+ int color = NotificationUtils.interpolateColors(mDecorColor, Color.WHITE, mDarkAmount);
+ if (mDotPaint.getColor() != color) {
+ mDotPaint.setColor(color);
+
+ if (mDotAppearAmount != 0) {
+ invalidate();
+ }
+ }
}
/**
@@ -477,6 +495,7 @@
mDrawableColor = color;
setColorInternal(color);
mIconColor = color;
+ mDozer.setColor(color);
}
private void setColorInternal(int color) {
@@ -649,6 +668,14 @@
mOnVisibilityChangedListener = listener;
}
+ public void setDark(boolean dark, boolean fade, long delay) {
+ mDozer.setImageDark(this, dark, fade, delay, mIconColor == NO_COLOR);
+ mDozer.setIntensityDark(f -> {
+ mDarkAmount = f;
+ updateDecorColor();
+ }, dark, fade, delay);
+ }
+
public interface OnVisibilityChangedListener {
void onVisibilityChanged(int newVisibility);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 3efa29f..bca4b43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -18,7 +18,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
+import android.content.Context;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
@@ -38,8 +38,8 @@
private boolean mIsLegacy;
private int mLegacyColor;
- protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
- super(view, row);
+ protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+ super(ctx, view, row);
mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
}
@@ -67,13 +67,11 @@
}
protected void fadeGrayscale(final boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateGrayscaleMatrix((float) animation.getAnimatedValue());
- mGreyPaint.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
- mView.setLayerPaint(mGreyPaint);
- }
+ getDozer().startIntensityAnimation(animation -> {
+ getDozer().updateGrayscaleMatrix((float) animation.getAnimatedValue());
+ mGreyPaint.setColorFilter(
+ new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
+ mView.setLayerPaint(mGreyPaint);
}, dark, delay, new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -86,9 +84,9 @@
protected void updateGrayscale(boolean dark) {
if (dark) {
- updateGrayscaleMatrix(1f);
+ getDozer().updateGrayscaleMatrix(1f);
mGreyPaint.setColorFilter(
- new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
mView.setLayerPaint(mGreyPaint);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
new file mode 100644
index 0000000..d592c5f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.widget.ImageView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+
+import java.util.function.Consumer;
+
+public class NotificationDozeHelper {
+ private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
+
+ public void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
+ startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateGrayscaleMatrix((float) animation.getAnimatedValue());
+ target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ }
+ }, dark, delay, new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!dark) {
+ target.setColorFilter(null);
+ }
+ }
+ });
+ }
+
+ public void updateGrayscale(ImageView target, boolean dark) {
+ if (dark) {
+ updateGrayscaleMatrix(1f);
+ target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ } else {
+ target.setColorFilter(null);
+ }
+ }
+
+ public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
+ boolean dark, long delay, Animator.AnimatorListener listener) {
+ float startIntensity = dark ? 0f : 1f;
+ float endIntensity = dark ? 1f : 0f;
+ ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
+ animator.addUpdateListener(updateListener);
+ animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+ animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ animator.setStartDelay(delay);
+ if (listener != null) {
+ animator.addListener(listener);
+ }
+ animator.start();
+ }
+
+ public void setIntensityDark(Consumer<Float> listener, boolean dark,
+ boolean animate, long delay) {
+ if (animate) {
+ startIntensityAnimation(a -> listener.accept((Float) a.getAnimatedValue()), dark, delay,
+ null /* listener */);
+ } else {
+ listener.accept(dark ? 1f : 0f);
+ }
+ }
+
+ public void updateGrayscaleMatrix(float intensity) {
+ mGrayscaleColorMatrix.setSaturation(1 - intensity);
+ }
+
+ public ColorMatrix getGrayscaleColorMatrix() {
+ return mGrayscaleColorMatrix;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 38e4ec1..1ffc944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -16,17 +16,10 @@
package com.android.systemui.statusbar.notification;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.app.Notification;
import android.content.Context;
-import android.graphics.Color;
import android.graphics.ColorFilter;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Drawable;
import android.util.ArraySet;
import android.view.NotificationHeaderView;
import android.view.View;
@@ -37,7 +30,6 @@
import android.widget.TextView;
import com.android.systemui.Interpolators;
-import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
@@ -55,10 +47,6 @@
private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
= new PathInterpolator(0.4f, 0f, 0.7f, 1f);
- private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
- 0, PorterDuff.Mode.SRC_ATOP);
- private final int mIconDarkAlpha;
- private final int mIconDarkColor = 0xffffffff;
protected final ViewInvertHelper mInvertHelper;
protected final ViewTransformationHelper mTransformationHelper;
@@ -74,8 +62,7 @@
private boolean mTransformLowPriorityTitle;
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
- super(view, row);
- mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+ super(ctx, view, row);
mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION);
mTransformationHelper = new ViewTransformationHelper();
@@ -108,6 +95,16 @@
updateInvertHelper();
}
+ @Override
+ protected NotificationDozeHelper createDozer(Context ctx) {
+ return new NotificationIconDozeHelper(ctx);
+ }
+
+ @Override
+ protected NotificationIconDozeHelper getDozer() {
+ return (NotificationIconDozeHelper) super.getDozer();
+ }
+
protected void resolveHeaderViews() {
mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text);
@@ -116,6 +113,7 @@
mColor = resolveColor(mExpandButton);
mNotificationHeader = (NotificationHeaderView) mView.findViewById(
com.android.internal.R.id.notification_header);
+ getDozer().setColor(mColor);
}
private int resolveColor(ImageView icon) {
@@ -223,90 +221,8 @@
// It also may lead to bugs where the icon isn't correctly greyed out.
boolean hadColorFilter = mNotificationHeader.getOriginalIconColor()
!= NotificationHeaderView.NO_COLOR;
- if (fade) {
- if (hadColorFilter) {
- fadeIconColorFilter(mIcon, dark, delay);
- fadeIconAlpha(mIcon, dark, delay);
- } else {
- fadeGrayscale(mIcon, dark, delay);
- }
- } else {
- if (hadColorFilter) {
- updateIconColorFilter(mIcon, dark);
- updateIconAlpha(mIcon, dark);
- } else {
- updateGrayscale(mIcon, dark);
- }
- }
- }
- }
- private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateIconColorFilter(target, (Float) animation.getAnimatedValue());
- }
- }, dark, delay, null /* listener */);
- }
-
- private void fadeIconAlpha(final ImageView target, boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (float) animation.getAnimatedValue();
- target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t));
- }
- }, dark, delay, null /* listener */);
- }
-
- protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateGrayscaleMatrix((float) animation.getAnimatedValue());
- target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
- }
- }, dark, delay, new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!dark) {
- target.setColorFilter(null);
- }
- }
- });
- }
-
- private void updateIconColorFilter(ImageView target, boolean dark) {
- updateIconColorFilter(target, dark ? 1f : 0f);
- }
-
- private void updateIconColorFilter(ImageView target, float intensity) {
- int color = interpolateColor(mColor, mIconDarkColor, intensity);
- mIconColorFilter.setColor(color);
- Drawable iconDrawable = target.getDrawable();
-
- // Also, the notification might have been modified during the animation, so background
- // might be null here.
- if (iconDrawable != null) {
- Drawable d = iconDrawable.mutate();
- // DrawableContainer ignores the color filter if it's already set, so clear it first to
- // get it set and invalidated properly.
- d.setColorFilter(null);
- d.setColorFilter(mIconColorFilter);
- }
- }
-
- private void updateIconAlpha(ImageView target, boolean dark) {
- target.setImageAlpha(dark ? mIconDarkAlpha : 255);
- }
-
- protected void updateGrayscale(ImageView target, boolean dark) {
- if (dark) {
- updateGrayscaleMatrix(1f);
- target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
- } else {
- target.setColorFilter(null);
+ getDozer().setImageDark(mIcon, dark, fade, delay, !hadColorFilter);
}
}
@@ -316,22 +232,6 @@
mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
}
- private static int interpolateColor(int source, int target, float t) {
- int aSource = Color.alpha(source);
- int rSource = Color.red(source);
- int gSource = Color.green(source);
- int bSource = Color.blue(source);
- int aTarget = Color.alpha(target);
- int rTarget = Color.red(target);
- int gTarget = Color.green(target);
- int bTarget = Color.blue(target);
- return Color.argb(
- (int) (aSource * (1f - t) + aTarget * t),
- (int) (rSource * (1f - t) + rTarget * t),
- (int) (gSource * (1f - t) + gTarget * t),
- (int) (bSource * (1f - t) + bTarget * t));
- }
-
@Override
public NotificationHeaderView getNotificationHeader() {
return mNotificationHeader;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java
new file mode 100644
index 0000000..9f79ef2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+public class NotificationIconDozeHelper extends NotificationDozeHelper {
+
+ private final int mImageDarkAlpha;
+ private final int mImageDarkColor = 0xffffffff;
+ private final PorterDuffColorFilter mImageColorFilter = new PorterDuffColorFilter(
+ 0, PorterDuff.Mode.SRC_ATOP);
+
+ private int mColor = Color.BLACK;
+
+ public NotificationIconDozeHelper(Context ctx) {
+ mImageDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+ }
+
+ public void setColor(int color) {
+ mColor = color;
+ }
+
+ public void setImageDark(ImageView target, boolean dark, boolean fade, long delay,
+ boolean useGrayscale) {
+ if (fade) {
+ if (!useGrayscale) {
+ fadeImageColorFilter(target, dark, delay);
+ fadeImageAlpha(target, dark, delay);
+ } else {
+ fadeGrayscale(target, dark, delay);
+ }
+ } else {
+ if (!useGrayscale) {
+ updateImageColorFilter(target, dark);
+ updateImageAlpha(target, dark);
+ } else {
+ updateGrayscale(target, dark);
+ }
+ }
+ }
+
+ private void fadeImageColorFilter(final ImageView target, boolean dark, long delay) {
+ startIntensityAnimation(animation -> {
+ updateImageColorFilter(target, (Float) animation.getAnimatedValue());
+ }, dark, delay, null /* listener */);
+ }
+
+ private void fadeImageAlpha(final ImageView target, boolean dark, long delay) {
+ startIntensityAnimation(animation -> {
+ float t = (float) animation.getAnimatedValue();
+ target.setImageAlpha((int) (255 * (1f - t) + mImageDarkAlpha * t));
+ }, dark, delay, null /* listener */);
+ }
+
+ private void updateImageColorFilter(ImageView target, boolean dark) {
+ updateImageColorFilter(target, dark ? 1f : 0f);
+ }
+
+ private void updateImageColorFilter(ImageView target, float intensity) {
+ int color = NotificationUtils.interpolateColors(mColor, mImageDarkColor, intensity);
+ mImageColorFilter.setColor(color);
+ Drawable imageDrawable = target.getDrawable();
+
+ // Also, the notification might have been modified during the animation, so background
+ // might be null here.
+ if (imageDrawable != null) {
+ Drawable d = imageDrawable.mutate();
+ // DrawableContainer ignores the color filter if it's already set, so clear it first to
+ // get it set and invalidated properly.
+ d.setColorFilter(null);
+ d.setColorFilter(mImageColorFilter);
+ }
+ }
+
+ private void updateImageAlpha(ImageView target, boolean dark) {
+ target.setImageAlpha(dark ? mImageDarkAlpha : 255);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 846d03a..f0b6b2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.service.notification.StatusBarNotification;
@@ -46,7 +45,8 @@
private int mContentHeight;
private int mMinHeightHint;
- protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+ protected NotificationTemplateViewWrapper(Context ctx, View view,
+ ExpandableNotificationRow row) {
super(ctx, view, row);
mTransformationHelper.setCustomTransformation(
new ViewTransformationHelper.CustomTransformation() {
@@ -154,16 +154,20 @@
// This also clears the existing types
super.updateTransformedTypes();
if (mTitle != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, mTitle);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
+ mTitle);
}
if (mText != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT, mText);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+ mText);
}
if (mPicture != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE, mPicture);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
+ mPicture);
}
if (mProgressBar != null) {
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS, mProgressBar);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
+ mProgressBar);
}
}
@@ -173,7 +177,7 @@
return;
}
super.setDark(dark, fade, delay);
- setPictureGrayscale(dark, fade, delay);
+ setPictureDark(dark, fade, delay);
setProgressBarDark(dark, fade, delay);
}
@@ -188,12 +192,9 @@
}
private void fadeProgressDark(final ProgressBar target, final boolean dark, long delay) {
- startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (float) animation.getAnimatedValue();
- updateProgressDark(target, t);
- }
+ getDozer().startIntensityAnimation(animation -> {
+ float t = (float) animation.getAnimatedValue();
+ updateProgressDark(target, t);
}, dark, delay, null /* listener */);
}
@@ -207,13 +208,9 @@
updateProgressDark(target, dark ? 1f : 0f);
}
- protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) {
+ private void setPictureDark(boolean dark, boolean fade, long delay) {
if (mPicture != null) {
- if (fade) {
- fadeGrayscale(mPicture, grayscale, delay);
- } else {
- updateGrayscale(mPicture, grayscale);
- }
+ getDozer().setImageDark(mPicture, dark, fade, delay, true /* useGrayscale */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index c85e8d8..f4db9a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -16,24 +16,17 @@
package com.android.systemui.statusbar.notification;
-import android.animation.Animator;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.ColorMatrix;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
import android.support.v4.graphics.ColorUtils;
import android.view.NotificationHeaderView;
import android.view.View;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
/**
* Wraps the actual notification content view; used to implement behaviors which are different for
@@ -41,14 +34,14 @@
*/
public abstract class NotificationViewWrapper implements TransformableView {
- protected final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
protected final View mView;
protected final ExpandableNotificationRow mRow;
+ private final NotificationDozeHelper mDozer;
+
protected boolean mDark;
private int mBackgroundColor = 0;
protected boolean mShouldInvertDark;
protected boolean mDarkInitialized = false;
- private boolean mForcedInvisible;
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -65,13 +58,22 @@
} else if (v instanceof NotificationHeaderView) {
return new NotificationHeaderViewWrapper(ctx, v, row);
} else {
- return new NotificationCustomViewWrapper(v, row);
+ return new NotificationCustomViewWrapper(ctx, v, row);
}
}
- protected NotificationViewWrapper(View view, ExpandableNotificationRow row) {
+ protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
mView = view;
mRow = row;
+ mDozer = createDozer(ctx);
+ }
+
+ protected NotificationDozeHelper createDozer(Context ctx) {
+ return new NotificationDozeHelper();
+ }
+
+ protected NotificationDozeHelper getDozer() {
+ return mDozer;
}
/**
@@ -112,26 +114,6 @@
|| ColorUtils.calculateLuminance(backgroundColor) > 0.5;
}
-
- protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
- boolean dark, long delay, Animator.AnimatorListener listener) {
- float startIntensity = dark ? 0f : 1f;
- float endIntensity = dark ? 1f : 0f;
- ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
- animator.addUpdateListener(updateListener);
- animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
- animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- animator.setStartDelay(delay);
- if (listener != null) {
- animator.addListener(listener);
- }
- animator.start();
- }
-
- protected void updateGrayscaleMatrix(float intensity) {
- mGrayscaleColorMatrix.setSaturation(1 - intensity);
- }
-
/**
* Update the appearance of the expand button.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 3706dc8..dee15d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -95,7 +95,7 @@
private int mActualLayoutWidth = NO_VALUE;
private float mActualPaddingEnd = NO_VALUE;
private float mActualPaddingStart = NO_VALUE;
- private boolean mCentered;
+ private boolean mDark;
private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1;
private int mCannedAnimationStartIndex = -1;
@@ -183,6 +183,9 @@
mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
}
}
+ if (mDark && child instanceof StatusBarIconView) {
+ ((StatusBarIconView) child).setDark(mDark, false, 0);
+ }
}
@Override
@@ -312,7 +315,8 @@
numDots++;
}
}
- if (mCentered && translationX < getLayoutEnd()) {
+ boolean center = mDark;
+ if (center && translationX < getLayoutEnd()) {
float delta = (getLayoutEnd() - translationX) / 2;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
@@ -390,9 +394,15 @@
mChangingViewPositions = changingViewPositions;
}
- public void setAmbient(boolean ambient) {
- mCentered = ambient;
+ public void setDark(boolean dark, boolean fade, long delay) {
+ mDark = dark;
mDisallowNextAnimation = true;
+ for (int i = 0; i < getChildCount(); i++) {
+ View view = getChildAt(i);
+ if (view instanceof StatusBarIconView) {
+ ((StatusBarIconView) view).setDark(dark, fade, delay);
+ }
+ }
}
public IconState getIconState(StatusBarIconView icon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c24a2a0..307a8c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2472,4 +2472,8 @@
public void setNoVisibleNotifications(boolean noNotifications) {
mNoVisibleNotifications = noNotifications;
}
+
+ public void setPulsing(boolean pulsing) {
+ mKeyguardStatusView.setPulsing(pulsing);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9a71ed7..472af65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -89,7 +89,6 @@
import android.provider.Settings;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
-import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -242,7 +241,6 @@
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -5012,19 +5010,25 @@
@Override
public void onPulseStarted() {
callback.onPulseStarted();
- if (!mHeadsUpManager.getAllEntries().isEmpty()) {
+ Collection<HeadsUpManager.HeadsUpEntry> pulsingEntries =
+ mHeadsUpManager.getAllEntries();
+ if (!pulsingEntries.isEmpty()) {
// Only pulse the stack scroller if there's actually something to show.
// Otherwise just show the always-on screen.
- mStackScroller.setPulsing(true);
- mVisualStabilityManager.setPulsing(true);
+ setPulsing(pulsingEntries);
}
}
@Override
public void onPulseFinished() {
callback.onPulseFinished();
- mStackScroller.setPulsing(false);
- mVisualStabilityManager.setPulsing(false);
+ setPulsing(null);
+ }
+
+ private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ mStackScroller.setPulsing(pulsing);
+ mNotificationPanel.setPulsing(pulsing != null);
+ mVisualStabilityManager.setPulsing(pulsing != null);
}
}, reason);
}
@@ -5767,12 +5771,16 @@
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
final String pkg = sbn.getPackageName();
NotificationInfo info = (NotificationInfo) gutsView;
- final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
- NotificationChannel channel, int appUid) -> {
- mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
- guts.resetFalsingCheck();
- startAppNotificationSettingsActivity(pkg, appUid, channel);
- };
+ // Settings link is only valid for notifications that specify a user, unless this is the
+ // system user.
+ NotificationInfo.OnSettingsClickListener onSettingsClick = null;
+ if (!userHandle.equals(UserHandle.ALL) || mCurrentUserId == UserHandle.USER_SYSTEM) {
+ onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
+ mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
+ guts.resetFalsingCheck();
+ startAppNotificationSettingsActivity(pkg, appUid, channel);
+ };
+ }
final View.OnClickListener onDoneClick = (View v) -> {
saveAndCloseNotificationMenu(info, row, guts, v);
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index fe83dc4..b2b23a55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -59,6 +59,7 @@
private boolean mPanelTracking;
private boolean mExpansionChanging;
private boolean mPanelFullWidth;
+ private boolean mPulsing;
public AmbientState(Context context) {
reload(context);
@@ -285,6 +286,14 @@
mPanelTracking = panelTracking;
}
+ public boolean isPulsing() {
+ return mPulsing;
+ }
+
+ public void setPulsing(boolean pulsing) {
+ mPulsing = pulsing;
+ }
+
public boolean isPanelTracking() {
return mPanelTracking;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7d2d0df..15fcb38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -72,6 +72,7 @@
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationGuts;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StackScrollerDecorView;
@@ -86,6 +87,7 @@
import com.android.systemui.statusbar.policy.ScrollAdapter;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
@@ -331,7 +333,7 @@
}
};
private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
- private boolean mPulsing;
+ private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
private boolean mDrawBackgroundAsSrc;
private boolean mFadingOut;
private boolean mParentNotFullyVisible;
@@ -1917,15 +1919,19 @@
int numShownItems = 0;
boolean finish = false;
int maxDisplayedNotifications = mAmbientState.isDark()
- ? (mPulsing ? 1 : 0)
+ ? (isPulsing() ? 1 : 0)
: mMaxDisplayedNotifications;
for (int i = 0; i < getChildCount(); i++) {
ExpandableView expandableView = (ExpandableView) getChildAt(i);
if (expandableView.getVisibility() != View.GONE
&& !expandableView.hasNoContentHeight()) {
- if (maxDisplayedNotifications != -1
- && numShownItems >= maxDisplayedNotifications) {
+ boolean limitReached = maxDisplayedNotifications != -1
+ && numShownItems >= maxDisplayedNotifications;
+ boolean notificationOnAmbientThatIsNotPulsing = isPulsing()
+ && expandableView instanceof ExpandableNotificationRow
+ && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
+ if (limitReached || notificationOnAmbientThatIsNotPulsing) {
expandableView = mShelf;
finish = true;
}
@@ -1971,6 +1977,19 @@
mAmbientState.setLayoutMaxHeight(mContentHeight);
}
+ private boolean isPulsing(NotificationData.Entry entry) {
+ for (HeadsUpManager.HeadsUpEntry e : mPulsing) {
+ if (e.entry == entry) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isPulsing() {
+ return mPulsing != null;
+ }
+
private void updateScrollability() {
boolean scrollable = getScrollRange() > 0;
if (scrollable != mScrollable) {
@@ -2784,7 +2803,7 @@
}
private void updateNotificationAnimationStates() {
- boolean running = mAnimationsEnabled || mPulsing;
+ boolean running = mAnimationsEnabled || isPulsing();
mShelf.setAnimationsEnabled(running);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -2795,7 +2814,7 @@
}
private void updateAnimationState(View child) {
- updateAnimationState((mAnimationsEnabled || mPulsing)
+ updateAnimationState((mAnimationsEnabled || isPulsing())
&& (mIsExpanded || isPinnedHeadsUp(child)), child);
}
@@ -4055,14 +4074,16 @@
return mIsExpanded;
}
- public void setPulsing(boolean pulsing) {
- if (mPulsing == pulsing) {
+ public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ if (mPulsing == null && pulsing == null) {
return;
}
mPulsing = pulsing;
+ mAmbientState.setPulsing(isPulsing());
updateNotificationAnimationStates();
updateContentHeight();
notifyHeightChangeListener(mShelf);
+ requestChildrenUpdate();
}
public void setFadingOut(boolean fadingOut) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index c67cccc..8609eeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -100,4 +100,10 @@
ViewUtils.detachView(mQsDetail);
mTestableLooper.processAllMessages();
}
+
+ @Test
+ public void testNullAdapterClick() {
+ mQsDetail.setupDetailFooter(mock(DetailAdapter.class));
+ mQsDetail.findViewById(android.R.id.button2).performClick();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 21930a3..0621f4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -206,6 +206,29 @@
}
@Test
+ public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ null, null, null, null);
+ final TextView settingsButton =
+ (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ assertTrue(settingsButton.getVisibility() != View.VISIBLE);
+ }
+
+ @Test
+ public void testBindNotification_SettingsButtonReappersAfterSecondBind() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ null, null, null, null);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ (View v, NotificationChannel c, int appUid) -> {}, null, null, null);
+ final TextView settingsButton =
+ (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ assertEquals(View.VISIBLE, settingsButton.getVisibility());
+ }
+
+ @Test
public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 31b9bae..efb9fea4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -44,4 +44,11 @@
ViewUtils.detachView(row.getMenuView());
TestableLooper.get(this).processAllMessages();
}
+
+ @Test
+ public void testRecreateMenu() {
+ NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+ row.createMenu(null);
+ row.createMenu(null);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
new file mode 100644
index 0000000..a69de7a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class NotificationViewWrapperTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ @Test
+ public void constructor_doesntUseViewContext() throws Exception {
+ new TestableNotificationViewWrapper(mContext, new View(null /* context */), null /* row */);
+ }
+
+ static class TestableNotificationViewWrapper extends NotificationViewWrapper {
+ protected TestableNotificationViewWrapper(Context ctx, View view,
+ ExpandableNotificationRow row) {
+ super(ctx, view, row);
+ }
+ }
+}
\ No newline at end of file
diff --git a/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/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 0482e73..ac81565 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1631,7 +1631,7 @@
@Override
public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
- int profileId) {
+ int profileId, String packageName) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -1653,8 +1653,11 @@
Provider provider = mProviders.get(i);
AppWidgetProviderInfo info = provider.info;
- // Ignore an invalid provider or one not matching the filter.
- if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
+ // Ignore an invalid provider, one not matching the filter,
+ // or one that isn't in the given package, if any.
+ boolean inPackage = packageName == null
+ || provider.id.componentName.getPackageName().equals(packageName);
+ if (provider.zombie || (info.widgetCategory & categoryFilter) == 0 || !inPackage) {
continue;
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index be14440..502b5fc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -23,7 +23,6 @@
import static com.android.server.autofill.Helper.VERBOSE;
import static com.android.server.autofill.Helper.bundleToString;
-import android.Manifest;
import android.annotation.NonNull;
import android.app.ActivityManagerInternal;
import android.content.BroadcastReceiver;
@@ -36,7 +35,6 @@
import android.database.ContentObserver;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3d1c251..15ec98f 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -57,6 +57,7 @@
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.IResultReceiver;
@@ -290,7 +291,8 @@
+ " f=" + flags;
mRequestsHistory.log(historyItem);
- // TODO(b/33197203): Handle partitioning
+ // TODO(b/33197203): Handle scenario when user forced autofill after app was already
+ // autofilled.
final Session session = mSessions.get(activityToken);
if (session != null) {
// Already started...
@@ -430,8 +432,11 @@
void dumpLocked(String prefix, PrintWriter pw) {
final String prefix2 = prefix + " ";
+ pw.print(prefix); pw.print("User :"); pw.println(mUserId);
pw.print(prefix); pw.print("Component:"); pw.println(mInfo != null
? mInfo.getServiceInfo().getComponentName() : null);
+ pw.print(prefix); pw.print("Default component: ");
+ pw.println(mContext.getString(R.string.config_defaultAutofillService));
pw.print(prefix); pw.print("Disabled:"); pw.println(mDisabled);
if (VERBOSE && mInfo != null) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index ac7d19e..801769c 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -48,6 +48,7 @@
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.util.ArrayMap;
+import android.util.DebugUtils;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
@@ -112,20 +113,19 @@
@GuardedBy("mLock")
RemoteFillService mRemoteFillService;
- // TODO(b/33197203 , b/35707731): Use List once it supports partitioning
@GuardedBy("mLock")
- private FillResponse mCurrentResponse;
+ private ArrayList<FillResponse> mResponses;
/**
- * Used to remember which {@link Dataset} filled the session.
+ * Response that requires a service authentitcation request.
*/
- // TODO(b/33197203 , b/35707731): will be removed once it supports partitioning
@GuardedBy("mLock")
- private Dataset mAutoFilledDataset;
+ private FillResponse mResponseWaitingAuth;
/**
* Dataset that when tapped launched a service authentication request.
*/
+ @GuardedBy("mLock")
private Dataset mDatasetWaitingAuth;
/**
@@ -163,8 +163,8 @@
mClient = IAutoFillManagerClient.Stub.asInterface(client);
try {
client.linkToDeath(() -> {
- if (DEBUG) {
- Slog.d(TAG, "app binder died");
+ if (VERBOSE) {
+ Slog.v(TAG, "app binder died");
}
removeSelf();
@@ -193,6 +193,10 @@
notifyUnavailableToClient();
}
synchronized (mLock) {
+ if (response.getAuthentication() != null) {
+ // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
+ mResponseWaitingAuth = response;
+ }
processResponseLocked(response);
}
@@ -318,23 +322,27 @@
}
public void setAuthenticationResultLocked(Bundle data) {
- if (mCurrentResponse == null || data == null) {
+ if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) {
removeSelf();
} else {
final Parcelable result = data.getParcelable(
AutofillManager.EXTRA_AUTHENTICATION_RESULT);
if (result instanceof FillResponse) {
mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
-
- mCurrentResponse = (FillResponse) result;
- processResponseLocked(mCurrentResponse);
+ mResponseWaitingAuth = null;
+ processResponseLocked((FillResponse) result);
} else if (result instanceof Dataset) {
final Dataset dataset = (Dataset) result;
- final int index = mCurrentResponse.getDatasets().indexOf(mDatasetWaitingAuth);
- if (index >= 0) {
- mCurrentResponse.getDatasets().set(index, dataset);
- autoFill(dataset);
- mDatasetWaitingAuth = null;
+ for (int i = 0; i < mResponses.size(); i++) {
+ final FillResponse response = mResponses.get(i);
+ final int index = response.getDatasets().indexOf(mDatasetWaitingAuth);
+ if (index >= 0) {
+ response.getDatasets().set(index, dataset);
+ mDatasetWaitingAuth = null;
+ autoFill(dataset);
+ resetViewStatesLocked(dataset, ViewState.STATE_WAITING_DATASET_AUTH);
+ return;
+ }
}
}
}
@@ -354,15 +362,19 @@
Slog.wtf(TAG, "showSaveLocked(): no mStructure");
return true;
}
- if (mCurrentResponse == null) {
+ if (mResponses == null) {
// Happens when the activity / session was finished before the service replied, or
// when the service cannot autofill it (and returned a null response).
if (DEBUG) {
- Slog.d(TAG, "showSaveLocked(): no mCurrentResponse");
+ Slog.d(TAG, "showSaveLocked(): no responses on session");
}
return true;
}
- final SaveInfo saveInfo = mCurrentResponse.getSaveInfo();
+
+ // TODO(b/33197203 , b/35707731): must iterate over all responses
+ final FillResponse response = mResponses.get(0);
+
+ final SaveInfo saveInfo = response.getSaveInfo();
if (DEBUG) {
Slog.d(TAG, "showSaveLocked(): saveInfo=" + saveInfo);
}
@@ -385,7 +397,6 @@
return true;
}
- // TODO(b/33197203 , b/35707731): refactor excessive calls to getCurrentValue()
boolean allRequiredAreNotEmpty = true;
boolean atLeastOneChanged = false;
for (int i = 0; i < requiredIds.length; i++) {
@@ -393,7 +404,8 @@
final ViewState viewState = mViewStates.get(id);
if (viewState == null) {
Slog.w(TAG, "showSaveLocked(): no ViewState for required " + id);
- continue;
+ allRequiredAreNotEmpty = false;
+ break;
}
final AutofillValue currentValue = viewState.getCurrentValue();
@@ -462,7 +474,8 @@
Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
}
- final Bundle extras = this.mCurrentResponse.getExtras();
+ // TODO(b/33197203 , b/35707731): decide how to handle bundle in multiple partitions
+ final Bundle extras = mResponses != null ? mResponses.get(0).getExtras() : null;
for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) {
final AutofillValue value = entry.getValue().getCurrentValue();
@@ -497,16 +510,21 @@
}
void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
- if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) {
- // TODO(b/33197203): ignoring because we don't support partitions yet
- Slog.d(TAG, "updateLocked(): ignoring " + id + " after app was autofilled");
- return;
- }
-
ViewState viewState = mViewStates.get(id);
+
if (viewState == null) {
- viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL);
- mViewStates.put(id, viewState);
+ if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED)) != 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags));
+ }
+ viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL);
+ mViewStates.put(id, viewState);
+ } else if ((flags & FLAG_VIEW_ENTERED) != 0) {
+ viewState = startPartitionLocked(id);
+ } else {
+ if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id);
+ return;
+ }
}
if ((flags & FLAG_START_SESSION) != 0) {
@@ -530,7 +548,8 @@
}
// Update the internal state...
viewState.setState(ViewState.STATE_CHANGED);
- // ... and the chooser UI.
+
+ //..and the UI
if (value.isText()) {
getUiForShowing().filterFillUi(value.getTextValue().toString());
} else {
@@ -551,10 +570,6 @@
// If the ViewState is ready to be displayed, onReady() will be called.
viewState.update(value, virtualBounds);
- if (mCurrentResponse != null) {
- viewState.setResponse(mCurrentResponse);
- }
-
return;
}
@@ -566,7 +581,28 @@
return;
}
- Slog.w(TAG, "updateLocked(): unknown flags " + flags);
+ Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags));
+ }
+
+ private ViewState startPartitionLocked(AutofillId id) {
+ if (DEBUG) {
+ Slog.d(TAG, "Starting partition for view id " + id);
+ }
+ final ViewState viewState =
+ new ViewState(this, id, this,ViewState.STATE_STARTED_PARTITION);
+ mViewStates.put(id, viewState);
+
+ /*
+ * TODO(b/33197203 , b/35707731): when start a new partition, it should
+ *
+ * - add autofilled fields as sanitized
+ * - set focus on ViewStructure that triggered it
+ * - pass the first onFillRequest() bundle
+ * - optional: perhaps add a new flag onFilLRequest() to indicate it's a new partition?
+ */
+ mRemoteFillService.onFillRequest(mStructure, null, 0);
+
+ return viewState;
}
@Override
@@ -580,6 +616,10 @@
getUiForShowing().showFillUi(filledId, response, filterText, mPackageName);
}
+ String getFlagAsString(int flag) {
+ return DebugUtils.flagsToString(AutofillManager.class, "FLAG_", flag);
+ }
+
private void notifyUnavailableToClient() {
if (mCurrentViewId == null) {
// TODO(b/33197203): temporary sanity check; should never happen
@@ -597,8 +637,7 @@
private void processResponseLocked(FillResponse response) {
if (DEBUG) {
- Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
- + "):" + response);
+ Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response);
}
if (mCurrentViewId == null) {
@@ -607,7 +646,10 @@
return;
}
- mCurrentResponse = response;
+ if (mResponses == null) {
+ mResponses = new ArrayList<>(4);
+ }
+ mResponses.add(response);
setViewStatesLocked(response, ViewState.STATE_FILLABLE);
@@ -669,10 +711,22 @@
}
}
+ /**
+ * Resets the given state from all existing views in the given dataset.
+ */
+ private void resetViewStatesLocked(@NonNull Dataset dataset, int state) {
+ final ArrayList<AutofillId> ids = dataset.getFieldIds();
+ for (int j = 0; j < ids.size(); j++) {
+ final AutofillId id = ids.get(j);
+ final ViewState viewState = mViewStates.get(id);
+ if (viewState != null) {
+ viewState.resetState(state);
+ }
+ }
+ }
+
void autoFill(Dataset dataset) {
synchronized (mLock) {
- mAutoFilledDataset = dataset;
-
// Autofill it directly...
if (dataset.getAuthentication() == null) {
autoFillApp(dataset);
@@ -680,7 +734,9 @@
}
// ...or handle authentication.
+ // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
mDatasetWaitingAuth = dataset;
+ setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH);
final Intent fillInIntent = createAuthFillInIntent(mStructure, null);
startAuthentication(dataset.getAuthentication(), fillInIntent);
}
@@ -690,8 +746,8 @@
return mService.getServiceName();
}
- FillResponse getCurrentResponse() {
- return mCurrentResponse;
+ FillResponse getResponseWaitingAuth() {
+ return mResponseWaitingAuth;
}
private Intent createAuthFillInIntent(AssistStructure structure, Bundle extras) {
@@ -714,8 +770,8 @@
void dumpLocked(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("mFlags: "); pw.println(mFlags);
- pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse);
- pw.print(prefix); pw.print("mAutoFilledDataset: "); pw.println(mAutoFilledDataset);
+ pw.print(prefix); pw.print("mResponses: "); pw.println(mResponses);
+ pw.print(prefix); pw.print("mResponseWaitingAuth: "); pw.println(mResponseWaitingAuth);
pw.print(prefix); pw.print("mDatasetWaitingAuth: "); pw.println(mDatasetWaitingAuth);
pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId);
pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size());
@@ -811,4 +867,4 @@
destroyLocked();
mService.removeSessionLocked(mActivityToken);
}
-}
\ No newline at end of file
+}
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 3aba723..549f231 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -16,10 +16,13 @@
package com.android.server.autofill;
+import static com.android.server.autofill.Helper.DEBUG;
+
import android.annotation.Nullable;
import android.graphics.Rect;
import android.service.autofill.FillResponse;
import android.util.DebugUtils;
+import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -40,6 +43,8 @@
@Nullable AutofillValue value);
}
+ private static final String TAG = "ViewState";
+
// NOTE: state constants must be public because of flagstoString().
public static final int STATE_UNKNOWN = 0x00;
/** Initial state. */
@@ -52,6 +57,10 @@
public static final int STATE_CHANGED = 0x08;
/** Set only in the View that started a session. */
public static final int STATE_STARTED_SESSION = 0x10;
+ /** View that started a new partition when focused on. */
+ public static final int STATE_STARTED_PARTITION = 0x20;
+ /** User select a dataset in this view, but service must authenticate first. */
+ public static final int STATE_WAITING_DATASET_AUTH = 0x40;
public final AutofillId id;
private final Listener mListener;
@@ -122,9 +131,15 @@
}
void setState(int state) {
- // TODO(b/33197203 , b/35707731): currently it's always setting one state, but once it
- // supports partitioning it will need to 'or' some of them..
- mState = state;
+ if (mState == STATE_INITIAL) {
+ mState = state;
+ } else {
+ mState |= state;
+ }
+ }
+
+ void resetState(int state) {
+ mState &= ~state;
}
// TODO(b/33197203): need to refactor / rename / document this method to make it clear that
@@ -147,6 +162,12 @@
* fill UI is ready to be displayed (i.e. when response and bounds are set).
*/
void maybeCallOnFillReady() {
+ if ((mState & (STATE_AUTOFILLED | STATE_WAITING_DATASET_AUTH)) != 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
+ }
+ return;
+ }
// First try the current response associated with this View.
if (mResponse != null) {
if (mResponse.getDatasets() != null) {
@@ -155,9 +176,9 @@
return;
}
// Then checks if the session has a response waiting authentication; if so, uses it instead.
- final FillResponse currentResponse = mSession.getCurrentResponse();
- if (currentResponse.getAuthentication() != null) {
- mListener.onFillReady(currentResponse, this.id, mCurrentValue);
+ final FillResponse responseWaitingAuth = mSession.getResponseWaitingAuth();
+ if (responseWaitingAuth != null) {
+ mListener.onFillReady(responseWaitingAuth, this.id, mCurrentValue);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d38fb96..b69d1dc 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -101,8 +101,9 @@
content.measure(widthMeasureSpec, heightMeasureSpec);
content.setOnClickListener(v -> mCallback.onResponsePicked(response));
content.setElevation(context.getResources().getDimension(R.dimen.floating_window_z));
- mContentWidth = content.getMeasuredWidth();
- mContentHeight = content.getMeasuredHeight();
+ // TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width
+ mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
+ mContentHeight = Math.min(content.getMeasuredHeight(), 500);
mWindow = new AnchoredWindow(content);
mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
diff --git a/services/core/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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0e752ff..25ac008 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -29,13 +29,6 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_NONE;
-import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
-import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.uidRulesToString;
import android.annotation.Nullable;
import android.app.BroadcastOptions;
@@ -104,7 +97,6 @@
import android.security.KeyStore;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.LocalLog;
import android.util.LocalLog.ReadOnlyLocalLog;
import android.util.Log;
@@ -130,6 +122,7 @@
import com.android.internal.util.MessageUtils;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.XmlUtils;
+import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.KeepaliveTracker;
@@ -147,6 +140,7 @@
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.LockdownVpnTracker;
+import com.android.server.net.NetworkPolicyManagerInternal;
import com.google.android.collect.Lists;
@@ -221,18 +215,6 @@
private boolean mLockdownEnabled;
private LockdownVpnTracker mLockdownTracker;
- /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
- private Object mRulesLock = new Object();
- /** Currently active network rules by UID. */
- @GuardedBy("mRulesLock")
- private SparseIntArray mUidRules = new SparseIntArray();
- /** Set of ifaces that are costly. */
- @GuardedBy("mRulesLock")
- private ArraySet<String> mMeteredIfaces = new ArraySet<>();
- /** Flag indicating if background data is restricted. */
- @GuardedBy("mRulesLock")
- private boolean mRestrictBackground;
-
final private Context mContext;
private int mNetworkPreference;
// 0 is full bad, 100 is full good
@@ -246,6 +228,7 @@
private INetworkManagementService mNetd;
private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager;
+ private NetworkPolicyManagerInternal mPolicyManagerInternal;
private String mCurrentTcpBufferSizes;
@@ -715,12 +698,15 @@
mNetd = checkNotNull(netManager, "missing INetworkManagementService");
mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
+ mPolicyManagerInternal = checkNotNull(
+ LocalServices.getService(NetworkPolicyManagerInternal.class),
+ "missing NetworkPolicyManagerInternal");
+
mKeyStore = KeyStore.getInstance();
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
try {
- mPolicyManager.setConnectivityListener(mPolicyListener);
- mRestrictBackground = mPolicyManager.getRestrictBackground();
+ mPolicyManager.registerListener(mPolicyListener);
} catch (RemoteException e) {
// ouch, no rules updates means some processes may never get network
loge("unable to register INetworkPolicyListener" + e);
@@ -991,51 +977,22 @@
private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
boolean ignoreBlocked) {
// Networks aren't blocked when ignoring blocked status
- if (ignoreBlocked) return false;
+ if (ignoreBlocked) {
+ return false;
+ }
// Networks are never blocked for system services
- if (isSystem(uid)) return false;
-
- final boolean networkMetered;
- final int uidRules;
-
+ // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
+ if (isSystem(uid)) {
+ return false;
+ }
synchronized (mVpns) {
final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
if (vpn != null && vpn.isBlockingUid(uid)) {
return true;
}
}
-
final String iface = (lp == null ? "" : lp.getInterfaceName());
- synchronized (mRulesLock) {
- networkMetered = mMeteredIfaces.contains(iface);
- uidRules = mUidRules.get(uid, RULE_NONE);
- }
-
- boolean allowed = true;
- // Check Data Saver Mode first...
- if (networkMetered) {
- if ((uidRules & RULE_REJECT_METERED) != 0) {
- if (LOGD_RULES) Log.d(TAG, "uid " + uid + " is blacklisted");
- // Explicitly blacklisted.
- allowed = false;
- } else {
- allowed = !mRestrictBackground
- || (uidRules & RULE_ALLOW_METERED) != 0
- || (uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0;
- if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
- + " mRestrictBackground=" + mRestrictBackground
- + ", whitelisted=" + ((uidRules & RULE_ALLOW_METERED) != 0)
- + ", tempWhitelist= + ((uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0)"
- + ": " + allowed);
- }
- }
- // ...then power restrictions.
- if (allowed) {
- allowed = (uidRules & RULE_REJECT_ALL) == 0;
- if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
- + " rule is " + uidRulesToString(uidRules) + ": " + allowed);
- }
- return !allowed;
+ return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
}
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
@@ -1481,67 +1438,24 @@
return true;
}
- private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+ private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
@Override
public void onUidRulesChanged(int uid, int uidRules) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
- }
-
- synchronized (mRulesLock) {
- // skip update when we've already applied rules
- final int oldRules = mUidRules.get(uid, RULE_NONE);
- if (oldRules == uidRules) return;
-
- if (uidRules == RULE_NONE) {
- mUidRules.delete(uid);
- } else {
- mUidRules.put(uid, uidRules);
- }
- }
-
// TODO: notify UID when it has requested targeted updates
}
-
@Override
public void onMeteredIfacesChanged(String[] meteredIfaces) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
- }
-
- synchronized (mRulesLock) {
- mMeteredIfaces.clear();
- for (String iface : meteredIfaces) {
- mMeteredIfaces.add(iface);
- }
- }
}
-
@Override
public void onRestrictBackgroundChanged(boolean restrictBackground) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
- }
-
- synchronized (mRulesLock) {
- mRestrictBackground = restrictBackground;
- }
-
+ // TODO: relocate this specific callback in Tethering.
if (restrictBackground) {
log("onRestrictBackgroundChanged(true): disabling tethering");
mTethering.untetherAll();
}
}
-
@Override
public void onUidPoliciesChanged(int uid, int uidPolicies) {
- // caller is NPMS, since we only register with them
- if (LOGD_RULES) {
- log("onUidRulesChanged(uid=" + uid + ", uidPolicies=" + uidPolicies + ")");
- }
}
};
@@ -1976,33 +1890,6 @@
pw.decreaseIndent();
pw.println();
- pw.println("Metered Interfaces:");
- pw.increaseIndent();
- for (String value : mMeteredIfaces) {
- pw.println(value);
- }
- pw.decreaseIndent();
- pw.println();
-
- pw.print("Restrict background: ");
- pw.println(mRestrictBackground);
- pw.println();
-
- pw.println("Status for known UIDs:");
- pw.increaseIndent();
- final int size = mUidRules.size();
- for (int i = 0; i < size; i++) {
- final int uid = mUidRules.keyAt(i);
- pw.print("UID=");
- pw.print(uid);
- final int uidRules = mUidRules.get(uid, RULE_NONE);
- pw.print(" rules=");
- pw.print(uidRulesToString(uidRules));
- pw.println();
- }
- pw.println();
- pw.decreaseIndent();
-
pw.println("Network Requests:");
pw.increaseIndent();
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -3437,6 +3324,10 @@
Slog.e(TAG, s);
}
+ private static void loge(String s, Throwable t) {
+ Slog.e(TAG, s, t);
+ }
+
private static <T> T checkNotNull(T value, String message) {
if (value == null) {
throw new NullPointerException(message);
@@ -4197,20 +4088,16 @@
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
final int uid = Binder.getCallingUid();
if (isSystem(uid)) {
+ // Exemption for system uid.
return;
}
- // if UID is restricted, don't allow them to bring up metered APNs
- if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) == false) {
- final int uidRules;
- synchronized(mRulesLock) {
- uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
- }
- if (mRestrictBackground && (uidRules & RULE_ALLOW_METERED) == 0
- && (uidRules & RULE_TEMPORARY_ALLOW_METERED) == 0) {
- // we could silently fail or we can filter the available nets to only give
- // them those they have access to. Chose the more useful option.
- networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
- }
+ if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+ // Policy already enforced.
+ return;
+ }
+ if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
+ // If UID is restricted, don't allow them to bring up metered APNs.
+ networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
}
}
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/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 421d5a6..c105b12 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.app.ActivityThread;
import android.content.Context;
import android.os.IBinder;
import android.os.ServiceManager;
@@ -104,6 +105,16 @@
}
/**
+ * Get the system UI context. This context is to be used for displaying UI. It is themable,
+ * which means resources can be overridden at runtime. Do not use to retrieve properties that
+ * configure the behavior of the device that is not UX related.
+ */
+ public final Context getUiContext() {
+ // This has already been set up by the time any SystemServices are created.
+ return ActivityThread.currentActivityThread().getSystemUiContext();
+ }
+
+ /**
* Returns true if the system is running in safe mode.
* TODO: we should define in which phase this becomes valid
*/
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..738365d 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} */
@@ -431,14 +427,13 @@
public boolean addAccountExplicitlyWithVisibility(Account account, String password,
Bundle extras, Map packageToVisibility) {
Bundle.setDefusable(extras, true);
-
- final int callingUid = Binder.getCallingUid();
+ int callingUid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
Preconditions.checkNotNull(account, "account cannot be null");
- int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
callingUid, account.type);
@@ -465,9 +460,9 @@
public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
String accountType) {
int callingUid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
boolean isSystemUid = UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
- List<String> managedTypes =
- getTypesForCaller(callingUid, UserHandle.getUserId(callingUid), isSystemUid);
+ List<String> managedTypes = getTypesForCaller(callingUid, userId, isSystemUid);
if ((accountType != null && !managedTypes.contains(accountType))
|| (accountType == null && !isSystemUid)) {
@@ -482,8 +477,9 @@
long identityToken = clearCallingIdentity();
try {
+ UserAccounts accounts = getUserAccounts(userId);
return getAccountsAndVisibilityForPackage(packageName, managedTypes, callingUid,
- getUserAccounts(UserHandle.getUserId(callingUid)));
+ accounts);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -494,12 +490,8 @@
*/
private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
List<String> accountTypes, Integer callingUid, UserAccounts accounts) {
- int uid = 0;
- try {
- uid = mPackageManager.getPackageUidAsUser(packageName,
- UserHandle.getUserId(callingUid));
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Package not found " + e.getMessage());
+ if (!packageExistsForUser(packageName, accounts.userId)) {
+ Log.d(TAG, "Package not found " + packageName);
return new LinkedHashMap<>();
}
@@ -524,19 +516,26 @@
public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
Preconditions.checkNotNull(account, "account cannot be null");
int callingUid = Binder.getCallingUid();
- int userId = UserHandle.getUserId(callingUid);
- UserAccounts accounts = getUserAccounts(userId);
+ int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)
&& !isSystemUid(callingUid)) {
String msg =
String.format("uid %s cannot get secrets for account %s", callingUid, account);
throw new SecurityException(msg);
}
- synchronized (accounts.dbLock) {
- synchronized (accounts.cacheLock) {
- return getPackagesAndVisibilityForAccountLocked(account, accounts);
+
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ synchronized (accounts.dbLock) {
+ synchronized (accounts.cacheLock) {
+ return getPackagesAndVisibilityForAccountLocked(account, accounts);
+ }
}
+ } finally {
+ restoreCallingIdentity(identityToken);
}
+
}
/**
@@ -564,8 +563,8 @@
Preconditions.checkNotNull(account, "account cannot be null");
Preconditions.checkNotNull(packageName, "packageName cannot be null");
int callingUid = Binder.getCallingUid();
- UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
- if (!isAccountManagedByCaller(account.type, callingUid, accounts.userId)
+ int userId = UserHandle.getCallingUserId();
+ if (!isAccountManagedByCaller(account.type, callingUid, userId)
&& !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot get secrets for accounts of type: %s",
@@ -573,7 +572,13 @@
account.type);
throw new SecurityException(msg);
}
- return resolveAccountVisibility(account, packageName, accounts);
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ return resolveAccountVisibility(account, packageName, accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
}
/**
@@ -712,8 +717,8 @@
Preconditions.checkNotNull(account, "account cannot be null");
Preconditions.checkNotNull(packageName, "packageName cannot be null");
int callingUid = Binder.getCallingUid();
- UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
- if (!isAccountManagedByCaller(account.type, callingUid, accounts.userId)
+ int userId = UserHandle.getCallingUserId();
+ if (!isAccountManagedByCaller(account.type, callingUid, userId)
&& !isSystemUid(callingUid)) {
String msg = String.format(
"uid %s cannot get secrets for accounts of type: %s",
@@ -721,8 +726,14 @@
account.type);
throw new SecurityException(msg);
}
- return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
}
/**
@@ -809,8 +820,15 @@
public void registerAccountListener(String[] accountTypes, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
- registerAccountListener(accountTypes, opPackageName,
- getUserAccounts(UserHandle.getUserId(callingUid)));
+
+ int userId = UserHandle.getCallingUserId();
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ registerAccountListener(accountTypes, opPackageName, accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
}
private void registerAccountListener(String[] accountTypes, String opPackageName,
@@ -836,7 +854,18 @@
public void unregisterAccountListener(String[] accountTypes, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
- UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
+ int userId = UserHandle.getCallingUserId();
+ long identityToken = clearCallingIdentity();
+ try {
+ UserAccounts accounts = getUserAccounts(userId);
+ unregisterAccountListener(accountTypes, opPackageName, accounts);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ private void unregisterAccountListener(String[] accountTypes, String opPackageName,
+ UserAccounts accounts) {
synchronized (accounts.mReceiversForType) {
if (accountTypes == null) {
// null for any type
@@ -907,7 +936,7 @@
long identityToken = clearCallingIdentity();
try {
mPackageManager.getPackageUidAsUser(packageName, userId);
- return true; // package exist
+ return true;
} finally {
restoreCallingIdentity(identityToken);
}
@@ -1863,12 +1892,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 +2050,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 +2941,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 +2951,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 +4966,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 +4983,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 +5006,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 +5928,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 b4ea49b..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
};
/**
@@ -1350,7 +1359,13 @@
@GuardedBy("this") boolean mLaunchWarningShown = false;
@GuardedBy("this") boolean mCheckedForSetup = false;
- Context mContext;
+ final Context mContext;
+
+ /**
+ * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can
+ * change at runtime. Use mContext for non-UI purposes.
+ */
+ final Context mUiContext;
/**
* The time at which we will allow normal application switches again,
@@ -1852,7 +1867,7 @@
} break;
case SHOW_FACTORY_ERROR_UI_MSG: {
Dialog d = new FactoryErrorDialog(
- mContext, msg.getData().getCharSequence("msg"));
+ mUiContext, msg.getData().getCharSequence("msg"));
d.show();
ensureBootCompleted();
} break;
@@ -1863,7 +1878,7 @@
if (!app.waitedForDebugger) {
Dialog d = new AppWaitingForDebuggerDialog(
ActivityManagerService.this,
- mContext, app);
+ mUiContext, app);
app.waitDialog = d;
app.waitedForDebugger = true;
d.show();
@@ -1878,24 +1893,24 @@
} break;
case SHOW_UID_ERROR_UI_MSG: {
if (mShowDialogs) {
- AlertDialog d = new BaseErrorDialog(mContext);
+ AlertDialog d = new BaseErrorDialog(mUiContext);
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
d.setCancelable(false);
- d.setTitle(mContext.getText(R.string.android_system_label));
- d.setMessage(mContext.getText(R.string.system_error_wipe_data));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ d.setTitle(mUiContext.getText(R.string.android_system_label));
+ d.setMessage(mUiContext.getText(R.string.system_error_wipe_data));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
obtainMessage(DISMISS_DIALOG_UI_MSG, d));
d.show();
}
} break;
case SHOW_FINGERPRINT_ERROR_UI_MSG: {
if (mShowDialogs) {
- AlertDialog d = new BaseErrorDialog(mContext);
+ AlertDialog d = new BaseErrorDialog(mUiContext);
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
d.setCancelable(false);
- d.setTitle(mContext.getText(R.string.android_system_label));
- d.setMessage(mContext.getText(R.string.system_error_manufacturer));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ d.setTitle(mUiContext.getText(R.string.android_system_label));
+ d.setMessage(mUiContext.getText(R.string.system_error_manufacturer));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
obtainMessage(DISMISS_DIALOG_UI_MSG, d));
d.show();
}
@@ -1919,7 +1934,7 @@
if (mode == ActivityManager.COMPAT_MODE_DISABLED
|| mode == ActivityManager.COMPAT_MODE_ENABLED) {
mCompatModeDialog = new CompatModeDialog(
- ActivityManagerService.this, mContext,
+ ActivityManagerService.this, mUiContext,
ar.info.applicationInfo);
mCompatModeDialog.show();
}
@@ -1939,7 +1954,7 @@
ar.packageName)) {
// TODO(multi-display): Show dialog on appropriate display.
mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
- ActivityManagerService.this, mContext, ar.info.applicationInfo);
+ ActivityManagerService.this, mUiContext, ar.info.applicationInfo);
mUnsupportedDisplaySizeDialog.show();
}
}
@@ -2461,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) {
@@ -2523,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();
@@ -2731,6 +2746,7 @@
public ActivityManagerService(Injector injector) {
mInjector = injector;
mContext = mInjector.getContext();
+ mUiContext = null;
GL_ES_VERSION = 0;
mActivityStarter = null;
mAppErrors = null;
@@ -2762,8 +2778,10 @@
LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
mInjector = new Injector();
mContext = systemContext;
+
mFactoryTest = FactoryTest.getMode();
mSystemThread = ActivityThread.currentActivityThread();
+ mUiContext = mSystemThread.getSystemUiContext();
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
@@ -2771,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);
@@ -2792,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());
}
@@ -2806,7 +2824,7 @@
mServices = new ActiveServices(this);
mProviderMap = new ProviderMap(this);
- mAppErrors = new AppErrors(mContext, this);
+ mAppErrors = new AppErrors(mUiContext, this);
// TODO: Move creation of battery stats service outside of activity manager service.
File dataDir = Environment.getDataDirectory();
@@ -2849,7 +2867,7 @@
mTempConfig.setToDefaults();
mTempConfig.setLocales(LocaleList.getDefault());
mConfigurationSeq = mTempConfig.seq = 1;
- mStackSupervisor = new ActivityStackSupervisor(this);
+ mStackSupervisor = createStackSupervisor();
mStackSupervisor.onConfigurationChanged(mTempConfig);
mKeyguardController = mStackSupervisor.mKeyguardController;
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
@@ -2897,6 +2915,10 @@
Watchdog.getInstance().addThread(mHandler);
}
+ protected ActivityStackSupervisor createStackSupervisor() {
+ return new ActivityStackSupervisor(this, mHandler.getLooper());
+ }
+
public void setSystemServiceManager(SystemServiceManager mgr) {
mSystemServiceManager = mgr;
}
@@ -2906,7 +2928,7 @@
}
private void start() {
- Process.removeAllProcessGroups();
+ removeAllProcessGroups();
mProcessCpuThread.start();
mBatteryStatsService.publish(mContext);
@@ -3114,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);
}
}
@@ -3151,7 +3173,8 @@
* {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
*/
void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
- if (r.task.isApplicationTask()) {
+ final TaskRecord task = r.getTask();
+ if (task.isApplicationTask()) {
if (mCurAppTimeTracker != r.appTimeTracker) {
// We are switching app tracking. Complete the current one.
if (mCurAppTimeTracker != null) {
@@ -3174,17 +3197,18 @@
// TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null
// TODO: Probably not, because we don't want to resume voice on switching
// back to this activity
- if (r.task.voiceInteractor != null) {
- startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
+ if (task.voiceInteractor != null) {
+ startRunningVoiceLocked(task.voiceSession, r.info.applicationInfo.uid);
} else {
finishRunningVoiceLocked();
if (mLastResumedActivity != null) {
final IVoiceInteractionSession session;
- if (mLastResumedActivity.task != null
- && mLastResumedActivity.task.voiceSession != null) {
- session = mLastResumedActivity.task.voiceSession;
+ final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
+ if (lastResumedActivityTask != null
+ && lastResumedActivityTask.voiceSession != null) {
+ session = lastResumedActivityTask.voiceSession;
} else {
session = mLastResumedActivity.voiceSession;
}
@@ -3317,7 +3341,7 @@
final void showAskCompatModeDialogLocked(ActivityRecord r) {
Message msg = Message.obtain();
msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
- msg.obj = r.task.askedCompatMode ? null : r;
+ msg.obj = r.getTask().askedCompatMode ? null : r;
mUiHandler.sendMessage(msg);
}
@@ -3384,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) {
@@ -3593,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).
@@ -3659,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";
@@ -3954,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);
@@ -4193,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);
@@ -4559,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) {
@@ -4723,7 +4747,7 @@
if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
throw new SecurityException("Only focused activity can call startVoiceInteraction");
}
- if (mRunningVoice != null || activity.task.voiceSession != null
+ if (mRunningVoice != null || activity.getTask().voiceSession != null
|| activity.voiceSession != null) {
Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
return;
@@ -5033,7 +5057,7 @@
return true;
}
// Keep track of the root activity of the task before we finish it
- TaskRecord tr = r.task;
+ TaskRecord tr = r.getTask();
ActivityRecord rootR = tr.getRootActivity();
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
@@ -5170,7 +5194,7 @@
// Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
// can finish.
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV &&
mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
mStackSupervisor.showLockTaskToast();
@@ -5411,7 +5435,7 @@
if (!app.killed) {
if (!fromBinderDied) {
- Process.killProcessQuiet(pid);
+ killProcessQuiet(pid);
}
killProcessGroup(app.uid, pid);
app.killed = true;
@@ -5506,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.
@@ -5761,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) {
@@ -5979,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;
}
@@ -6011,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;
@@ -6038,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);
@@ -6069,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
@@ -6135,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) {
@@ -6171,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));
}
@@ -6688,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 {
@@ -6796,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));
@@ -7019,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);
@@ -7056,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 {
@@ -7397,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)) {
@@ -7834,7 +7858,7 @@
return false;
}
// An activity is consider to be in multi-window mode if its task isn't fullscreen.
- return !r.task.mFullscreen;
+ return !r.getTask().mFullscreen;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -8664,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 {
@@ -9150,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");
@@ -9534,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;
@@ -9927,8 +9951,9 @@
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
r.setTaskDescription(td);
- r.task.updateTaskDescription();
- mTaskChangeNotificationController.notifyTaskDescriptionChanged(r.task.taskId, td);
+ final TaskRecord task = r.getTask();
+ task.updateTaskDescription();
+ mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
}
}
}
@@ -10378,8 +10403,8 @@
}
if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
- r.task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT,
- ANIMATE, !DEFER_RESUME, "exitFreeformMode");
+ r.getTask().reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
+ REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "exitFreeformMode");
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10677,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) {
@@ -10688,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()");
}
@@ -10711,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) {
@@ -10760,7 +10785,7 @@
if (r == null) {
return;
}
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (task != null) {
startLockTaskModeLocked(task);
}
@@ -10859,7 +10884,7 @@
if (r == null) {
return;
}
- mStackSupervisor.showLockTaskEscapeMessageLocked(r.task);
+ mStackSupervisor.showLockTaskEscapeMessageLocked(r.getTask());
}
}
@@ -11190,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;
@@ -11892,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--) {
@@ -12065,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++;
@@ -13121,9 +13146,10 @@
if (r == null) {
return false;
}
- int index = r.task.mActivities.lastIndexOf(r);
+ final TaskRecord task = r.getTask();
+ int index = task.mActivities.lastIndexOf(r);
if (index > 0) {
- ActivityRecord under = r.task.mActivities.get(index - 1);
+ ActivityRecord under = task.mActivities.get(index - 1);
under.returningOptions = ActivityOptions.fromBundle(options);
}
final boolean translucentChanged = r.changeWindowTranslucency(false);
@@ -13257,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;
}
@@ -13281,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.
@@ -13300,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) {
@@ -13320,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");
}
@@ -13332,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 {
@@ -13410,7 +13436,7 @@
if (r == null) {
throw new IllegalArgumentException();
}
- return r.task.getTopActivity() == r;
+ return r.getTask().getTopActivity() == r;
}
}
@@ -13496,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,
@@ -13519,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);
}
@@ -13538,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;
@@ -13611,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");
}
@@ -13619,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");
}
@@ -13696,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);
}
};
@@ -14040,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);
@@ -14054,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 {
@@ -15928,8 +15954,9 @@
}
needSep = true;
synchronized (this) {
- if (lastTask != r.task) {
- lastTask = r.task;
+ final TaskRecord task = r.getTask();
+ if (lastTask != task) {
+ lastTask = task;
pw.print("TASK "); pw.print(lastTask.affinity);
pw.print(" id="); pw.print(lastTask.taskId);
pw.print(" userId="); pw.println(lastTask.userId);
@@ -16698,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;
@@ -17989,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,
@@ -18008,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,
@@ -18026,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;
}
@@ -18268,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.
@@ -18329,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
@@ -18546,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)) {
@@ -18730,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
@@ -18774,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:
@@ -19154,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(
@@ -19396,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 "
@@ -19852,7 +19879,7 @@
private void enforceWriteSettingsPermission(String func) {
int uid = Binder.getCallingUid();
- if (uid == Process.ROOT_UID) {
+ if (uid == ROOT_UID) {
return;
}
@@ -20050,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);
@@ -20061,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);
}
@@ -20561,8 +20588,9 @@
app.cached = false;
app.empty = false;
foregroundActivities = true;
- if (r.task != null && minLayer > 0) {
- final int layer = r.task.mLayerRank;
+ final TaskRecord task = r.getTask();
+ if (task != null && minLayer > 0) {
+ final int layer = task.mLayerRank;
if (layer >= 0 && minLayer > layer) {
minLayer = layer;
}
@@ -21534,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
@@ -21562,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
}
@@ -21587,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
}
@@ -21602,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);
}
}
}
@@ -22728,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");
}
@@ -22742,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);
}
}
}
@@ -23883,7 +23911,7 @@
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mLruProcesses.get(i);
- if (app.thread == null || app.pid == Process.myPid()) {
+ if (app.thread == null) {
continue;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index cbb51e1..3a29414 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -229,7 +229,7 @@
private int theme; // resource identifier of activity's theme.
private int realTheme; // actual theme resource we will use, never 0.
private int windowFlags; // custom window flags for preview window.
- TaskRecord task; // the task this is in.
+ private TaskRecord task; // the task this is in.
private long createTime = System.currentTimeMillis();
long displayStartTime; // when we started launching this activity
long fullyDrawnStartTime; // when we started launching this activity
@@ -686,9 +686,48 @@
@Override
protected ConfigurationContainer getParent() {
+ return getTask();
+ }
+
+ TaskRecord getTask() {
return task;
}
+ /**
+ * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
+ * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
+ * children. However, this method will clean up references to this {@link ActivityRecord} in
+ * {@link ActivityStack}.
+ * @param task The new parent {@link TaskRecord}.
+ */
+ void setTask(TaskRecord task) {
+ setTask(task, false /*reparenting*/);
+ }
+
+ /**
+ * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
+ */
+ void setTask(TaskRecord task, boolean reparenting) {
+ // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}.
+ if (task != null && task == getTask()) {
+ return;
+ }
+
+ final ActivityStack stack = getStack();
+
+ // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
+ // {@link ActivityRecord} from its current {@link ActivityStack}.
+ if (!reparenting && stack != null && (task == null || stack != task.getStack())) {
+ stack.onActivityRemovedFromStack(this);
+ }
+
+ this.task = task;
+
+ if (!reparenting) {
+ onParentChanged();
+ }
+ }
+
static class Token extends IApplicationToken.Stub {
private final WeakReference<ActivityRecord> weakActivity;
@@ -925,8 +964,8 @@
// Must reparent first in window manager
mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
- // Remove the activity from the old task and add it to the new task
- prevTask.removeActivity(this);
+ // Remove the activity from the old task and add it to the new task.
+ prevTask.removeActivity(this, true /*reparenting*/);
newTask.addActivityAtIndex(position, this);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ee37463..f13b11e 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -116,6 +116,7 @@
import android.util.SparseArray;
import android.view.Display;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
@@ -725,7 +726,7 @@
if (r == null) {
return null;
}
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final ActivityStack stack = r.getStack();
if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
if (stack != this) Slog.w(TAG,
@@ -934,7 +935,7 @@
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
+ taskIntent.getComponent().flattenToShortString()
- + "/aff=" + r.task.rootAffinity + " to new cls="
+ + "/aff=" + r.getTask().rootAffinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
// TODO Refactor to remove duplications. Check if logic can be simplified.
if (taskIntent != null && taskIntent.getComponent() != null &&
@@ -1049,8 +1050,9 @@
void addRecentActivityLocked(ActivityRecord r) {
if (r != null) {
- mRecentTasks.addLocked(r.task);
- r.task.touchActiveTime();
+ final TaskRecord task = r.getTask();
+ mRecentTasks.addLocked(task);
+ task.touchActiveTime();
}
}
@@ -1226,11 +1228,12 @@
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
prev.state = ActivityState.PAUSING;
- prev.task.touchActiveTime();
+ prev.getTask().touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
if (mService.mHasRecents
- && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
+ && (next == null || next.noDisplay || next.getTask() != prev.getTask()
+ || uiSleeping)) {
prev.mUpdateTaskThumbnailWhenHidden = true;
}
stopFullyDrawnTraceIfNeeded();
@@ -1457,7 +1460,7 @@
// Find the first visible activity above the passed activity and if it is translucent return it
// otherwise return null;
ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
- TaskRecord task = r.task;
+ TaskRecord task = r.getTask();
if (task == null) {
return null;
}
@@ -1604,7 +1607,7 @@
// Otherwise, the docked stack is always visible, except in the case where the top
// running activity task in the focus stack doesn't support any form of resizing but we
// show it for the home task even though it's not resizable.
- final TaskRecord task = r != null ? r.task : null;
+ final TaskRecord task = r != null ? r.getTask() : null;
return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
: STACK_INVISIBLE;
}
@@ -2157,8 +2160,9 @@
mResumedActivity = r;
r.state = ActivityState.RESUMED;
mService.setResumedActivityUncheckLocked(r, reason);
- r.task.touchActiveTime();
- mRecentTasks.addLocked(r.task);
+ final TaskRecord task = r.getTask();
+ task.touchActiveTime();
+ mRecentTasks.addLocked(task);
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -2207,8 +2211,8 @@
return false;
}
- final TaskRecord nextTask = next.task;
- final TaskRecord prevTask = prev != null ? prev.task : null;
+ final TaskRecord nextTask = next.getTask();
+ final TaskRecord prevTask = prev != null ? prev.getTask() : null;
if (prevTask != null && prevTask.getStack() == this &&
prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2373,7 +2377,7 @@
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
- mWindowManager.prepareAppTransition(prev.task == next.task
+ mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_CLOSE
: TRANSIT_TASK_CLOSE, false);
}
@@ -2385,7 +2389,7 @@
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
- mWindowManager.prepareAppTransition(prev.task == next.task
+ mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
@@ -2522,7 +2526,8 @@
next.notifyAppResumed(next.stopped, allowSavedSurface);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
- System.identityHashCode(next), next.task.taskId, next.shortComponentName);
+ System.identityHashCode(next), next.getTask().taskId,
+ next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
@@ -2696,9 +2701,15 @@
return;
}
- // If the task was launched from the assistant stack, set the return type to assistant
final ActivityStack lastStack = mStackSupervisor.getLastStack();
- if (lastStack != null && lastStack.isAssistantStack()) {
+
+ // If there is no last task, do not set task to return to
+ if (lastStack == null) {
+ return;
+ }
+
+ // If the task was launched from the assistant stack, set the return type to assistant
+ if (lastStack.isAssistantStack()) {
task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
return;
}
@@ -2721,7 +2732,7 @@
final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
- TaskRecord rTask = r.task;
+ TaskRecord rTask = r.getTask();
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
@@ -2740,7 +2751,7 @@
// All activities in task are finishing.
continue;
}
- if (task == r.task) {
+ if (task == rTask) {
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.
@@ -2762,13 +2773,14 @@
// If we are not placing the new activity frontmost, we do not want to deliver the
// onUserLeaving callback to the actual frontmost activity
- if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
+ final TaskRecord activityTask = r.getTask();
+ if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
}
- task = r.task;
+ task = activityTask;
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
@@ -2795,7 +2807,8 @@
} else {
// If a new task is being launched, then mark the existing top activity as
// supporting picture-in-picture while pausing
- if (focusedTopActivity != null) {
+ if (focusedTopActivity != null &&
+ focusedTopActivity.getStack().getStackId() != PINNED_STACK_ID) {
focusedTopActivity.supportsPictureInPictureWhilePausing = true;
}
transit = TRANSIT_TASK_OPEN;
@@ -2829,11 +2842,12 @@
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
- ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
+ TaskRecord prevTask = r.getTask();
+ ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
- if (prev.task != r.task) {
+ if (prev.getTask() != prevTask) {
prev = null;
}
// (2) The current activity is already displayed.
@@ -2852,7 +2866,7 @@
private boolean isTaskSwitch(ActivityRecord r,
ActivityRecord topFocusedActivity) {
- return topFocusedActivity != null && r.task != topFocusedActivity.task;
+ return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
}
/**
@@ -2919,20 +2933,20 @@
!mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
mTaskHistory.get(0).mActivities.get(0) : null;
if (bottom != null && target.taskAffinity != null
- && target.taskAffinity.equals(bottom.task.affinity)) {
+ && target.taskAffinity.equals(bottom.getTask().affinity)) {
// If the activity currently at the bottom has the
// same task affinity as the one we are moving,
// then merge it into the same task.
- targetTask = bottom.task;
+ targetTask = bottom.getTask();
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
- + " out to bottom task " + bottom.task);
+ + " out to bottom task " + targetTask);
} else {
targetTask = createTaskRecord(
mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
target.info, null, null, null, false, target.mActivityType);
targetTask.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
- + " out to new task " + target.task);
+ + " out to new task " + targetTask);
}
boolean noOptions = canMoveOptions;
@@ -2954,7 +2968,7 @@
"Removing activity " + p + " from task=" + task + " adding to task="
+ targetTask + " Callers=" + Debug.getCallers(4));
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Pushing next activity " + p + " out to target's task " + target.task);
+ "Pushing next activity " + p + " out to target's task " + target);
p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
}
@@ -3125,13 +3139,13 @@
boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
if (ACTIVITY_INACTIVE_RESET_TIME > 0
- && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
+ && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
forceReset = true;
}
}
- final TaskRecord task = taskTop.task;
+ final TaskRecord task = taskTop.getTask();
/** False until we evaluate the TaskRecord associated with taskTop. Switches to true
* for remaining tasks. Used for later tasks to reparent to task. */
@@ -3214,7 +3228,7 @@
// stack as long as there is a running activity.
return;
} else {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() ||
task.isOverAssistantStack();
if (r.frontOfTask && task == topTask() &&
@@ -3373,10 +3387,12 @@
}
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
- int taskNdx = mTaskHistory.indexOf(r.task);
- int activityNdx = r.task.mActivities.indexOf(r);
+ finishedTask = r.getTask();
+ int taskNdx = mTaskHistory.indexOf(finishedTask);
+ final TaskRecord task = finishedTask;
+ int activityNdx = task.mActivities.indexOf(r);
finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
- finishedTask = r.task;
+ finishedTask = task;
// Also terminate any activities below it that aren't yet
// stopped, to avoid a situation where one will get
// re-start our crashing activity once it gets resumed again.
@@ -3446,7 +3462,7 @@
}
final boolean finishActivityAffinityLocked(ActivityRecord r) {
- ArrayList<ActivityRecord> activities = r.task.mActivities;
+ ArrayList<ActivityRecord> activities = r.getTask().mActivities;
for (int index = activities.indexOf(r); index >= 0; --index) {
ActivityRecord cur = activities.get(index);
if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
@@ -3511,7 +3527,7 @@
mWindowManager.deferSurfaceLayout();
try {
r.makeFinishingLocked();
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.userId, System.identityHashCode(r),
task.taskId, r.shortComponentName, reason);
@@ -3700,23 +3716,24 @@
final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
// Basic case: for simple app-centric recents, we need to recreate
// the task if the affinity has changed.
- if (srec == null || srec.task.affinity == null ||
- !srec.task.affinity.equals(destAffinity)) {
+ if (srec == null || srec.getTask().affinity == null ||
+ !srec.getTask().affinity.equals(destAffinity)) {
return true;
}
// Document-centric case: an app may be split in to multiple documents;
// they need to re-create their task if this current activity is the root
// of a document, unless simply finishing it will return them to the the
// correct app behind.
- if (srec.frontOfTask && srec.task != null && srec.task.getBaseIntent() != null
- && srec.task.getBaseIntent().isDocument()) {
+ final TaskRecord task = srec.getTask();
+ if (srec.frontOfTask && task != null && task.getBaseIntent() != null
+ && task.getBaseIntent().isDocument()) {
// Okay, this activity is at the root of its task. What to do, what to do...
- if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
+ if (task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
// Finishing won't return to an application, so we need to recreate.
return true;
}
// We now need to get the task below it to determine what to do.
- int taskIdx = mTaskHistory.indexOf(srec.task);
+ int taskIdx = mTaskHistory.indexOf(task);
if (taskIdx <= 0) {
Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
return false;
@@ -3726,7 +3743,7 @@
return true;
}
TaskRecord prevTask = mTaskHistory.get(taskIdx);
- if (!srec.task.affinity.equals(prevTask.affinity)) {
+ if (!task.affinity.equals(prevTask.affinity)) {
// These are different apps, so need to recreate.
return true;
}
@@ -3736,7 +3753,7 @@
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
- final TaskRecord task = srec.task;
+ final TaskRecord task = srec.getTask();
final ArrayList<ActivityRecord> activities = task.mActivities;
final int start = activities.indexOf(srec);
if (!mTaskHistory.contains(task) || (start < 0)) {
@@ -3815,6 +3832,22 @@
Binder.restoreCallingIdentity(origId);
return foundParentInTask;
}
+
+ /**
+ * Remove any state associated with the {@link ActivityRecord}. This should be called whenever
+ * an activity moves away from the stack.
+ */
+ void onActivityRemovedFromStack(ActivityRecord r) {
+ if (mResumedActivity == r) {
+ mResumedActivity = null;
+ }
+ if (mPausingActivity == r) {
+ mPausingActivity = null;
+ }
+
+ removeTimeoutsForActivityLocked(r);
+ }
+
/**
* Perform the common clean-up of an activity record. This is called both
* as part of destroyActivityLocked() (when destroying the client-side
@@ -3825,12 +3858,7 @@
* Note: Call before #removeActivityFromHistoryLocked.
*/
private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
- if (mResumedActivity == r) {
- mResumedActivity = null;
- }
- if (mPausingActivity == r) {
- mPausingActivity = null;
- }
+ onActivityRemovedFromStack(r);
r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
@@ -3897,7 +3925,7 @@
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
r.app = null;
r.removeWindowContainer();
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final boolean lastActivity = task != null ? task.removeActivity(r) : false;
// If we are removing the last activity in the task, not including task overlay activities,
// then fall through into the block below to remove the entire task itself
@@ -4043,7 +4071,7 @@
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
r.userId, System.identityHashCode(r),
- r.task.taskId, r.shortComponentName, reason);
+ r.getTask().taskId, r.shortComponentName, reason);
boolean removedFromHistory = false;
@@ -4275,7 +4303,7 @@
Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.userId, System.identityHashCode(r),
- r.task.taskId, r.shortComponentName,
+ r.getTask().taskId, r.shortComponentName,
"proc died without state saved");
if (r.state == ActivityState.RESUMED) {
mService.updateUsageStats(r, false);
@@ -4403,7 +4431,7 @@
}
// If a new task is moved to the front, then mark the existing top activity as supporting
// picture-in-picture while paused
- if (topActivity != null) {
+ if (topActivity != null && topActivity.getStack().getStackId() != PINNED_STACK_ID) {
topActivity.supportsPictureInPictureWhilePausing = true;
}
@@ -4529,7 +4557,7 @@
}
}
- final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
+ final TaskRecord task = mResumedActivity != null ? mResumedActivity.getTask() : null;
if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
@@ -4570,7 +4598,7 @@
return;
}
- final TaskRecord startTask = start.task;
+ final TaskRecord startTask = start.getTask();
boolean behindFullscreen = false;
boolean updatedConfig = false;
@@ -4578,7 +4606,7 @@
final TaskRecord task = mTaskHistory.get(taskIndex);
final ArrayList<ActivityRecord> activities = task.mActivities;
int activityIndex =
- (start.task == task) ? activities.indexOf(start) : activities.size() - 1;
+ (start.getTask() == task) ? activities.indexOf(start) : activities.size() - 1;
for (; activityIndex >= 0; --activityIndex) {
final ActivityRecord r = activities.get(activityIndex);
updatedConfig |= r.ensureActivityConfigurationLocked(0 /* globalChanges */,
@@ -4739,7 +4767,7 @@
|| filterByClasses.contains(r.realActivity.getClassName())))
|| (packageName == null && r.userId == userId);
if ((userId == UserHandle.USER_ALL || r.userId == userId)
- && (sameComponent || r.task == lastTask)
+ && (sameComponent || r.getTask() == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
if (r.finishing) {
@@ -4765,7 +4793,7 @@
}
r.app = null;
}
- lastTask = r.task;
+ lastTask = r.getTask();
if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
true)) {
// r has been deleted from mActivities, accommodate.
@@ -4816,7 +4844,7 @@
if (DEBUG_ALL) Slog.v(
TAG, r.intent.getComponent().flattenToShortString()
- + ": task=" + r.task);
+ + ": task=" + r.getTask());
}
RunningTaskInfo ci = new RunningTaskInfo();
@@ -4832,8 +4860,8 @@
topTask = false;
}
- if (top.task != null) {
- ci.description = top.task.lastDescription;
+ if (top.getTask() != null) {
+ ci.description = top.getTask().lastDescription;
}
ci.numActivities = numActivities;
ci.numRunning = numRunning;
@@ -4982,9 +5010,8 @@
task.removeWindowContainer();
}
- final ActivityRecord r = mResumedActivity;
- if (r != null && r.task == task) {
- mResumedActivity = null;
+ for (ActivityRecord record : task.mActivities) {
+ onActivityRemovedFromStack(record);
}
final int taskNdx = mTaskHistory.indexOf(task);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f16849d..3e3fee5 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -164,6 +164,7 @@
import android.view.InputEvent;
import android.view.Surface;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -173,6 +174,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.StackWindowController;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -553,9 +555,9 @@
}
}
- public ActivityStackSupervisor(ActivityManagerService service) {
+ public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
mService = service;
- mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
+ mHandler = new ActivityStackSupervisorHandler(looper);
mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
mKeyguardController = new KeyguardController(service, this);
}
@@ -722,7 +724,7 @@
}
if (prev != null) {
- prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+ prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
mHomeStack.moveHomeStackTaskToTop();
@@ -743,7 +745,7 @@
}
/**
- * Returns a {@link TaskRecord} for the input id if available. Null otherwise.
+ * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
* @param id Id of the task we would like returned.
* @param matchMode The mode to match the given task id in.
* @param stackId The stack to restore the task to (default launch stack will be used if
@@ -763,7 +765,7 @@
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
- TaskRecord task = stack.taskForIdLocked(id);
+ final TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
}
@@ -778,11 +780,17 @@
// Otherwise, check the recent tasks and return if we find it there and we are not restoring
// the task from recents
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- TaskRecord task = mRecentTasks.taskForIdLocked(id);
- if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
- if (DEBUG_RECENTS && task == null) {
+ final TaskRecord task = mRecentTasks.taskForIdLocked(id);
+
+ if (task == null) {
+ if (DEBUG_RECENTS) {
Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
}
+
+ return null;
+ }
+
+ if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
return task;
}
@@ -1314,7 +1322,7 @@
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
@@ -2622,7 +2630,7 @@
}
for (int k = 0; k < proc.activities.size(); k++) {
- TaskRecord otherTask = proc.activities.get(k).task;
+ TaskRecord otherTask = proc.activities.get(k).getTask();
if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
// Don't kill process(es) that has an activity in a different task that is
// also in recents.
@@ -2837,7 +2845,7 @@
final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
try {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
if (r == task.getStack().getVisibleBehindActivity()) {
// An activity can't be pinned and visible behind at the same time. Go ahead and
@@ -2910,7 +2918,7 @@
return false;
}
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final ActivityStack stack = r.getStack();
if (stack == null) {
Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
@@ -3203,7 +3211,7 @@
// Called when WindowManager has finished animating the launchingBehind activity to the back.
private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
final ActivityStack stack = task.getStack();
r.mLaunchTaskBehind = false;
@@ -3216,7 +3224,7 @@
// task has been shown briefly
final ActivityRecord top = stack.topActivity();
if (top != null) {
- top.task.touchActiveTime();
+ top.getTask().touchActiveTime();
}
}
@@ -3315,17 +3323,19 @@
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
continue;
}
- if (r.task != null) {
- if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + r.task
+
+ final TaskRecord task = r.getTask();
+ if (task != null) {
+ if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
+ " from " + r);
if (firstTask == null) {
- firstTask = r.task;
- } else if (firstTask != r.task) {
+ firstTask = task;
+ } else if (firstTask != task) {
if (tasks == null) {
tasks = new ArraySet<>();
tasks.add(firstTask);
}
- tasks.add(r.task);
+ tasks.add(task);
}
}
}
@@ -3664,8 +3674,8 @@
pw.println(header2);
header2 = null;
}
- if (lastTask != r.task) {
- lastTask = r.task;
+ if (lastTask != r.getTask()) {
+ lastTask = r.getTask();
pw.print(prefix);
pw.print(full ? "* " : " ");
pw.println(lastTask);
@@ -4080,7 +4090,7 @@
}
}
final ActivityRecord r = topRunningActivityLocked();
- final TaskRecord task = r != null ? r.task : null;
+ final TaskRecord task = r != null ? r.getTask() : null;
if (mLockTaskModeTasks.isEmpty() && task != null
&& task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
// This task must have just been authorized.
@@ -4390,19 +4400,24 @@
synchronized (mService) {
mStackId = stackId;
mActivityDisplay = activityDisplay;
- switch (mStackId) {
- case PINNED_STACK_ID:
- new PinnedActivityStack(this, mRecentTasks, onTop);
- break;
- default:
- new ActivityStack(this, mRecentTasks, onTop);
- break;
- }
mIdString = "ActivtyContainer{" + mStackId + "}";
+
+ createStack(stackId, onTop);
if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
}
}
+ protected void createStack(int stackId, boolean onTop) {
+ switch (stackId) {
+ case PINNED_STACK_ID:
+ new PinnedActivityStack(this, mRecentTasks, onTop);
+ break;
+ default:
+ new ActivityStack(this, mRecentTasks, onTop);
+ break;
+ }
+ }
+
/**
* Adds the stack to specified display. Also calls WindowManager to do the same from
* {@link ActivityStack#reparent(ActivityDisplay, boolean)}.
@@ -4926,7 +4941,7 @@
mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
ActivityManager.START_TASK_TO_FRONT,
- sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
+ sourceRecord != null ? sourceRecord.getTask().getStackId() : INVALID_STACK_ID,
sourceRecord, task.getStack());
return ActivityManager.START_TASK_TO_FRONT;
}
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 547161a..cafc4f0 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -188,10 +188,10 @@
}
ActivityRecord homeActivityRecord = mSupervisor.getHomeActivity();
- if (homeActivityRecord != null && homeActivityRecord.task != null) {
+ if (homeActivityRecord != null && homeActivityRecord.getTask() != null) {
// Showing credential confirmation activity in home task to avoid stopping multi-windowed
// mode after showing the full-screen credential confirmation activity.
- mActivityOptions.setLaunchTaskId(homeActivityRecord.task.taskId);
+ mActivityOptions.setLaunchTaskId(homeActivityRecord.getTask().taskId);
}
final UserInfo parent = mUserManager.getProfileParent(mUserId);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 18e74080..b408569 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -79,7 +79,6 @@
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
@@ -87,8 +86,6 @@
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
-import static java.lang.Integer.MAX_VALUE;
-
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -335,7 +332,7 @@
}
if (err == ActivityManager.START_SUCCESS && sourceRecord != null
- && sourceRecord.task.voiceSession != null) {
+ && sourceRecord.getTask().voiceSession != null) {
// If this activity is being launched as part of a voice session, we need
// to ensure that it is safe to do so. If the upcoming activity will also
// be part of the voice session, we can only launch it if it has explicitly
@@ -575,7 +572,7 @@
// visibility instead of using this flag.
final boolean noDisplayActivityOverHome = sourceRecord != null
&& sourceRecord.noDisplay
- && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
+ && sourceRecord.getTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
if (startedActivityStackId == DOCKED_STACK_ID
&& (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
@@ -625,7 +622,7 @@
FLAG_ACTIVITY_TASK_ON_HOME);
ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
: ActivityOptions.makeBasic());
- options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
+ options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
}
@@ -763,7 +760,7 @@
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
- hist.task.taskId);
+ hist.getTask().taskId);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
@@ -967,8 +964,8 @@
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
- if (result != START_SUCCESS && mStartActivity.task != null) {
- mStartActivity.task.removeActivity(mStartActivity);
+ if (result != START_SUCCESS && mStartActivity.getTask() != null) {
+ mStartActivity.getTask().removeActivity(mStartActivity);
}
mService.mWindowManager.continueSurfaceLayout();
}
@@ -1002,7 +999,7 @@
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
- if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
+ if (mSupervisor.isLockTaskModeViolation(mReusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
@@ -1010,13 +1007,13 @@
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
- if (mStartActivity.task == null) {
- mStartActivity.task = mReusedActivity.task;
+ if (mStartActivity.getTask() == null) {
+ mStartActivity.setTask(mReusedActivity.getTask());
}
- if (mReusedActivity.task.intent == null) {
+ if (mReusedActivity.getTask().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
- mReusedActivity.task.setIntent(mStartActivity);
+ mReusedActivity.getTask().setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
@@ -1025,7 +1022,7 @@
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
- final TaskRecord task = mReusedActivity.task;
+ final TaskRecord task = mReusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
@@ -1037,17 +1034,17 @@
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
- if (mReusedActivity.task == null) {
- mReusedActivity.task = task;
+ if (mReusedActivity.getTask() == null) {
+ mReusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
- top.task.setIntent(mStartActivity);
+ top.getTask().setIntent(mStartActivity);
}
- ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
@@ -1098,7 +1095,7 @@
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
- ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
@@ -1116,14 +1113,14 @@
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(
- top.task, preferredLaunchStackId, topStack.mStackId);
+ top.getTask(), preferredLaunchStackId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
- ? mSourceRecord.task : null;
+ ? mSourceRecord.getTask() : null;
// Should this be considered a new task?
int result = START_SUCCESS;
@@ -1150,14 +1147,15 @@
mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
if (mSourceRecord != null) {
- mStartActivity.task.setTaskToReturnTo(mSourceRecord);
+ mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
}
if (newTask) {
EventLog.writeEvent(
- EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
+ EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
+ mStartActivity.getTask().taskId);
}
ActivityStack.logStartActivity(
- EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
+ EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
mTargetStack.mLastPausedActivity = null;
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
@@ -1165,7 +1163,8 @@
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
- final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
+ final ActivityRecord topTaskActivity =
+ mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
@@ -1197,7 +1196,7 @@
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(
- mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
+ mStartActivity.getTask(), preferredLaunchStackId, mTargetStack.mStackId);
return START_SUCCESS;
}
@@ -1424,7 +1423,7 @@
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
mNewTaskInfo = mSourceRecord.info;
- mNewTaskIntent = mSourceRecord.task.intent;
+ mNewTaskIntent = mSourceRecord.getTask().intent;
}
mSourceRecord = null;
mSourceStack = null;
@@ -1516,15 +1515,16 @@
ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
- if (curTop != null
- && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
+ final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
+ if (topTask != null
+ && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
&& !mAvoidMoveToFront) {
mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
- mSourceStack.topActivity().task == mSourceRecord.task)) {
+ mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
// We really do want to push this one into the user's face, right now.
if (mLaunchTaskBehind && mSourceRecord != null) {
- intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
+ intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
}
mMovedOtherTask = true;
@@ -1539,13 +1539,13 @@
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
if (!willClearTask) {
final ActivityStack launchStack = getLaunchStack(
- mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
+ mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
+ final TaskRecord intentTask = intentActivity.getTask();
if (launchStack == null || launchStack == mTargetStack) {
// We only want to move to the front, if we aren't going to launch on a
// different stack. If we launch on a different stack, we will put the
// task on top there.
- mTargetStack.moveTaskToFrontLocked(
- intentActivity.task, mNoAnimation, mOptions,
+ mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
mMovedToFront = true;
} else if (launchStack.mStackId == DOCKED_STACK_ID
@@ -1553,7 +1553,7 @@
if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// If we want to launch adjacent and mTargetStack is not the computed
// launch stack - move task to top of computed stack.
- intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+ intentTask.reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"launchToSide");
} else {
@@ -1561,8 +1561,8 @@
// We choose to move task to front instead of launching it adjacent
// when specific stack was requested explicitly and it appeared to be
// adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
- mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
- mOptions, mStartActivity.appTimeTracker,
+ mTargetStack.moveTaskToFrontLocked(intentTask,
+ mNoAnimation, mOptions, mStartActivity.appTimeTracker,
"bringToFrontInsteadOfAdjacentLaunch");
}
mMovedToFront = true;
@@ -1570,7 +1570,7 @@
// Target and computed stacks are on different displays and we've
// found a matching task - move the existing instance to that display and
// move it to front.
- intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+ intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentToDisplay");
mMovedToFront = true;
@@ -1582,7 +1582,7 @@
intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
true /* taskSwitch */);
}
- updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
+ updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
}
}
if (!mMovedToFront && mDoResume) {
@@ -1591,7 +1591,7 @@
mTargetStack.moveToFront("intentActivityFound");
}
- mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
+ mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
mTargetStack.mStackId);
// If the caller has requested that the target task be reset, then do so.
@@ -1635,7 +1635,7 @@
// launching another activity.
// TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
// already launching one.
- final TaskRecord task = intentActivity.task;
+ final TaskRecord task = intentActivity.getTask();
task.performClearTaskLocked();
mReuseTask = task;
mReuseTask.setIntent(mStartActivity);
@@ -1646,7 +1646,7 @@
mMovedOtherTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| mLaunchSingleInstance || mLaunchSingleTask) {
- ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
+ ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
mLaunchFlags);
if (top == null) {
// A special case: we need to start the activity because it is not currently
@@ -1655,11 +1655,11 @@
mAddingToTask = true;
// We are no longer placing the activity in the task we previously thought we were.
- mStartActivity.task = null;
+ mStartActivity.setTask(null);
// Now pretend like this activity is being started by the top of its task, so it
// is put in the right place.
mSourceRecord = intentActivity;
- final TaskRecord task = mSourceRecord.task;
+ final TaskRecord task = mSourceRecord.getTask();
if (task != null && task.getStack() == null) {
// Target stack got cleared when we all activities were removed above.
// Go ahead and reset it.
@@ -1669,7 +1669,7 @@
!mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
}
}
- } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
+ } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
// In this case the top activity on the task is the same as the one being launched,
// so we take that as a request to bring the task to the foreground. If the top
// activity in the task is the root activity, deliver this new intent to it if it
@@ -1677,13 +1677,13 @@
if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
- intentActivity.task);
+ intentActivity.getTask());
if (intentActivity.frontOfTask) {
- intentActivity.task.setIntent(mStartActivity);
+ intentActivity.getTask().setIntent(mStartActivity);
}
intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
- } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
+ } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
// In this case we are launching the root activity of the task, but with a
// different intent. We should start a new instance on top.
mAddingToTask = true;
@@ -1696,13 +1696,13 @@
// current task.
mAddingToTask = true;
mSourceRecord = intentActivity;
- } else if (!intentActivity.task.rootWasReset) {
+ } else if (!intentActivity.getTask().rootWasReset) {
// In this case we are launching into an existing task that has not yet been started
// from its front door. The current task has been brought to the front. Ideally,
// we'd probably like to place this new task at the bottom of its stack, but that's
// a little hard to do with the current organization of the code so for now we'll
// just drop it.
- intentActivity.task.setIntent(mStartActivity);
+ intentActivity.getTask().setIntent(mStartActivity);
}
}
@@ -1736,11 +1736,11 @@
mService.resizeStack(
stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
- mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
+ mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
}
}
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new task " + mStartActivity.task);
+ + " in new task " + mStartActivity.getTask());
} else {
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
@@ -1749,7 +1749,7 @@
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
- if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
+ if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
@@ -1758,7 +1758,7 @@
// If stack id is specified in activity options, usually it means that activity is
// launched not from currently focused stack (e.g. from SysUI or from shell) - in
// that case we check the target stack.
- updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
+ updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
}
if (mDoResume) {
@@ -1768,19 +1768,19 @@
}
private int setTaskFromSourceRecord() {
- if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
+ if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
- final TaskRecord sourceTask = mSourceRecord.task;
+ final TaskRecord sourceTask = mSourceRecord.getTask();
final ActivityStack sourceStack = mSourceRecord.getStack();
// We only want to allow changing stack if the target task is not the top one,
// otherwise we would move the launching task to the other side, rather than show
// two side by side.
final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
if (moveStackAllowed) {
- mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
+ mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
mOptions);
}
@@ -1805,7 +1805,7 @@
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
if (top != null) {
- ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
@@ -1821,7 +1821,7 @@
// stack if so.
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
if (top != null) {
- final TaskRecord task = top.task;
+ final TaskRecord task = top.getTask();
task.moveActivityToFrontLocked(top);
top.updateOptionsLocked(mOptions);
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
@@ -1838,7 +1838,7 @@
// the same task as the one that is starting it.
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
+ + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
return START_SUCCESS;
}
@@ -1861,7 +1861,7 @@
|| mLaunchSingleTop || mLaunchSingleTask) {
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
- ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
@@ -1901,7 +1901,7 @@
addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in explicit task " + mStartActivity.task);
+ + " in explicit task " + mStartActivity.getTask());
return START_SUCCESS;
}
@@ -1913,17 +1913,17 @@
mTargetStack.moveToFront("addingToTopTask");
}
final ActivityRecord prev = mTargetStack.topActivity();
- final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
+ final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
mIntent, null, null, true, mStartActivity.mActivityType);
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new guessed " + mStartActivity.task);
+ + " in new guessed " + mStartActivity.getTask());
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
- if (mStartActivity.task == null || mStartActivity.task == parent) {
+ if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
parent.addActivityToTop(mStartActivity);
} else {
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
@@ -1973,7 +1973,7 @@
private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
int launchFlags, ActivityOptions aOptions) {
- final TaskRecord task = r.task;
+ final TaskRecord task = r.getTask();
ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
if (stack != null) {
return stack;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 21c131c..ba72dcf 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -98,6 +98,7 @@
AppErrors(Context context, ActivityManagerService service) {
+ context.assertRuntimeOverlayThemable();
mService = service;
mContext = context;
}
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 5f7f67a..347a357 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -34,6 +34,7 @@
public BaseErrorDialog(Context context) {
super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+ context.assertRuntimeOverlayThemable();
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 27a2461..c7f20b9f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -660,17 +660,6 @@
// we are coming from in WM before we reparent because it became empty.
mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
- // Reset the resumed activity on the previous stack
- if (wasResumed) {
- sourceStack.mResumedActivity = null;
- }
-
- // Reset the paused activity on the previous stack
- if (wasPaused) {
- sourceStack.mPausingActivity = null;
- sourceStack.removeTimeoutsForActivityLocked(r);
- }
-
// Move the task
sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
@@ -1212,14 +1201,13 @@
* be in the current task or unparented to any task.
*/
void addActivityAtIndex(int index, ActivityRecord r) {
- if (r.task != null && r.task != this) {
+ TaskRecord task = r.getTask();
+ if (task != null && task != this) {
throw new IllegalArgumentException("Can not add r=" + " to task=" + this
- + " current parent=" + r.task);
+ + " current parent=" + task);
}
- // TODO(b/36505427): Maybe make task private to ActivityRecord so we can also do
- // onParentChanged() within the setter?
- r.task = this;
- r.onParentChanged();
+
+ r.setTask(this);
// Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
if (!mActivities.remove(r) && r.fullscreen) {
@@ -1274,15 +1262,21 @@
}
/**
- * @return true if this was the last activity in the task
+ * Removes the specified activity from this task.
+ * @param r The {@link ActivityRecord} to remove.
+ * @return true if this was the last activity in the task.
*/
boolean removeActivity(ActivityRecord r) {
- if (r.task != this) {
+ return removeActivity(r, false /*reparenting*/);
+ }
+
+ boolean removeActivity(ActivityRecord r, boolean reparenting) {
+ if (r.getTask() != this) {
throw new IllegalArgumentException(
"Activity=" + r + " does not belong to task=" + this);
}
- r.task = null;
+ r.setTask(null /*task*/, reparenting);
if (mActivities.remove(r) && r.fullscreen) {
// Was previously in list.
@@ -1437,7 +1431,7 @@
TaskThumbnail getTaskThumbnailLocked() {
if (mStack != null) {
final ActivityRecord resumedActivity = mStack.mResumedActivity;
- if (resumedActivity != null && resumedActivity.task == this) {
+ if (resumedActivity != null && resumedActivity.getTask() == this) {
final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
setLastThumbnailLocked(thumbnail);
}
@@ -1619,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) {
@@ -1631,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);
}
@@ -1953,7 +1953,7 @@
task.updateOverrideConfiguration(bounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
- activities.get(activityNdx).task = task;
+ activities.get(activityNdx).setTask(task);
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 70e56b0..c11f531 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -55,6 +55,7 @@
import android.hardware.usb.UsbManager;
import android.media.AudioAttributes;
import android.media.AudioDevicePort;
+import android.media.AudioFocusInfo;
import android.media.AudioSystem;
import android.media.AudioFormat;
import android.media.AudioManager;
@@ -5634,8 +5635,9 @@
clientId, callingPackageName, flags);
}
- public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) {
- return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa);
+ public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
+ String callingPackageName) {
+ return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
}
public void unregisterAudioFocusClient(String clientId) {
@@ -5650,6 +5652,7 @@
return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
}
+ //==========================================================================================
private boolean readCameraSoundForced() {
return SystemProperties.getBoolean("audio.camerasound.force", false) ||
mContext.getResources().getBoolean(
@@ -6430,7 +6433,7 @@
// Audio policy management
//==========================================================================================
public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
- boolean hasFocusListener) {
+ boolean hasFocusListener, boolean isFocusPolicy) {
AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
@@ -6452,7 +6455,8 @@
Slog.e(TAG, "Cannot re-register policy");
return null;
}
- AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener);
+ AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
+ isFocusPolicy);
pcb.asBinder().linkToDeath(app, 0/*flags*/);
regId = app.getRegistrationId();
mAudioPolicies.put(pcb.asBinder(), app);
@@ -6650,15 +6654,21 @@
* is handling ducking for audio focus.
*/
int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
+ boolean mIsFocusPolicy = false;
AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
- boolean hasFocusListener) {
+ boolean hasFocusListener, boolean isFocusPolicy) {
super(config);
setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
mPolicyCallback = token;
mHasFocusListener = hasFocusListener;
if (mHasFocusListener) {
mMediaFocusControl.addFocusFollower(mPolicyCallback);
+ // can only ever be true if there is a focus listener
+ if (isFocusPolicy) {
+ mIsFocusPolicy = true;
+ mMediaFocusControl.setFocusPolicy(mPolicyCallback);
+ }
}
connectMixes();
}
@@ -6676,6 +6686,9 @@
}
void release() {
+ if (mIsFocusPolicy) {
+ mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
+ }
if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
}
@@ -6690,6 +6703,22 @@
}
};
+ //======================
+ // Audio policy: focus
+ //======================
+ /** */
+ public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
+ synchronized (mAudioPolicies) {
+ if (!mAudioPolicies.containsKey(pcb.asBinder())) {
+ throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
+ }
+ return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
+ }
+ }
+
+ //======================
+ // misc
+ //======================
private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
new HashMap<IBinder, AudioPolicyProxy>();
private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 5275c05..bcaa295 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -33,7 +33,7 @@
* @hide
* Class to handle all the information about a user of audio focus. The lifecycle of each
* instance is managed by android.media.MediaFocusControl, from its addition to the audio focus
- * stack to its release.
+ * stack, or the map of focus owners for an external focus policy, to its release.
*/
public class FocusRequester {
@@ -101,6 +101,21 @@
mFocusController = ctlr;
}
+ FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl,
+ IBinder source, AudioFocusDeathHandler hdlr, @NonNull MediaFocusControl ctlr) {
+ mAttributes = afi.getAttributes();
+ mClientId = afi.getClientId();
+ mPackageName = afi.getPackageName();
+ mCallingUid = afi.getClientUid();
+ mFocusGainRequest = afi.getGainRequest();
+ mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
+ mGrantFlags = afi.getFlags();
+
+ mFocusDispatcher = afl;
+ mSourceRef = source;
+ mDeathHandler = hdlr;
+ mFocusController = ctlr;
+ }
boolean hasSameClient(String otherClient) {
try {
@@ -118,6 +133,10 @@
return (mSourceRef != null) && mSourceRef.equals(ib);
}
+ boolean hasSameDispatcher(IAudioFocusDispatcher fd) {
+ return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
+ }
+
boolean hasSamePackage(String pack) {
try {
return mPackageName.compareTo(pack) == 0;
@@ -369,6 +388,35 @@
}
}
+ int dispatchFocusChange(int focusChange) {
+ if (mFocusDispatcher == null) {
+ if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: no focus dispatcher"); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ if (focusChange == AudioManager.AUDIOFOCUS_NONE) {
+ if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: AUDIOFOCUS_NONE"); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ } else if ((focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
+ || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
+ || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
+ || focusChange == AudioManager.AUDIOFOCUS_GAIN)
+ && (mFocusGainRequest != focusChange)){
+ Log.w(TAG, "focus gain was requested with " + mFocusGainRequest
+ + ", dispatching " + focusChange);
+ } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
+ || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
+ || focusChange == AudioManager.AUDIOFOCUS_LOSS) {
+ mFocusLossReceived = focusChange;
+ }
+ try {
+ mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId);
+ } catch (android.os.RemoteException e) {
+ Log.v(TAG, "dispatchFocusChange: error talking to focus listener", e);
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+ }
+
AudioFocusInfo toAudioFocusInfo() {
return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName,
mFocusGainRequest, mFocusLossReceived, mGrantFlags);
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index b3f1548..821e78a 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -16,6 +16,7 @@
package com.android.server.audio;
+import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
import android.media.AudioAttributes;
@@ -23,6 +24,7 @@
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IAudioFocusDispatcher;
+import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.os.Binder;
import android.os.IBinder;
@@ -32,7 +34,10 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.Stack;
import java.text.DateFormat;
@@ -43,6 +48,7 @@
public class MediaFocusControl implements PlayerFocusEnforcer {
private static final String TAG = "MediaFocusControl";
+ static final boolean DEBUG = false;
/**
* set to true so the framework enforces ducking itself, without communicating to apps
@@ -155,6 +161,13 @@
while(stackIterator.hasNext()) {
stackIterator.next().dump(pw);
}
+ pw.println("\n");
+ if (mFocusPolicy == null) {
+ pw.println("No external focus policy\n");
+ } else {
+ pw.println("External focus policy: "+ mFocusPolicy + ", focus owners:\n");
+ dumpExtFocusPolicyFocusOwners(pw);
+ }
}
pw.println("\n");
pw.println(" Notify on duck: " + mNotifyFocusOwnerOnDuck + "\n");
@@ -234,6 +247,31 @@
}
/**
+ * Helper function for external focus policy:
+ * Called synchronized on mAudioFocusLock
+ * Remove focus listeners from the list of potential focus owners for a particular client when
+ * it has died.
+ */
+ private void removeFocusEntryForExtPolicy(IBinder cb) {
+ if (mFocusOwnersForFocusPolicy.isEmpty()) {
+ return;
+ }
+ boolean released = false;
+ final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
+ final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
+ while (ownerIterator.hasNext()) {
+ final Entry<String, FocusRequester> owner = ownerIterator.next();
+ final FocusRequester fr = owner.getValue();
+ if (fr.hasSameBinder(cb)) {
+ ownerIterator.remove();
+ fr.release();
+ notifyExtFocusPolicyFocusAbandon_syncAf(fr.toAudioFocusInfo());
+ break;
+ }
+ }
+ }
+
+ /**
* Helper function:
* Returns true if the system is in a state where the focus can be reevaluated, false otherwise.
* The implementation guarantees that a state where focus cannot be immediately reassigned
@@ -297,7 +335,11 @@
public void binderDied() {
synchronized(mAudioFocusLock) {
- removeFocusStackEntryOnDeath(mCb);
+ if (mFocusPolicy != null) {
+ removeFocusEntryForExtPolicy(mCb);
+ } else {
+ removeFocusStackEntryOnDeath(mCb);
+ }
}
}
}
@@ -353,6 +395,34 @@
}
}
+ private IAudioPolicyCallback mFocusPolicy = null;
+
+ // Since we don't have a stack of focus owners when using an external focus policy, we keep
+ // track of all the focus requesters in this map, with their clientId as the key. This is
+ // used both for focus dispatch and death handling
+ private HashMap<String, FocusRequester> mFocusOwnersForFocusPolicy =
+ new HashMap<String, FocusRequester>();
+
+ void setFocusPolicy(IAudioPolicyCallback policy) {
+ if (policy == null) {
+ return;
+ }
+ synchronized (mAudioFocusLock) {
+ mFocusPolicy = policy;
+ }
+ }
+
+ void unsetFocusPolicy(IAudioPolicyCallback policy) {
+ if (policy == null) {
+ return;
+ }
+ synchronized (mAudioFocusLock) {
+ if (mFocusPolicy == policy) {
+ mFocusPolicy = null;
+ }
+ }
+ }
+
/**
* @param pcb non null
*/
@@ -409,6 +479,100 @@
}
}
+ /**
+ * Called synchronized on mAudioFocusLock
+ * @param afi
+ * @param requestResult
+ * @return true if the external audio focus policy (if any) is handling the focus request
+ */
+ boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi, int requestResult,
+ IAudioFocusDispatcher fd, IBinder cb) {
+ if (mFocusPolicy == null) {
+ return false;
+ }
+ if (DEBUG) {
+ Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId()
+ + " dispatcher=" + fd);
+ }
+ final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+ if (existingFr != null) {
+ if (!existingFr.hasSameDispatcher(fd)) {
+ existingFr.release();
+ final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+ mFocusOwnersForFocusPolicy.put(afi.getClientId(),
+ new FocusRequester(afi, fd, cb, hdlr, this));
+ }
+ } else if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
+ || requestResult == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
+ // new focus (future) focus owner to keep track of
+ final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+ mFocusOwnersForFocusPolicy.put(afi.getClientId(),
+ new FocusRequester(afi, fd, cb, hdlr, this));
+ }
+ try {
+ //oneway
+ mFocusPolicy.notifyAudioFocusRequest(afi, requestResult);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't call notifyAudioFocusRequest() on IAudioPolicyCallback "
+ + mFocusPolicy.asBinder(), e);
+ }
+ return true;
+ }
+
+ /**
+ * Called synchronized on mAudioFocusLock
+ * @param afi
+ * @param requestResult
+ * @return true if the external audio focus policy (if any) is handling the focus request
+ */
+ boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) {
+ if (mFocusPolicy == null) {
+ return false;
+ }
+ final FocusRequester fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId());
+ if (fr != null) {
+ fr.release();
+ }
+ try {
+ //oneway
+ mFocusPolicy.notifyAudioFocusAbandon(afi);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't call notifyAudioFocusAbandon() on IAudioPolicyCallback "
+ + mFocusPolicy.asBinder(), e);
+ }
+ return true;
+ }
+
+ /** see AudioManager.dispatchFocusChange(AudioFocusInfo afi, int focusChange, AudioPolicy ap) */
+ int dispatchFocusChange(AudioFocusInfo afi, int focusChange) {
+ if (DEBUG) {
+ Log.v(TAG, "dispatchFocusChange " + focusChange + " to afi client="
+ + afi.getClientId());
+ }
+ synchronized (mAudioFocusLock) {
+ if (mFocusPolicy == null) {
+ if (DEBUG) { Log.v(TAG, "> failed: no focus policy" ); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ final FocusRequester fr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+ if (fr == null) {
+ if (DEBUG) { Log.v(TAG, "> failed: no such focus requester known" ); }
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ return fr.dispatchFocusChange(focusChange);
+ }
+ }
+
+ private void dumpExtFocusPolicyFocusOwners(PrintWriter pw) {
+ final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
+ final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
+ while (ownerIterator.hasNext()) {
+ final Entry<String, FocusRequester> owner = ownerIterator.next();
+ final FocusRequester fr = owner.getValue();
+ fr.dump(pw);
+ }
+ }
+
protected int getCurrentAudioFocus() {
synchronized(mAudioFocusLock) {
if (mFocusStack.empty()) {
@@ -487,10 +651,23 @@
& (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
if (enteringRingOrCall) { mRingOrCallActive = true; }
+ final AudioFocusInfo afiForExtPolicy;
+ if (mFocusPolicy != null) {
+ // construct AudioFocusInfo as it will be communicated to audio focus policy
+ afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(),
+ clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/,
+ flags);
+ } else {
+ afiForExtPolicy = null;
+ }
+
+ // handle delayed focus
boolean focusGrantDelayed = false;
if (!canReassignAudioFocus()) {
if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
- return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ final int result = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, result, fd, cb);
+ return result;
} else {
// request has AUDIOFOCUS_FLAG_DELAY_OK: focus can't be
// granted right now, so the requester will be inserted in the focus stack
@@ -499,6 +676,14 @@
}
}
+ // external focus policy: delay request for focus gain?
+ final int resultWithExtPolicy = AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
+ if (notifyExtFocusPolicyFocusRequest_syncAf(
+ afiForExtPolicy, resultWithExtPolicy, fd, cb)) {
+ // stop handling focus request here as it is handled by external audio focus policy
+ return resultWithExtPolicy;
+ }
+
// handle the potential premature death of the new holder of the focus
// (premature death == death before abandoning focus)
// Register for client death notification
@@ -569,7 +754,8 @@
/**
* @see AudioManager#abandonAudioFocus(AudioManager.OnAudioFocusChangeListener, AudioAttributes)
* */
- protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa) {
+ protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa,
+ String callingPackageName) {
// AudioAttributes are currently ignored, to be used for zones
Log.i(TAG, " AudioFocus abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
@@ -577,6 +763,16 @@
try {
// this will take care of notifying the new focus owner if needed
synchronized(mAudioFocusLock) {
+ // external focus policy?
+ if (mFocusPolicy != null) {
+ final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(),
+ clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/,
+ 0 /*flags*/);
+ if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) {
+ return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+ }
+ }
+
boolean exitingRingOrCall = mRingOrCallActive
& (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
if (exitingRingOrCall) { mRingOrCallActive = false; }
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 82a0ff6..51aa4f8 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -103,6 +103,13 @@
apc.init();
synchronized(mPlayerLock) {
mPlayers.put(newPiid, apc);
+ if (mDuckedUids.contains(new Integer(apc.getClientUid()))) {
+ if (DEBUG) { Log.v(TAG, " > trackPlayer() piid=" + newPiid + " must be ducked"); }
+ mDuckedPlayers.add(new Integer(newPiid));
+ // FIXME here the player needs to be put in a state that is the same as if it
+ // had been ducked as it starts. At the moment, this works already for linked
+ // players, as is the case in gapless playback.
+ }
}
return newPiid;
}
@@ -141,6 +148,13 @@
Log.e(TAG, "Error handling event " + event);
change = false;
}
+ if (change && event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
+ && mDuckedUids.contains(new Integer(apc.getClientUid()))) {
+ if (DEBUG) { Log.v(TAG, " > playerEvent() piid=" + piid + " must be ducked"); }
+ if (!mDuckedPlayers.contains(new Integer(piid))) {
+ mDuckedPlayers.add(new Integer(piid));
+ }
+ }
}
if (change) {
dispatchPlaybackChange();
@@ -273,13 +287,20 @@
// PlayerFocusEnforcer implementation
private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
+ // size of 2 for typical cases of double-ducking, not expected to grow beyond that, but can
+ private final ArrayList<Integer> mDuckedUids = new ArrayList<Integer>(2);
@Override
public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
if (DEBUG) {
Log.v(TAG, String.format("duckPlayers: uids winner=%d loser=%d",
- winner.getClientUid(), loser.getClientUid())); }
+ winner.getClientUid(), loser.getClientUid()));
+ }
synchronized (mPlayerLock) {
+ final Integer loserUid = new Integer(loser.getClientUid());
+ if (!mDuckedUids.contains(loserUid)) {
+ mDuckedUids.add(loserUid);
+ }
if (mPlayers.isEmpty()) {
return true;
}
@@ -296,7 +317,7 @@
&& loser.hasSameUid(apc.getClientUid())
&& apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED)
{
- if (mDuckedPlayers.contains(piid)) {
+ if (mDuckedPlayers.contains(new Integer(piid))) {
if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); }
} else if (apc.getAudioAttributes().getContentType() ==
AudioAttributes.CONTENT_TYPE_SPEECH) {
@@ -313,7 +334,7 @@
apc.getPlayerProxy().applyVolumeShaper(
DUCK_VSHAPE,
PLAY_CREATE_IF_NEEDED);
- mDuckedPlayers.add(piid);
+ mDuckedPlayers.add(new Integer(piid));
} catch (Exception e) {
Log.e(TAG, "Error ducking player " + piid, e);
// something went wrong trying to duck, so let the app handle it
@@ -332,25 +353,36 @@
if (DEBUG) { Log.v(TAG, "unduckPlayers: uids winner=" + winner.getClientUid()); }
synchronized (mPlayerLock) {
if (mDuckedPlayers.isEmpty()) {
+ mDuckedUids.remove(new Integer(winner.getClientUid()));
return;
}
+ final ArrayList<Integer> playersToRemove =
+ new ArrayList<Integer>(mDuckedPlayers.size());
for (int piid : mDuckedPlayers) {
final AudioPlaybackConfiguration apc = mPlayers.get(piid);
- if (apc != null
- && winner.hasSameUid(apc.getClientUid())) {
- try {
- Log.v(TAG, "unducking player" + piid);
- mDuckedPlayers.remove(new Integer(piid));
- apc.getPlayerProxy().applyVolumeShaper(
- DUCK_ID,
- VolumeShaper.Operation.REVERSE);
- } catch (Exception e) {
- Log.e(TAG, "Error unducking player " + piid, e);
+ if (apc != null) {
+ if (winner.hasSameUid(apc.getClientUid())) {
+ try {
+ Log.v(TAG, "unducking player " + piid);
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_ID,
+ VolumeShaper.Operation.REVERSE);
+ } catch (Exception e) {
+ Log.e(TAG, "Error unducking player " + piid, e);
+ } finally {
+ playersToRemove.add(piid);
+ }
}
} else {
- Log.e(TAG, "Error unducking player " + piid + ", player not found");
+ // this piid was in the list of ducked players, but wasn't found, discard it
+ Log.v(TAG, "Error unducking player " + piid + ", player not found");
+ playersToRemove.add(piid);
}
}
+ for (int piid : playersToRemove) {
+ mDuckedPlayers.remove(new Integer(piid));
+ }
+ mDuckedUids.remove(new Integer(winner.getClientUid()));
}
}
@@ -383,7 +415,7 @@
try {
Log.v(TAG, "call: muting player" + piid);
apc.getPlayerProxy().setVolume(0.0f);
- mMutedPlayers.add(piid);
+ mMutedPlayers.add(new Integer(piid));
} catch (Exception e) {
Log.e(TAG, "call: error muting player " + piid, e);
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a1a7437..ddd918f 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -339,6 +339,18 @@
}
}
+ /**
+ * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
+ */
+ private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
+ synchronized (mSyncRoot) {
+ final LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ display.getNonOverrideDisplayInfoLocked(outInfo);
+ }
+ }
+ }
+
private void performTraversalInTransactionFromWindowManagerInternal() {
synchronized (mSyncRoot) {
if (!mPendingTraversal) {
@@ -1663,6 +1675,11 @@
}
@Override
+ public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
+ getNonOverrideDisplayInfoInternal(displayId, outInfo);
+ }
+
+ @Override
public void performTraversalInTransactionFromWindowManager() {
performTraversalInTransactionFromWindowManagerInternal();
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index a947b41..addad0b 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import android.graphics.Rect;
+import android.hardware.display.DisplayManagerInternal;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -62,7 +63,18 @@
private final int mDisplayId;
private final int mLayerStack;
- private DisplayInfo mOverrideDisplayInfo; // set by the window manager
+ /**
+ * Override information set by the window manager. Will be reported instead of {@link #mInfo}
+ * if not null.
+ * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
+ * @see #getDisplayInfoLocked()
+ */
+ private DisplayInfo mOverrideDisplayInfo;
+ /**
+ * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
+ * needs to be updated.
+ * @see #getDisplayInfoLocked()
+ */
private DisplayInfo mInfo;
// The display device that this logical display is based on and which
@@ -142,6 +154,13 @@
}
/**
+ * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
+ */
+ void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) {
+ outInfo.copyFrom(mBaseDisplayInfo);
+ }
+
+ /**
* Sets overridden logical display information from the window manager.
* This method can be used to adjust application insets, rotation, and other
* properties that the window manager takes care of.
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 0a6d8a4..8ad1bea 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -345,6 +345,7 @@
public void notePending(JobStatus job) {
final long now = SystemClock.uptimeMillis();
+ job.madePending = now;
rebatchIfNeeded(now);
mCurDataSet.incPending(job.getSourceUid(), job.getSourcePackageName(), now);
}
@@ -357,6 +358,7 @@
public void noteActive(JobStatus job) {
final long now = SystemClock.uptimeMillis();
+ job.madeActive = now;
rebatchIfNeeded(now);
if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 7c231ff..cd3ba4c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2035,27 +2035,35 @@
pw.print(" Evaluated priority: "); pw.println(priority);
}
pw.print(" Tag: "); pw.println(job.getTag());
+ pw.print(" Enq: ");
+ TimeUtils.formatDuration(now - job.madePending, pw);
+ pw.println(" ago");
}
pw.println();
pw.println("Active jobs:");
for (int i=0; i<mActiveServices.size(); i++) {
JobServiceContext jsc = mActiveServices.get(i);
pw.print(" Slot #"); pw.print(i); pw.print(": ");
- if (jsc.getRunningJob() == null) {
+ final JobStatus job = jsc.getRunningJob();
+ if (job == null) {
pw.println("inactive");
continue;
} else {
- pw.println(jsc.getRunningJob().toShortString());
+ pw.println(job.toShortString());
pw.print(" Running for: ");
TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
pw.print(", timeout at: ");
TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
pw.println();
- jsc.getRunningJob().dump(pw, " ", false);
+ job.dump(pw, " ", false);
int priority = evaluateJobPriorityLocked(jsc.getRunningJob());
if (priority != JobInfo.PRIORITY_DEFAULT) {
pw.print(" Evaluated priority: "); pw.println(priority);
}
+ pw.print(" Active at "); pw.println(job.madeActive);
+ pw.print(" Pending for ");
+ TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
+ pw.println();
}
}
if (filterUid == -1) {
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index f41e187..0e04d24 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -147,7 +147,6 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
-
if (action.equals(Intent.ACTION_SCREEN_ON)
|| action.equals(Intent.ACTION_DREAMING_STOPPED)) {
if (DEBUG) {
@@ -183,6 +182,11 @@
}
mIdle = true;
reportNewIdleState(mIdle);
+ } else {
+ if (DEBUG) {
+ Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
+ + mIdle + " screen=" + mScreenOn);
+ }
}
}
}
@@ -191,7 +195,7 @@
@Override
public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
pw.print("Idle: ");
- pw.println(mIdleTracker.isIdle() ? "true" : "false");
+ pw.println(mIdleTracker.isIdle());
pw.print("Tracking ");
pw.print(mTrackedTasks.size());
pw.println(":");
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 47630d0..d27d0e5 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -129,6 +129,10 @@
// Used by shell commands
public int overrideState = 0;
+ // Metrics about queue latency
+ public long madePending;
+ public long madeActive;
+
/**
* For use only by ContentObserverController: state it is maintaining about content URIs
* being observed.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 9e4432d..dc2ebb4 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -27,4 +27,15 @@
* Resets all policies associated with a given user.
*/
public abstract void resetUserState(int userId);
+
+ /**
+ * @return true if the given uid is restricted from doing networking on metered networks.
+ */
+ public abstract boolean isUidRestrictedOnMeteredNetworks(int uid);
+
+ /**
+ * @return true if networking is blocked on the given interface for the given uid according
+ * to current networking policies.
+ */
+ public abstract boolean isUidNetworkingBlocked(int uid, String ifname);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 4e1166b..02e106e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -248,8 +248,8 @@
*/
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
static final String TAG = "NetworkPolicy";
- private static final boolean LOGD = false;
- private static final boolean LOGV = false;
+ private static final boolean LOGD = true; // UNDO
+ private static final boolean LOGV = true; // UNDO
private static final int VERSION_INIT = 1;
private static final int VERSION_ADDED_SNOOZE = 2;
@@ -428,9 +428,6 @@
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidState = new SparseIntArray();
- /** Higher priority listener before general event dispatch */
- private INetworkPolicyListener mConnectivityListener;
-
private final RemoteCallbackList<INetworkPolicyListener>
mListeners = new RemoteCallbackList<>();
@@ -2237,15 +2234,6 @@
}
@Override
- public void setConnectivityListener(INetworkPolicyListener listener) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- if (mConnectivityListener != null) {
- throw new IllegalStateException("Connectivity listener already registered");
- }
- mConnectivityListener = listener;
- }
-
- @Override
public void registerListener(INetworkPolicyListener listener) {
// TODO: create permission for observing network policy
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -3556,7 +3544,6 @@
case MSG_RULES_CHANGED: {
final int uid = msg.arg1;
final int uidRules = msg.arg2;
- dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3567,7 +3554,6 @@
}
case MSG_METERED_IFACES_CHANGED: {
final String[] meteredIfaces = (String[]) msg.obj;
- dispatchMeteredIfacesChanged(mConnectivityListener, meteredIfaces);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3598,7 +3584,6 @@
}
case MSG_RESTRICT_BACKGROUND_CHANGED: {
final boolean restrictBackground = msg.arg1 != 0;
- dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3616,7 +3601,6 @@
final int policy = msg.arg2;
final Boolean notifyApp = (Boolean) msg.obj;
// First notify internal listeners...
- dispatchUidPoliciesChanged(mConnectivityListener, uid, policy);
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -4049,6 +4033,74 @@
}
}
}
+
+ /**
+ * @return true if the given uid is restricted from doing networking on metered networks.
+ */
+ @Override
+ public boolean isUidRestrictedOnMeteredNetworks(int uid) {
+ final int uidRules;
+ final boolean isBackgroundRestricted;
+ synchronized (mUidRulesFirstLock) {
+ uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+ isBackgroundRestricted = mRestrictBackground;
+ }
+ return isBackgroundRestricted
+ && !hasRule(uidRules, RULE_ALLOW_METERED)
+ && !hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED);
+ }
+
+ /**
+ * @return true if networking is blocked on the given interface for the given uid according
+ * to current networking policies.
+ */
+ @Override
+ public boolean isUidNetworkingBlocked(int uid, String ifname) {
+ final int uidRules;
+ final boolean isBackgroundRestricted;
+ final boolean isNetworkMetered;
+ synchronized (mUidRulesFirstLock) {
+ uidRules = mUidRules.get(uid, RULE_NONE);
+ isBackgroundRestricted = mRestrictBackground;
+ synchronized (mNetworkPoliciesSecondLock) {
+ isNetworkMetered = mMeteredIfaces.contains(ifname);
+ }
+ }
+ if (hasRule(uidRules, RULE_REJECT_ALL)) {
+ if (LOGV) logUidStatus(uid, "blocked by power restrictions");
+ return true;
+ }
+ if (!isNetworkMetered) {
+ if (LOGV) logUidStatus(uid, "allowed on unmetered network");
+ return false;
+ }
+ if (hasRule(uidRules, RULE_REJECT_METERED)) {
+ if (LOGV) logUidStatus(uid, "blacklisted on metered network");
+ return true;
+ }
+ if (hasRule(uidRules, RULE_ALLOW_METERED)) {
+ if (LOGV) logUidStatus(uid, "whitelisted on metered network");
+ return false;
+ }
+ if (hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED)) {
+ if (LOGV) logUidStatus(uid, "temporary whitelisted on metered network");
+ return false;
+ }
+ if (isBackgroundRestricted) {
+ if (LOGV) logUidStatus(uid, "blocked when background is restricted");
+ return true;
+ }
+ if (LOGV) logUidStatus(uid, "allowed by default");
+ return false;
+ }
+ }
+
+ private static boolean hasRule(int uidRules, int rule) {
+ return (uidRules & rule) != 0;
+ }
+
+ private static void logUidStatus(int uid, String descr) {
+ Slog.d(TAG, String.format("uid %d is %s", uid, descr));
}
/**
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 5bdef9e..3705946 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -325,13 +325,11 @@
// Disable all other overlays.
allOverlays.remove(oi);
for (int i = 0; i < allOverlays.size(); i++) {
- mSettings.setEnabled(allOverlays.get(i).packageName, userId, false);
+ // TODO: Optimize this to only send updates after all changes.
+ setEnabled(allOverlays.get(i).packageName, false, userId);
}
- final PackageInfo targetPackage =
- mPackageManager.getPackageInfo(oi.targetPackageName, userId);
- mSettings.setEnabled(packageName, userId, enable);
- updateState(targetPackage, overlayPackage, userId);
+ setEnabled(packageName, enable, userId);
return true;
} catch (OverlayManagerSettings.BadKeyException e) {
return false;
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index b0730ef..f6e96b2 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -47,7 +48,7 @@
* service and handling all interactions in a timely manner.
* @hide
*/
-final class EphemeralResolverConnection {
+final class EphemeralResolverConnection implements DeathRecipient {
// This is running in a critical section and the timeout must be sufficiently low
private static final long BIND_SERVICE_TIMEOUT_MS =
("eng".equals(Build.TYPE)) ? 300 : 200;
@@ -65,7 +66,7 @@
public EphemeralResolverConnection(Context context, ComponentName componentName) {
mContext = context;
- mIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE).setComponent(componentName);
+ mIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE).setComponent(componentName);
}
public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[],
@@ -171,6 +172,15 @@
}
}
+ @Override
+ public void binderDied() {
+ if (mRemoteInstance != null) {
+ mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ }
+ mRemoteInstance = null;
+ mBindRequested = false;
+ }
+
/**
* Asynchronous callback when results come back from ephemeral resolution phase two.
*/
@@ -183,7 +193,11 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
- mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
+ try {
+ service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/);
+ mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
+ } catch (RemoteException e) {
+ }
mLock.notifyAll();
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 7eef7ad..9f7c4a2 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -66,6 +66,7 @@
public static final int FLAG_FREE_CACHE_V2 = 1 << 13;
public static final int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
public static final int FLAG_FREE_CACHE_NOOP = 1 << 15;
+ public static final int FLAG_FORCE = 1 << 16;
private final boolean mIsolated;
@@ -202,6 +203,15 @@
}
}
+ public void fixupAppData(String uuid, int flags) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.fixupAppData(uuid, flags);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
String dataAppName, int appId, String seInfo, int targetSdkVersion)
throws InstallerException {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 0b40fc5..f79f6f4 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -242,18 +242,8 @@
try {
UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
if (callingUserInfo.isManagedProfile()) {
-
- // STOPSHIP Remove the whitelist.
- if ("com.google.android.talk".equals(callingPackage)
- || "com.google.android.quicksearchbox".equals(callingPackage)
- || "com.google.android.googlequicksearchbox".equals(callingPackage)
- ) {
- return false;
- }
- // STOPSHIP Change it to 'e'.
- Slog.wtfStack(TAG, message + " by " + callingPackage + " for another profile "
+ Slog.w(TAG, message + " by " + callingPackage + " for another profile "
+ targetUserId + " from " + callingUserId);
-
return false;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 365a8e8..d5c4fb9 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();
@@ -2385,6 +2385,10 @@
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
+ if (mIsUpgrade) {
+ logCriticalInfo(Log.INFO,
+ "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
+ }
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
@@ -2713,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;
}
@@ -2803,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
@@ -3041,10 +3056,18 @@
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
- final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
+ final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE);
+ List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
-
+ // temporarily look for the old action
+ if (resolvers.size() == 0) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral resolver not found with new action; try old one");
+ }
+ resolverIntent.setAction(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
+ resolvers = queryIntentServicesInternal(resolverIntent, null,
+ resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
+ }
final int N = resolvers.size();
if (N == 0) {
if (DEBUG_EPHEMERAL) {
@@ -3083,7 +3106,7 @@
}
private @Nullable ActivityInfo getEphemeralInstallerLPr() {
- final Intent intent = new Intent(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+ final Intent intent = new Intent(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
@@ -3091,8 +3114,17 @@
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+ List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
resolveFlags, UserHandle.USER_SYSTEM);
+ // temporarily look for the old action
+ if (matches.isEmpty()) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral installer not found with new action; try old one");
+ }
+ intent.setAction(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+ matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+ resolveFlags, UserHandle.USER_SYSTEM);
+ }
Iterator<ResolveInfo> iter = matches.iterator();
while (iter.hasNext()) {
final ResolveInfo rInfo = iter.next();
@@ -3115,35 +3147,27 @@
}
}
- private @Nullable ComponentName getEphemeralResolverSettingsLPr() {
- final Intent intent = new Intent(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- final int resolveFlags =
- MATCH_DIRECT_BOOT_AWARE
- | MATCH_DIRECT_BOOT_UNAWARE
- | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
- resolveFlags, UserHandle.USER_SYSTEM);
- Iterator<ResolveInfo> iter = matches.iterator();
- while (iter.hasNext()) {
- final ResolveInfo rInfo = iter.next();
- final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
- if (ps != null) {
- final PermissionsState permissionsState = ps.getPermissionsState();
- if (permissionsState.hasPermission(Manifest.permission.ACCESS_INSTANT_APPS, 0)) {
- continue;
- }
+ private @Nullable ComponentName getEphemeralResolverSettingsLPr(
+ @NonNull ComponentName resolver) {
+ final Intent intent = new Intent(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .setPackage(resolver.getPackageName());
+ final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+ List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+ UserHandle.USER_SYSTEM);
+ // temporarily look for the old action
+ if (matches.isEmpty()) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral resolver settings not found with new action; try old one");
}
- iter.remove();
+ intent.setAction(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
+ matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+ UserHandle.USER_SYSTEM);
}
- if (matches.size() == 0) {
+ if (matches.isEmpty()) {
return null;
- } else if (matches.size() == 1) {
- return matches.get(0).getComponentInfo().getComponentName();
- } else {
- throw new RuntimeException(
- "There must be at most one ephemeral resolver settings; found " + matches);
}
+ return matches.get(0).getComponentInfo().getComponentName();
}
private void primeDomainVerificationsLPw(int userId) {
@@ -16961,6 +16985,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.
@@ -17009,6 +17042,7 @@
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
+
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
@@ -17635,6 +17669,7 @@
int removedAppId = -1;
int[] origUsers;
int[] removedUsers = null;
+ int[] broadcastUsers = null;
SparseArray<Integer> installReasons;
boolean isRemovedPackageSystemUpdate = false;
boolean isUpdate;
@@ -17708,16 +17743,16 @@
extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
if (removedPackage != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, 0, null, null, removedUsers);
+ extras, 0, null, null, broadcastUsers);
if (dataRemoved && !isRemovedPackageSystemUpdate) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, removedUsers);
+ null, null, broadcastUsers);
}
}
if (removedAppId >= 0) {
sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, 0, null, null,
- removedUsers);
+ broadcastUsers);
}
}
}
@@ -17746,6 +17781,20 @@
outInfo.removedUsers = deletedPs != null
? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
: null;
+ if (outInfo.removedUsers == null) {
+ outInfo.broadcastUsers = null;
+ } else {
+ outInfo.broadcastUsers = EMPTY_INT_ARRAY;
+ int[] allUsers = outInfo.removedUsers;
+ for (int i = allUsers.length - 1; i >= 0; --i) {
+ final int userId = allUsers[i];
+ if (deletedPs.getInstantApp(userId)) {
+ continue;
+ }
+ outInfo.broadcastUsers =
+ ArrayUtils.appendInt(outInfo.broadcastUsers, userId);
+ }
+ }
}
}
@@ -20854,13 +20903,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.
@@ -20931,6 +20973,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/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9c4e700..a60dae7 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2671,11 +2671,11 @@
public void run() {
synchronized (this) {
if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
- ShutdownThread.rebootSafeMode(mContext, confirm);
+ ShutdownThread.rebootSafeMode(getUiContext(), confirm);
} else if (haltMode == HALT_MODE_REBOOT) {
- ShutdownThread.reboot(mContext, reason, confirm);
+ ShutdownThread.reboot(getUiContext(), reason, confirm);
} else {
- ShutdownThread.shutdown(mContext, reason, confirm);
+ ShutdownThread.shutdown(getUiContext(), reason, confirm);
}
}
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 841e2a1..864e83e 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -79,7 +79,7 @@
private static final int SHUTDOWN_VIBRATE_MS = 500;
// state tracking
- private static Object sIsStartedGuard = new Object();
+ private static final Object sIsStartedGuard = new Object();
private static boolean sIsStarted = false;
private static boolean mReboot;
@@ -121,7 +121,8 @@
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
- * @param context Context used to display the shutdown progress dialog.
+ * @param context Context used to display the shutdown progress dialog. This must be a context
+ * suitable for displaying UI (aka Themable).
* @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
@@ -132,7 +133,11 @@
shutdownInner(context, confirm);
}
- static void shutdownInner(final Context context, boolean confirm) {
+ private static void shutdownInner(final Context context, boolean confirm) {
+ // ShutdownThread is called from many places, so best to verify here that the context passed
+ // in is themed.
+ context.assertRuntimeOverlayThemable();
+
// ensure that only one thread is trying to power down.
// any additional calls are just returned
synchronized (sIsStartedGuard) {
@@ -204,7 +209,8 @@
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
- * @param context Context used to display the shutdown progress dialog.
+ * @param context Context used to display the shutdown progress dialog. This must be a context
+ * suitable for displaying UI (aka Themable).
* @param reason code to pass to the kernel (e.g. "recovery"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
@@ -220,7 +226,8 @@
* Request a reboot into safe mode. Must be called from a Looper thread in which its UI
* is shown.
*
- * @param context Context used to display the shutdown progress dialog.
+ * @param context Context used to display the shutdown progress dialog. This must be a context
+ * suitable for displaying UI (aka Themable).
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void rebootSafeMode(final Context context, boolean confirm) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 212bd61..32871bb 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.statusbar;
+import android.app.ActivityThread;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
@@ -61,6 +62,7 @@
private static final boolean SPEW = false;
private final Context mContext;
+
private final WindowManagerService mWindowManager;
private Handler mHandler = new Handler();
private NotificationDelegate mNotificationDelegate;
@@ -761,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);
}
@@ -777,10 +781,12 @@
long identity = Binder.clearCallingIdentity();
try {
mHandler.post(() -> {
+ // ShutdownThread displays UI, so give it a UI context.
if (safeMode) {
- ShutdownThread.rebootSafeMode(mContext, false);
+ ShutdownThread.rebootSafeMode(getUiContext(), false);
} else {
- ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, false);
+ ShutdownThread.reboot(getUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, false);
}
});
} finally {
@@ -1014,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 3c68e4f..4ebf1fc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -180,11 +180,23 @@
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
+ // Initial display metrics.
int mInitialDisplayWidth = 0;
int mInitialDisplayHeight = 0;
int mInitialDisplayDensity = 0;
+
+ /**
+ * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
+ * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
+ * @see WindowManagerService#setForcedDisplaySize(int, int, int)
+ */
int mBaseDisplayWidth = 0;
int mBaseDisplayHeight = 0;
+ /**
+ * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
+ * but can be set from Settings or via shell command "adb shell wm density".
+ * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
+ */
int mBaseDisplayDensity = 0;
boolean mDisplayScalingDisabled;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -1497,8 +1509,12 @@
}
void updateDisplayInfo() {
+ // Check if display metrics changed and update base values if needed.
+ updateBaseDisplayMetricsIfNeeded();
+
mDisplay.getDisplayInfo(mDisplayInfo);
mDisplay.getMetrics(mDisplayMetrics);
+
for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
mTaskStackContainers.get(i).updateDisplayInfo(null);
}
@@ -1514,10 +1530,11 @@
}
}
- mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
- mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
- mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
- mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+ updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
+ mDisplayInfo.logicalDensityDpi);
+ mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+ mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+ mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
}
void getLogicalDisplayRect(Rect out) {
@@ -1547,6 +1564,42 @@
}
}
+ /**
+ * If display metrics changed, overrides are not set and it's not just a rotation - update base
+ * values.
+ */
+ private void updateBaseDisplayMetricsIfNeeded() {
+ // Get real display metrics without overrides from WM.
+ mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
+ final int orientation = mDisplayInfo.rotation;
+ final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+ final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
+ final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
+ final int newDensity = mDisplayInfo.logicalDensityDpi;
+
+ final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
+ || mInitialDisplayHeight != newHeight
+ || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi;
+
+ if (displayMetricsChanged) {
+ // Check if display size or density is forced.
+ final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
+ || mBaseDisplayHeight != mInitialDisplayHeight;
+ final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity;
+
+ // If there is an override set for base values - use it, otherwise use new values.
+ updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth,
+ isDisplaySizeForced ? mBaseDisplayHeight : newHeight,
+ isDisplayDensityForced ? mBaseDisplayDensity : newDensity);
+
+ // Real display metrics changed, so we should also update initial values.
+ mInitialDisplayWidth = newWidth;
+ mInitialDisplayHeight = newHeight;
+ mInitialDisplayDensity = newDensity;
+ mService.reconfigureDisplayLocked(this);
+ }
+ }
+
/** Sets the maximum width the screen resolution can be */
void setMaxUiWidth(int width) {
if (DEBUG_DISPLAY) {
@@ -2867,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%
rename from core/java/com/android/internal/font/IFontManager.aidl
rename 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 95fbbb8..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;
@@ -102,6 +110,7 @@
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.content.BroadcastReceiver;
@@ -124,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;
@@ -138,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;
@@ -150,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;
@@ -214,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;
@@ -238,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 {
@@ -407,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,
@@ -847,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) {
@@ -935,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;
@@ -1580,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");
}
@@ -1592,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) {
@@ -1607,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.");
}
@@ -2263,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;
}
@@ -2916,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;
}
@@ -3196,19 +3211,25 @@
// Called by window manager policy. Not exposed externally.
@Override
public void shutdown(boolean confirm) {
- ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+ // Pass in the UI context, since ShutdownThread requires it (to show UI).
+ ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}
// Called by window manager policy. Not exposed externally.
@Override
public void reboot(boolean confirm) {
- ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+ // Pass in the UI context, since ShutdownThread requires it (to show UI).
+ ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}
// Called by window manager policy. Not exposed externally.
@Override
public void rebootSafeMode(boolean confirm) {
- ShutdownThread.rebootSafeMode(mContext, confirm);
+ // Pass in the UI context, since ShutdownThread requires it (to show UI).
+ ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
+ confirm);
}
public void setCurrentProfileIds(final int[] currentProfileIds) {
@@ -5312,8 +5333,8 @@
if (displayContent.mBaseDisplayWidth != width
|| displayContent.mBaseDisplayHeight != height) {
Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
- displayContent.mBaseDisplayWidth = width;
- displayContent.mBaseDisplayHeight = height;
+ displayContent.updateBaseDisplayMetrics(width, height,
+ displayContent.mBaseDisplayDensity);
}
} catch (NumberFormatException ex) {
}
@@ -5338,8 +5359,7 @@
// displayContent must not be null
private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
- displayContent.mBaseDisplayWidth = width;
- displayContent.mBaseDisplayHeight = height;
+ displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
reconfigureDisplayLocked(displayContent);
}
@@ -7052,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 da49eb3..a5eac46 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -475,6 +475,9 @@
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
+
+ final Context systemUiContext = activityThread.getSystemUiContext();
+ systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
/**
@@ -1014,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/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index aa37407..5d0c23f 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -149,7 +149,7 @@
// 2nd account
Account account2 = new Account("name", "example2.com");
long accId2 = mAccountsDb.insertCeAccount(account2, "password");
- mAccountsDb.insertDeAccount(account2, accId);
+ mAccountsDb.insertDeAccount(account2, accId2);
mAccountsDb.insertAuthToken(accId2, "type", "token");
mAccountsDb.deleteAuthTokensByAccountId(accId2);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
new file mode 100644
index 0000000..54ecab3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link ActivityRecord} class.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityRecordTests extends ActivityTestsBase {
+ private final ComponentName testActivityComponent =
+ ComponentName.unflattenFromString("com.foo/.BarActivity");
+ @Test
+ public void testStackCleanupOnClearingTask() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ record.setTask(null);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ }
+
+ @Test
+ public void testStackCleanupOnActivityRemoval() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ task.removeActivity(record);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ }
+
+ @Test
+ public void testStackCleanupOnTaskRemoval() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ testStack.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+ }
+
+ @Test
+ public void testNoCleanupMovingActivityInSameStack() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord oldTask = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
+ final TaskRecord newTask = createTask(service, testActivityComponent, testStack);
+
+ record.reparent(newTask, 0, null /*reason*/);
+ assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
new file mode 100644
index 0000000..b59c2bc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertNull;
+
+import android.os.Debug;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+
+/**
+ * Tests for the {@link ActivityStackSupervisor} class.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityStackSupervisorTests extends ActivityTestsBase {
+ /**
+ * This test ensures that we do not try to restore a task based off an invalid task id. The
+ * stack supervisor is a test version so there will be no tasks present. We should expect
+ * {@code null} to be returned in this case.
+ */
+ @Test
+ public void testRestoringInvalidTask() throws Exception {
+ Debug.waitForDebugger();
+ final ActivityManagerService service = createActivityManagerService();
+ TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
+ assertNull(task);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
new file mode 100644
index 0000000..5240586
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import com.android.server.AttributeCache;
+import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.StackWindowController;
+
+import com.android.server.wm.WindowManagerService;
+import com.android.server.wm.WindowTestUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * A base class to handle common operations in activity related unit tests.
+ */
+public class ActivityTestsBase {
+ private final Context mContext = InstrumentationRegistry.getContext();
+ private HandlerThread mHandlerThread;
+
+ // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
+ // be called at before any tests.
+ private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
+ mHandlerThread.start();
+ }
+
+ @After
+ public void tearDown() {
+ mHandlerThread.quitSafely();
+ }
+
+ protected ActivityManagerService createActivityManagerService() {
+ return new TestActivityManagerService(mContext);
+ }
+
+ protected static TestActivityStack createActivityStack(ActivityManagerService service,
+ int stackId, int displayId, boolean onTop) {
+ if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
+ final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
+ .createTestStack(stackId, onTop);
+ return stack;
+ }
+
+ return null;
+ }
+
+ protected static ActivityRecord createActivity(ActivityManagerService service,
+ ComponentName component, TaskRecord task) {
+ Intent intent = new Intent();
+ intent.setComponent(component);
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = component.getPackageName();
+ AttributeCache.init(service.mContext);
+ final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
+ 0 /* launchedFromPid */, 0, null, intent, null,
+ aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
+ 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
+ service.mStackSupervisor, null /* container */, null /* options */,
+ null /* sourceRecord */);
+ activity.mWindowContainerController = mock(AppWindowContainerController.class);
+
+ if (task != null) {
+ task.addActivityToTop(activity);
+ }
+
+ return activity;
+ }
+
+ protected static TaskRecord createTask(ActivityManagerService service,
+ ComponentName component, ActivityStack stack) {
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = component.getPackageName();
+
+ Intent intent = new Intent();
+ intent.setComponent(component);
+
+ final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
+ null /*_taskDescription*/, null /*thumbnailInfo*/);
+ stack.addTask(task, true, "creating test task");
+ task.setStack(stack);
+ task.createWindowContainer(true, true);
+
+ return task;
+ }
+
+ /**
+ * An {@link ActivityManagerService} subclass which provides a test
+ * {@link ActivityStackSupervisor}.
+ */
+ protected static class TestActivityManagerService extends ActivityManagerService {
+ public TestActivityManagerService(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected ActivityStackSupervisor createStackSupervisor() {
+ return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
+ }
+ }
+
+ /**
+ * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
+ * setup not available in the test environment. Also specifies an injector for
+ */
+ protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
+ public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+ super(service, looper);
+ }
+
+ // Invoked during {@link ActivityStack} creation.
+ @Override
+ void updateUIDsPresentOnDisplay() {
+ }
+
+ public TestActivityStack createTestStack(int stackId, boolean onTop) {
+ final ActivityDisplay display = new ActivityDisplay();
+ final TestActivityContainer container =
+ new TestActivityContainer(stackId, display, onTop);
+ return container.getStack();
+ }
+
+ private class TestActivityContainer extends ActivityContainer {
+ private TestActivityStack mStack;
+ TestActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) {
+ super(stackId, activityDisplay, onTop);
+ }
+
+ @Override
+ protected void createStack(int stackId, boolean onTop) {
+ mStack = new TestActivityStack(this, null /*recentTasks*/, onTop);
+ }
+
+ public TestActivityStack getStack() {
+ return mStack;
+ }
+ }
+ }
+
+ /**
+ * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
+ * method is called. Note that its functionality depends on the implementations of the
+ * construction arguments.
+ */
+ protected static class TestActivityStack<T extends StackWindowController>
+ extends ActivityStack<T> {
+ private int mOnActivityRemovedFromStackCount = 0;
+ private T mContainerController;
+ TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
+ RecentTasks recentTasks, boolean onTop) {
+ super(activityContainer, recentTasks, onTop);
+ }
+
+ @Override
+ void onActivityRemovedFromStack(ActivityRecord r) {
+ mOnActivityRemovedFromStackCount++;
+ super.onActivityRemovedFromStack(r);
+ }
+
+ // Returns the number of times {@link #onActivityRemovedFromStack} has been called
+ public int onActivityRemovedFromStackInvocationCount() {
+ return mOnActivityRemovedFromStackCount;
+ }
+
+ @Override
+ protected T createStackWindowController(int displayId, boolean onTop,
+ Rect outBounds) {
+ mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
+ return mContainerController;
+ }
+
+ @Override
+ T getWindowContainerController() {
+ return mContainerController;
+ }
+ }
+
+ protected static class ActivityStackBuilder {
+ private boolean mOnTop = true;
+ private int mStackId = 0;
+ private int mDisplayId = 1;
+
+ private final ActivityManagerService mService;
+
+ public ActivityStackBuilder(ActivityManagerService ams) {
+ mService = ams;
+ }
+
+ public ActivityStackBuilder setOnTop(boolean onTop) {
+ mOnTop = onTop;
+ return this;
+ }
+
+ public ActivityStackBuilder setStackId(int id) {
+ mStackId = id;
+ return this;
+ }
+
+ public ActivityStackBuilder setDisplayId(int id) {
+ mDisplayId = id;
+ return this;
+ }
+
+ public TestActivityStack build() {
+ return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f3f68ff..2663aaf 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -50,6 +50,7 @@
import org.mockito.ArgumentCaptor;
+import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -249,6 +250,25 @@
assertEquals(7, updates.size());
}
+ public void testGetInstalledProvidersForPackage() {
+ List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
+ assertTrue(!allProviders.isEmpty());
+ String packageName = allProviders.get(0).provider.getPackageName();
+ List<AppWidgetProviderInfo> providersForPackage = mManager.getInstalledProvidersForPackage(
+ packageName, null);
+ // Remove providers from allProviders that don't have the given package name.
+ Iterator<AppWidgetProviderInfo> iter = allProviders.iterator();
+ while (iter.hasNext()) {
+ if (!iter.next().provider.getPackageName().equals(packageName)) {
+ iter.remove();
+ }
+ }
+ assertEquals(allProviders.size(), providersForPackage.size());
+ for (int i = 0; i < allProviders.size(); i++) {
+ assertEquals(allProviders.get(i).provider, providersForPackage.get(i).provider);
+ }
+ }
+
private int setupHostAndWidget() {
List<PendingHostUpdate> updates = mService.startListening(
mMockHost, mPkgName, HOST_ID, new int[0]).getList();
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 2ccaefc..25004de 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -44,7 +44,8 @@
@Test
public void testRemoveContainer() throws Exception {
- final TestAppWindowContainerController controller = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller =
+ createAppWindowController();
// Assert token was added to display.
assertNotNull(sDisplayContent.getWindowToken(controller.mToken.asBinder()));
@@ -61,7 +62,8 @@
@Test
public void testSetOrientation() throws Exception {
- final TestAppWindowContainerController controller = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller =
+ createAppWindowController();
// Assert orientation is unspecified to start.
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation());
@@ -92,7 +94,8 @@
@Test
public void testCreateRemoveStartingWindow() throws Exception {
- final TestAppWindowContainerController controller = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller =
+ createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
waitUntilHandlerIdle();
@@ -105,8 +108,10 @@
@Test
public void testTransferStartingWindow() throws Exception {
- final TestAppWindowContainerController controller1 = createAppWindowController();
- final TestAppWindowContainerController controller2 = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller1 =
+ createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller2 =
+ createAppWindowController();
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
waitUntilHandlerIdle();
@@ -120,8 +125,10 @@
@Test
public void testTransferStartingWindowWhileCreating() throws Exception {
- final TestAppWindowContainerController controller1 = createAppWindowController();
- final TestAppWindowContainerController controller2 = createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller1 =
+ createAppWindowController();
+ final WindowTestUtils.TestAppWindowContainerController controller2 =
+ createAppWindowController();
sPolicy.setRunnableWhenAddingSplashScreen(() -> {
// Surprise, ...! Transfer window in the middle of the creation flow.
@@ -140,16 +147,16 @@
public void testReparent() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController1 =
- new TestTaskWindowContainerController(stackController);
- final TestAppWindowContainerController appWindowController1 = createAppWindowController(
- taskController1);
- final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stackController);
- final TestAppWindowContainerController appWindowController2 = createAppWindowController(
- taskController2);
- final TestTaskWindowContainerController taskController3 =
- new TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController1 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestAppWindowContainerController appWindowController1 =
+ createAppWindowController(taskController1);
+ final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestAppWindowContainerController appWindowController2 =
+ createAppWindowController(taskController2);
+ final WindowTestUtils.TestTaskWindowContainerController taskController3 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
try {
appWindowController1.reparent(taskController1, 0);
@@ -169,16 +176,18 @@
// Reparent the app window and ensure that it is moved
appWindowController1.reparent(taskController2, 0);
assertEquals(taskController2.mContainer, appWindowController1.mContainer.getParent());
- assertEquals(0, ((TestAppWindowToken) appWindowController1.mContainer).positionInParent());
- assertEquals(1, ((TestAppWindowToken) appWindowController2.mContainer).positionInParent());
+ assertEquals(0, ((WindowTestUtils.TestAppWindowToken) appWindowController1.mContainer)
+ .positionInParent());
+ assertEquals(1, ((WindowTestUtils.TestAppWindowToken) appWindowController2.mContainer)
+ .positionInParent());
}
- private TestAppWindowContainerController createAppWindowController() {
- return createAppWindowController(new TestTaskWindowContainerController());
+ private WindowTestUtils.TestAppWindowContainerController createAppWindowController() {
+ return createAppWindowController(new WindowTestUtils.TestTaskWindowContainerController());
}
- private TestAppWindowContainerController createAppWindowController(
- TestTaskWindowContainerController taskController) {
- return new TestAppWindowContainerController(taskController);
+ private WindowTestUtils.TestAppWindowContainerController createAppWindowController(
+ WindowTestUtils.TestTaskWindowContainerController taskController) {
+ return new WindowTestUtils.TestAppWindowContainerController(taskController);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 2003b91..7a7ca3f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -51,7 +51,8 @@
@Test
public void testAddWindow_Order() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -78,7 +79,8 @@
@Test
public void testFindMainWindow() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
assertNull(token.findMainWindow());
@@ -102,12 +104,13 @@
// Create an app window with token on a display.
final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken appWindowToken = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken appWindowToken =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task.addChild(appWindowToken, 0);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
- final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+ final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken);
appWindowToken.addWindow(appWindow);
// Set initial orientation and update.
@@ -137,12 +140,13 @@
final DisplayContent defaultDisplayContent = sWm.getDefaultDisplayContentLocked();
final TaskStack stack = createTaskStackOnDisplay(defaultDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken appWindowToken = new TestAppWindowToken(defaultDisplayContent);
+ final WindowTestUtils.TestAppWindowToken appWindowToken =
+ new WindowTestUtils.TestAppWindowToken(defaultDisplayContent);
task.addChild(appWindowToken, 0);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
- final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+ final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken);
appWindowToken.addWindow(appWindow);
// Set initial orientation and update.
@@ -165,7 +169,8 @@
@Test
public void testGetOrientation() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
token.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
token.setFillsParent(false);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index e3ccd6e..d7d365e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -175,7 +175,7 @@
assertEquals(dc, stack.getDisplayContent());
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken token = new TestAppWindowToken(dc);
+ final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
task.addChild(token, 0);
assertEquals(dc, task.getDisplayContent());
assertEquals(dc, token.getDisplayContent());
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
index b0eba0b..13098f6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -16,12 +16,7 @@
package com.android.server.wm;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
-import android.view.Display;
-import android.view.DisplayInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,8 +43,8 @@
public void testRemoveContainer() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
final TaskStack stack = stackController.mContainer;
final Task task = taskController.mContainer;
@@ -68,11 +63,11 @@
public void testRemoveContainer_deferRemoval() throws Exception {
final StackWindowController stackController =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController);
final TaskStack stack = stackController.mContainer;
- final TestTask task = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
// Stack removal is deferred if one of its child is animating.
task.setLocalIsAnimating(true);
@@ -96,9 +91,9 @@
final StackWindowController stack1Controller =
createStackControllerOnDisplay(sDisplayContent);
final TaskStack stack1 = stack1Controller.mContainer;
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1Controller);
- final TestTask task1 = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
+ final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
task1.mOnDisplayChangedCalled = false;
// Create second display and put second stack on it.
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/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index 462bd68..82ea2313 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -56,7 +56,7 @@
// Stack should contain visible app window to be considered visible.
final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
assertFalse(mPinnedStack.isVisible());
- final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
+ final WindowTestUtils.TestAppWindowToken pinnedApp = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
pinnedTask.addChild(pinnedApp, 0 /* addPos */);
assertTrue(mPinnedStack.isVisible());
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
index 9dbd8a6..267e5f7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import android.content.pm.ActivityInfo;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -67,12 +64,14 @@
public void testClosingAppDifferentStackOrientation() throws Exception {
final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- TestAppWindowToken appWindowToken1 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken1 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task1.addChild(appWindowToken1, 0);
appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- TestAppWindowToken appWindowToken2 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken2 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task2.addChild(appWindowToken2, 0);
appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -85,12 +84,14 @@
public void testMoveTaskToBackDifferentStackOrientation() throws Exception {
final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- TestAppWindowToken appWindowToken1 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken1 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task1.addChild(appWindowToken1, 0);
appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- TestAppWindowToken appWindowToken2 = new TestAppWindowToken(sDisplayContent);
+ WindowTestUtils.TestAppWindowToken appWindowToken2 =
+ new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task2.addChild(appWindowToken2, 0);
appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index f79908e..1819c56 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -16,14 +16,9 @@
package com.android.server.wm;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
-import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.Display;
-import android.view.DisplayInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,10 +40,10 @@
@Test
public void testRemoveContainer() throws Exception {
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController();
- final TestAppWindowContainerController appController =
- new TestAppWindowContainerController(taskController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController();
+ final WindowTestUtils.TestAppWindowContainerController appController =
+ new WindowTestUtils.TestAppWindowContainerController(taskController);
taskController.removeContainer();
// Assert that the container was removed.
@@ -58,12 +53,12 @@
@Test
public void testRemoveContainer_deferRemoval() throws Exception {
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController();
- final TestAppWindowContainerController appController =
- new TestAppWindowContainerController(taskController);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController();
+ final WindowTestUtils.TestAppWindowContainerController appController =
+ new WindowTestUtils.TestAppWindowContainerController(taskController);
- final TestTask task = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
final AppWindowToken app = appController.mContainer;
task.mShouldDeferRemoval = true;
@@ -85,12 +80,12 @@
public void testReparent() throws Exception {
final StackWindowController stackController1 =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stackController1);
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController1);
final StackWindowController stackController2 =
createStackControllerOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stackController2);
+ final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+ new WindowTestUtils.TestTaskWindowContainerController(stackController2);
boolean gotException = false;
try {
@@ -114,8 +109,8 @@
taskController.reparent(stackController2, 0);
assertEquals(stackController2.mContainer, taskController.mContainer.getParent());
- assertEquals(0, ((TestTask) taskController.mContainer).positionInParent());
- assertEquals(1, ((TestTask) taskController2.mContainer).positionInParent());
+ assertEquals(0, ((WindowTestUtils.TestTask) taskController.mContainer).positionInParent());
+ assertEquals(1, ((WindowTestUtils.TestTask) taskController2.mContainer).positionInParent());
}
@Test
@@ -124,9 +119,9 @@
final StackWindowController stack1Controller =
createStackControllerOnDisplay(sDisplayContent);
final TaskStack stack1 = stack1Controller.mContainer;
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1Controller);
- final TestTask task1 = (TestTask) taskController.mContainer;
+ final WindowTestUtils.TestTaskWindowContainerController taskController =
+ new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
+ final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
task1.mOnDisplayChangedCalled = false;
assertEquals(sDisplayContent, stack1.getDisplayContent());
@@ -134,9 +129,10 @@
final DisplayContent dc = createNewDisplay();
final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
final TaskStack stack2 = stack2Controller.mContainer;
- final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stack2Controller);
- final TestTask task2 = (TestTask) taskController2.mContainer;
+ final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+ new WindowTestUtils.TestTaskWindowContainerController(stack2Controller);
+ final WindowTestUtils.TestTask task2 =
+ (WindowTestUtils.TestTask) taskController2.mContainer;
// Reparent and check state
taskController.reparent(stack2Controller, 0);
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index cf8af67..0eaf5bc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -46,7 +46,7 @@
@Test
public void testFlow() throws Exception {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token);
sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
sWm.mUnknownAppVisibilityController.notifyRelayouted(token);
@@ -58,8 +58,8 @@
@Test
public void testMultiple() throws Exception {
- final AppWindowToken token1 = new TestAppWindowToken(sDisplayContent);
- final AppWindowToken token2 = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token1 = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token2 = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token1);
sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
sWm.mUnknownAppVisibilityController.notifyLaunched(token2);
@@ -74,7 +74,7 @@
@Test
public void testClear() throws Exception {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token);
sWm.mUnknownAppVisibilityController.clear();;
assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
@@ -82,7 +82,7 @@
@Test
public void testAppRemoved() throws Exception {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
sWm.mUnknownAppVisibilityController.notifyLaunched(token);
sWm.mUnknownAppVisibilityController.appRemoved(token);
assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 2e6eac0..a2aa058 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -102,7 +102,7 @@
// Just any non zero value.
sWm.mSystemDecorLayer = 10000;
- mWindowToken = new TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
+ mWindowToken = new WindowTestUtils.TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
mStubStack = new TaskStack(sWm, 0);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
new file mode 100644
index 0000000..3a44357
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -0,0 +1,308 @@
+/*
+ * 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.wm;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.IApplicationToken;
+import android.view.IWindow;
+import android.view.WindowManager;
+
+import static android.app.AppOpsManager.OP_NONE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.EMPTY;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static org.mockito.Mockito.mock;
+
+/**
+ * A collection of static functions that can be referenced by other test packages to provide access
+ * to WindowManager related test functionality.
+ */
+public class WindowTestUtils {
+ public static int sNextTaskId = 0;
+
+ /**
+ * Retrieves an instance of {@link WindowManagerService}, creating it if necessary.
+ */
+ public static WindowManagerService getWindowManagerService(Context context) {
+ return TestWindowManagerPolicy.getWindowManagerService(context);
+ }
+
+ /**
+ * Creates a mock instance of {@link StackWindowController}.
+ */
+ public static StackWindowController createMockStackWindowContainerController() {
+ StackWindowController controller = mock(StackWindowController.class);
+ controller.mContainer = mock(TestTaskStack.class);
+ return controller;
+ }
+
+ /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
+ public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
+ int userId) {
+ final Task newTask = new Task(WindowTestUtils.sNextTaskId++, stack, userId, service, null,
+ EMPTY, 0, false,
+ false, new ActivityManager.TaskDescription(), null);
+ stack.addTask(newTask, POSITION_TOP);
+ return newTask;
+ }
+
+ /**
+ * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
+ * normally be mocked out.
+ */
+ public static class TestTaskStack extends TaskStack {
+ TestTaskStack(WindowManagerService service, int stackId) {
+ super(service, stackId);
+ }
+
+ @Override
+ void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
+ // Do nothing.
+ }
+ }
+
+ /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
+ public static class TestAppWindowToken extends AppWindowToken {
+
+ TestAppWindowToken(DisplayContent dc) {
+ super(WindowTestsBase.sWm, null, false, dc, true /* fillsParent */,
+ null /* overrideConfig */, null /* bounds */);
+ }
+
+ TestAppWindowToken(WindowManagerService service, IApplicationToken token,
+ boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+ boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+ int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+ boolean alwaysFocusable, AppWindowContainerController controller,
+ Configuration overrideConfig, Rect bounds) {
+ super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
+ showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
+ launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ WindowState getFirstChild() {
+ return mChildren.getFirst();
+ }
+
+ WindowState getLastChild() {
+ return mChildren.getLast();
+ }
+
+ int positionInParent() {
+ return getParent().mChildren.indexOf(this);
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+ public static class TestWindowToken extends WindowToken {
+ int adj = 0;
+
+ TestWindowToken(int type, DisplayContent dc) {
+ this(type, dc, false /* persistOnEmpty */);
+ }
+
+ TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(WindowTestsBase.sWm, mock(IBinder.class), type, persistOnEmpty, dc,
+ false /* ownerCanManageAppTokens */);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ @Override
+ int getAnimLayerAdjustment() {
+ return adj;
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link Task} class */
+ public static class TestTask extends Task {
+ boolean mShouldDeferRemoval = false;
+ boolean mOnDisplayChangedCalled = false;
+ private boolean mUseLocalIsAnimating = false;
+ private boolean mIsAnimating = false;
+
+ TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, TaskWindowContainerController controller) {
+ super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, new ActivityManager.TaskDescription(),
+ controller);
+ }
+
+ boolean shouldDeferRemoval() {
+ return mShouldDeferRemoval;
+ }
+
+ int positionInParent() {
+ return getParent().mChildren.indexOf(this);
+ }
+
+ @Override
+ void onDisplayChanged(DisplayContent dc) {
+ super.onDisplayChanged(dc);
+ mOnDisplayChangedCalled = true;
+ }
+
+ @Override
+ boolean isAnimating() {
+ return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
+ }
+
+ void setLocalIsAnimating(boolean isAnimating) {
+ mUseLocalIsAnimating = true;
+ mIsAnimating = isAnimating;
+ }
+ }
+
+ /**
+ * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
+ * class.
+ */
+ public static class TestTaskWindowContainerController extends TaskWindowContainerController {
+
+ TestTaskWindowContainerController() {
+ this(WindowTestsBase.createStackControllerOnDisplay(WindowTestsBase.sDisplayContent));
+ }
+
+ TestTaskWindowContainerController(StackWindowController stackController) {
+ super(sNextTaskId++, new TaskWindowContainerListener() {
+ @Override
+ public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+
+ }
+
+ @Override
+ public void requestResize(Rect bounds, int resizeMode) {
+
+ }
+ }, stackController, 0 /* userId */, null /* bounds */,
+ EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
+ false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
+ true /* showForAllUsers */, new ActivityManager.TaskDescription(), WindowTestsBase.sWm);
+ }
+
+ @Override
+ TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, ActivityManager.TaskDescription taskDescription) {
+ return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, this);
+ }
+ }
+
+ public static class TestAppWindowContainerController extends AppWindowContainerController {
+
+ final IApplicationToken mToken;
+
+ TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
+ this(taskController, new TestIApplicationToken());
+ }
+
+ TestAppWindowContainerController(TestTaskWindowContainerController taskController,
+ IApplicationToken token) {
+ super(taskController, token, null /* listener */, 0 /* index */,
+ SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
+ true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
+ false /* launchTaskBehind */, false /* alwaysFocusable */,
+ 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
+ 0 /* inputDispatchingTimeoutNanos */, WindowTestsBase.sWm, null /* overrideConfig */,
+ null /* bounds */);
+ mToken = token;
+ }
+
+ @Override
+ AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
+ boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+ boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+ int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+ boolean alwaysFocusable, AppWindowContainerController controller,
+ Configuration overrideConfig, Rect bounds) {
+ return new TestAppWindowToken(service, token, voiceInteraction, dc,
+ inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
+ orientation,
+ rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
+ controller, overrideConfig, bounds);
+ }
+
+ AppWindowToken getAppWindowToken() {
+ return (AppWindowToken) WindowTestsBase.sDisplayContent.getWindowToken(mToken.asBinder());
+ }
+ }
+
+ public static class TestIApplicationToken implements IApplicationToken {
+
+ private final Binder mBinder = new Binder();
+ @Override
+ public IBinder asBinder() {
+ return mBinder;
+ }
+ }
+
+ /** Used to track resize reports. */
+ public static class TestWindowState extends WindowState {
+ boolean resizeReported;
+
+ TestWindowState(WindowManagerService service, Session session, IWindow window,
+ WindowManager.LayoutParams attrs, WindowToken token) {
+ super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
+ }
+
+ @Override
+ void reportResized() {
+ super.reportResized();
+ resizeReported = true;
+ }
+
+ @Override
+ public boolean isGoneForLayoutLw() {
+ return false;
+ }
+
+ @Override
+ void updateResizingWindowIfNeeded() {
+ // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+ // the system that it can actually update the window.
+ boolean hadSurface = mHasSurface;
+ mHasSurface = true;
+
+ super.updateResizingWindowIfNeeded();
+
+ mHasSurface = hadSurface;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index a9d930f..eaf4ac4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -19,21 +19,16 @@
import static android.view.View.VISIBLE;
import android.app.ActivityManager.TaskDescription;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.Binder;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.IApplicationToken;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
import org.mockito.MockitoAnnotations;
-import android.app.ActivityManager.TaskSnapshot;
import android.content.Context;
-import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
import android.view.IWindow;
import android.view.WindowManager;
@@ -41,10 +36,6 @@
import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.AppOpsManager.OP_NONE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -58,7 +49,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.mockito.Mockito.mock;
import com.android.server.AttributeCache;
@@ -78,8 +68,7 @@
// make sure we don't collide with any existing display. If we run into no other display, the
// added display should be treated as default. This cannot be the default display
private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
- static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
- private static int sNextTaskId = 0;
+ private static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
private static boolean sOneTimeSetupDone = false;
static DisplayContent sDisplayContent;
@@ -184,14 +173,14 @@
private static WindowToken createWindowToken(DisplayContent dc, int stackId, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
- return new TestWindowToken(type, dc);
+ return new WindowTestUtils.TestWindowToken(type, dc);
}
final TaskStack stack = stackId == INVALID_STACK_ID
? createTaskStackOnDisplay(dc)
: createStackControllerOnStackOnDisplay(stackId, dc).mContainer;
final Task task = createTaskInStack(stack, 0 /* userId */);
- final TestAppWindowToken token = new TestAppWindowToken(dc);
+ final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
task.addChild(token, 0);
return token;
}
@@ -209,7 +198,7 @@
}
WindowState createAppWindow(Task task, int type, String name) {
- final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
task.addChild(token, 0);
return createWindow(null, type, token, name);
}
@@ -260,10 +249,7 @@
/** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
static Task createTaskInStack(TaskStack stack, int userId) {
- final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, 0, false,
- false, new TaskDescription(), null);
- stack.addTask(newTask, POSITION_TOP);
- return newTask;
+ return WindowTestUtils.createTaskInStack(sWm, stack, userId);
}
/** Creates a {@link DisplayContent} and adds it to the system. */
@@ -274,227 +260,10 @@
return new DisplayContent(display, sWm, sLayersController, new WallpaperController(sWm));
}
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- static class TestWindowToken extends WindowToken {
- int adj = 0;
-
- TestWindowToken(int type, DisplayContent dc) {
- this(type, dc, false /* persistOnEmpty */);
- }
-
- TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
- super(sWm, mock(IBinder.class), type, persistOnEmpty, dc,
- false /* ownerCanManageAppTokens */);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- @Override
- int getAnimLayerAdjustment() {
- return adj;
- }
+ /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
+ WindowTestUtils.TestWindowState createWindowState(WindowManager.LayoutParams attrs,
+ WindowToken token) {
+ return new WindowTestUtils.TestWindowState(sWm, sMockSession, sIWindow, attrs, token);
}
- /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
- static class TestAppWindowToken extends AppWindowToken {
-
- TestAppWindowToken(DisplayContent dc) {
- super(sWm, null, false, dc, true /* fillsParent */, null /* overrideConfig */,
- null /* bounds */);
- }
-
- TestAppWindowToken(WindowManagerService service, IApplicationToken token,
- boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
- boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
- int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
- boolean alwaysFocusable, AppWindowContainerController controller,
- Configuration overrideConfig, Rect bounds) {
- super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
- showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
- launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- WindowState getFirstChild() {
- return mChildren.getFirst();
- }
-
- WindowState getLastChild() {
- return mChildren.getLast();
- }
-
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
- }
-
- /* Used so we can gain access to some protected members of the {@link Task} class */
- class TestTask extends Task {
-
- boolean mShouldDeferRemoval = false;
- boolean mOnDisplayChangedCalled = false;
- private boolean mUseLocalIsAnimating = false;
- private boolean mIsAnimating = false;
-
- TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
- Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, TaskWindowContainerController controller) {
- super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
- supportsPictureInPicture, homeTask, new TaskDescription(), controller);
- }
-
- boolean shouldDeferRemoval() {
- return mShouldDeferRemoval;
- }
-
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
-
- @Override
- void onDisplayChanged(DisplayContent dc) {
- super.onDisplayChanged(dc);
- mOnDisplayChangedCalled = true;
- }
-
- @Override
- boolean isAnimating() {
- return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
- }
-
- void setLocalIsAnimating(boolean isAnimating) {
- mUseLocalIsAnimating = true;
- mIsAnimating = isAnimating;
- }
- }
-
- /**
- * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
- * class.
- */
- class TestTaskWindowContainerController extends TaskWindowContainerController {
-
- TestTaskWindowContainerController() {
- this(createStackControllerOnDisplay(sDisplayContent));
- }
-
- TestTaskWindowContainerController(StackWindowController stackController) {
- super(sNextTaskId++, new TaskWindowContainerListener() {
- @Override
- public void onSnapshotChanged(TaskSnapshot snapshot) {
-
- }
-
- @Override
- public void requestResize(Rect bounds, int resizeMode) {
-
- }
- }, stackController, 0 /* userId */, null /* bounds */,
- EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
- false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
- true /* showForAllUsers */, new TaskDescription(), sWm);
- }
-
- @Override
- TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
- Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, TaskDescription taskDescription) {
- return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
- supportsPictureInPicture, homeTask, this);
- }
- }
-
- class TestAppWindowContainerController extends AppWindowContainerController {
-
- final IApplicationToken mToken;
-
- TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
- this(taskController, new TestIApplicationToken());
- }
-
- TestAppWindowContainerController(TestTaskWindowContainerController taskController,
- IApplicationToken token) {
- super(taskController, token, null /* listener */, 0 /* index */,
- SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
- true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
- false /* launchTaskBehind */, false /* alwaysFocusable */,
- 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
- 0 /* inputDispatchingTimeoutNanos */, sWm, null /* overrideConfig */,
- null /* bounds */);
- mToken = token;
- }
-
- @Override
- AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
- boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
- boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
- int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
- boolean alwaysFocusable, AppWindowContainerController controller,
- Configuration overrideConfig, Rect bounds) {
- return new TestAppWindowToken(service, token, voiceInteraction, dc,
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
- orientation,
- rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
- controller, overrideConfig, bounds);
- }
-
- AppWindowToken getAppWindowToken() {
- return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder());
- }
- }
-
- class TestIApplicationToken implements IApplicationToken {
-
- private final Binder mBinder = new Binder();
- @Override
- public IBinder asBinder() {
- return mBinder;
- }
- }
-
- /** Used to track resize reports. */
- class TestWindowState extends WindowState {
- boolean resizeReported;
-
- TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
- super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
- false /* ownerCanAddInternalSystemWindow */);
- }
-
- @Override
- void reportResized() {
- super.reportResized();
- resizeReported = true;
- }
-
- @Override
- public boolean isGoneForLayoutLw() {
- return false;
- }
-
- @Override
- void updateResizingWindowIfNeeded() {
- // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
- // the system that it can actually update the window.
- boolean hadSurface = mHasSurface;
- mHasSurface = true;
-
- super.updateResizingWindowIfNeeded();
-
- mHasSurface = hadSurface;
- }
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index babb6d9..4f7ad41 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -46,7 +46,8 @@
@Test
public void testAddWindow() throws Exception {
- final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
+ final WindowTestUtils.TestWindowToken token =
+ new WindowTestUtils.TestWindowToken(0, sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -76,7 +77,7 @@
@Test
public void testChildRemoval() throws Exception {
final DisplayContent dc = sDisplayContent;
- final TestWindowToken token = new TestWindowToken(0, dc);
+ final WindowTestUtils.TestWindowToken token = new WindowTestUtils.TestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
@@ -95,7 +96,8 @@
@Test
public void testAdjustAnimLayer() throws Exception {
- final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
+ final WindowTestUtils.TestWindowToken token =
+ new WindowTestUtils.TestWindowToken(0, sDisplayContent);
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
@@ -135,8 +137,9 @@
*/
@Test
public void testTokenRemovalProcess() throws Exception {
- final TestWindowToken token =
- new TestWindowToken(TYPE_TOAST, sDisplayContent, true /* persistOnEmpty */);
+ final WindowTestUtils.TestWindowToken token =
+ new WindowTestUtils.TestWindowToken(TYPE_TOAST, sDisplayContent,
+ true /* persistOnEmpty */);
// Verify that the token is on the display
assertNotNull(sDisplayContent.getWindowToken(token.token));
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 7b8ebd4..01e36f5 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -1039,18 +1039,34 @@
* Start the appropriate package when an device/accessory got attached.
*
* @param intent The intent to start the package
- * @param matches The available resolutions of the intent
+ * @param rawMatches The available resolutions of the intent
* @param defaultActivity The default activity for the device (if set)
* @param device The device if a device was attached
* @param accessory The accessory if a device was attached
*/
- private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> matches,
+ private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> rawMatches,
@Nullable ActivityInfo defaultActivity, @Nullable UsbDevice device,
@Nullable UsbAccessory accessory) {
- int count = matches.size();
+ final int numRawMatches = rawMatches.size();
+
+ // The raw matches contain the activities that can be started but also the intents to switch
+ // between the profiles
+ int numParentActivityMatches = 0;
+ int numNonParentActivityMatches = 0;
+ for (int i = 0; i < numRawMatches; i++) {
+ final ResolveInfo rawMatch = rawMatches.get(i);
+ if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ if (UserHandle.getUserHandleForUid(
+ rawMatch.activityInfo.applicationInfo.uid).equals(mParentUser)) {
+ numParentActivityMatches++;
+ } else {
+ numNonParentActivityMatches++;
+ }
+ }
+ }
// don't show the resolver activity if there are no choices available
- if (count == 0) {
+ if (numParentActivityMatches + numNonParentActivityMatches == 0) {
if (accessory != null) {
String uri = accessory.getUri();
if (uri != null && uri.length() > 0) {
@@ -1073,6 +1089,21 @@
return;
}
+ // If only one profile has activity matches, we need to remove all switch intents
+ ArrayList<ResolveInfo> matches;
+ if (numParentActivityMatches == 0 || numNonParentActivityMatches == 0) {
+ matches = new ArrayList<>(numParentActivityMatches + numNonParentActivityMatches);
+
+ for (int i = 0; i < numRawMatches; i++) {
+ ResolveInfo rawMatch = rawMatches.get(i);
+ if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ matches.add(rawMatch);
+ }
+ }
+ } else {
+ matches = rawMatches;
+ }
+
if (defaultActivity != null) {
UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser(
UserHandle.getUserId(defaultActivity.applicationInfo.uid));
@@ -1101,7 +1132,7 @@
resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
UserHandle user;
- if (count == 1) {
+ if (matches.size() == 1) {
ResolveInfo rInfo = matches.get(0);
// start UsbConfirmActivity if there is only one choice
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 92233b1..f80ee73 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -356,6 +356,7 @@
private final StatusHints mStatusHints;
private final Bundle mExtras;
private final Bundle mIntentExtras;
+ private final long mCreationTimeMillis;
/**
* Whether the supplied capabilities supports the specified capability.
@@ -578,9 +579,12 @@
}
/**
- * @return The time the {@code Call} has been connected. This information is updated
- * periodically, but user interfaces should not rely on this to display any "call time
- * clock".
+ * Returns the time the {@link Call} connected (i.e. became active). This information is
+ * updated periodically, but user interfaces should not rely on this to display the "call
+ * time clock". For the time when the call was first added to Telecom, see
+ * {@link #getCreationTimeMillis()}.
+ *
+ * @return The time the {@link Call} connected in milliseconds since the epoch.
*/
public final long getConnectTimeMillis() {
return mConnectTimeMillis;
@@ -622,6 +626,18 @@
return mIntentExtras;
}
+ /**
+ * Returns the time when the call was first created and added to Telecom. This is the same
+ * time that is logged as the start time in the Call Log (see
+ * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
+ * (became active), see {@link #getConnectTimeMillis()}.
+ *
+ * @return The creation time of the call, in millis since the epoch.
+ */
+ public long getCreationTimeMillis() {
+ return mCreationTimeMillis;
+ }
+
@Override
public boolean equals(Object o) {
if (o instanceof Details) {
@@ -641,28 +657,29 @@
Objects.equals(mVideoState, d.mVideoState) &&
Objects.equals(mStatusHints, d.mStatusHints) &&
areBundlesEqual(mExtras, d.mExtras) &&
- areBundlesEqual(mIntentExtras, d.mIntentExtras);
+ areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
+ Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
}
return false;
}
@Override
public int hashCode() {
- return
- Objects.hashCode(mHandle) +
- Objects.hashCode(mHandlePresentation) +
- Objects.hashCode(mCallerDisplayName) +
- Objects.hashCode(mCallerDisplayNamePresentation) +
- Objects.hashCode(mAccountHandle) +
- Objects.hashCode(mCallCapabilities) +
- Objects.hashCode(mCallProperties) +
- Objects.hashCode(mDisconnectCause) +
- Objects.hashCode(mConnectTimeMillis) +
- Objects.hashCode(mGatewayInfo) +
- Objects.hashCode(mVideoState) +
- Objects.hashCode(mStatusHints) +
- Objects.hashCode(mExtras) +
- Objects.hashCode(mIntentExtras);
+ return Objects.hash(mHandle,
+ mHandlePresentation,
+ mCallerDisplayName,
+ mCallerDisplayNamePresentation,
+ mAccountHandle,
+ mCallCapabilities,
+ mCallProperties,
+ mDisconnectCause,
+ mConnectTimeMillis,
+ mGatewayInfo,
+ mVideoState,
+ mStatusHints,
+ mExtras,
+ mIntentExtras,
+ mCreationTimeMillis);
}
/** {@hide} */
@@ -681,7 +698,8 @@
int videoState,
StatusHints statusHints,
Bundle extras,
- Bundle intentExtras) {
+ Bundle intentExtras,
+ long creationTimeMillis) {
mTelecomCallId = telecomCallId;
mHandle = handle;
mHandlePresentation = handlePresentation;
@@ -697,6 +715,7 @@
mStatusHints = statusHints;
mExtras = extras;
mIntentExtras = intentExtras;
+ mCreationTimeMillis = creationTimeMillis;
}
/** {@hide} */
@@ -716,7 +735,8 @@
parcelableCall.getVideoState(),
parcelableCall.getStatusHints(),
parcelableCall.getExtras(),
- parcelableCall.getIntentExtras());
+ parcelableCall.getIntentExtras(),
+ parcelableCall.getCreationTimeMillis());
}
@Override
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 85a92d1..6212a77 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -59,6 +59,7 @@
private final List<String> mConferenceableCallIds;
private final Bundle mIntentExtras;
private final Bundle mExtras;
+ private final long mCreationTimeMillis;
public ParcelableCall(
String id,
@@ -85,7 +86,8 @@
int videoState,
List<String> conferenceableCallIds,
Bundle intentExtras,
- Bundle extras) {
+ Bundle extras,
+ long creationTimeMillis) {
mId = id;
mState = state;
mDisconnectCause = disconnectCause;
@@ -111,6 +113,7 @@
mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds);
mIntentExtras = intentExtras;
mExtras = extras;
+ mCreationTimeMillis = creationTimeMillis;
}
/** The unique ID of the call. */
@@ -289,6 +292,13 @@
return mIsVideoCallProviderChanged;
}
+ /**
+ * @return The time the call was created, in milliseconds since the epoch.
+ */
+ public long getCreationTimeMillis() {
+ return mCreationTimeMillis;
+ }
+
/** Responsible for creating ParcelableCall objects for deserialized Parcels. */
public static final Parcelable.Creator<ParcelableCall> CREATOR =
new Parcelable.Creator<ParcelableCall> () {
@@ -324,6 +334,7 @@
int supportedAudioRoutes = source.readInt();
boolean isRttCallChanged = source.readByte() == 1;
ParcelableRttCall rttCall = source.readParcelable(classLoader);
+ long creationTimeMillis = source.readLong();
return new ParcelableCall(
id,
state,
@@ -349,7 +360,8 @@
videoState,
conferenceableCallIds,
intentExtras,
- extras);
+ extras,
+ creationTimeMillis);
}
@Override
@@ -393,6 +405,7 @@
destination.writeInt(mSupportedAudioRoutes);
destination.writeByte((byte) (mIsRttCallChanged ? 1 : 0));
destination.writeParcelable(mRttCall, 0);
+ destination.writeLong(mCreationTimeMillis);
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index b4c531e..f9875c5 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -53,8 +53,9 @@
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
+ * @deprecated use {@link Intent#ACTION_SERVICE_STATE}
*/
- public static final String ACTION_SERVICE_STATE_CHANGED = "android.intent.action.SERVICE_STATE";
+ public static final String ACTION_SERVICE_STATE_CHANGED = Intent.ACTION_SERVICE_STATE;
/**
* <p>Broadcast Action: The radio technology has changed. The intent will have the following
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
index 36ebc90..71067ae 100644
--- a/tests/UiBench/Android.mk
+++ b/tests/UiBench/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := 24
+LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
# omit gradle 'build' dir
diff --git a/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/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 04443a5..c562cb9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -80,6 +80,7 @@
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
+import com.android.server.net.NetworkPolicyManagerInternal;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -713,6 +714,9 @@
}
mServiceContext = new MockContext(getContext());
+ LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
+ LocalServices.addService(
+ NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext,
mock(INetworkManagementService.class),
mock(INetworkStatsService.class),
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) {