Merge "Audio focus: API for external audio focus policy" into oc-dev
diff --git a/Android.mk b/Android.mk
index eb649c9..634272b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -102,6 +102,7 @@
core/java/android/app/IUserSwitchObserver.aidl \
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
+ core/java/android/app/admin/IDeviceAdminService.aidl \
core/java/android/app/admin/IDevicePolicyManager.aidl \
core/java/android/app/trust/IStrongAuthTracker.aidl \
core/java/android/app/trust/ITrustManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index d890cdb..5926e98 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -104,7 +104,7 @@
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
- field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
+ field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
@@ -3675,7 +3675,8 @@
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
method public void onMovedToDisplay(int, android.content.res.Configuration);
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
method public boolean onNavigateUpFromChild(android.app.Activity);
method protected void onNewIntent(android.content.Intent);
@@ -3683,7 +3684,8 @@
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method protected void onPostCreate(android.os.Bundle);
method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
@@ -4180,7 +4182,7 @@
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
- field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBERS = "android:read_phone_numbers";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -4616,11 +4618,13 @@
method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method public void onPrepareOptionsMenu(android.view.Menu);
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method public void onResume();
@@ -4705,11 +4709,13 @@
method public void dispatchDestroy();
method public void dispatchDestroyView();
method public void dispatchLowMemory();
- method public void dispatchMultiWindowModeChanged(boolean);
+ method public deprecated void dispatchMultiWindowModeChanged(boolean);
+ method public void dispatchMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
method public void dispatchOptionsMenuClosed(android.view.Menu);
method public void dispatchPause();
- method public void dispatchPictureInPictureModeChanged(boolean);
+ method public deprecated void dispatchPictureInPictureModeChanged(boolean);
+ method public void dispatchPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
method public void dispatchResume();
method public void dispatchStart();
@@ -6226,6 +6232,11 @@
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
+ public class DeviceAdminService extends android.app.Service {
+ ctor public DeviceAdminService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ }
+
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6392,6 +6403,7 @@
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+ field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -6595,6 +6607,7 @@
method public android.os.Bundle getExtras();
method public int getHeight();
method public java.lang.String getHint();
+ method public android.view.ViewStructure.HtmlInfo getHtmlInfo();
method public int getId();
method public java.lang.String getIdEntry();
method public java.lang.String getIdPackage();
@@ -7147,7 +7160,6 @@
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
- method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7947,7 +7959,7 @@
}
public final class AdvertisingSet {
- method public void enableAdvertising(boolean, int);
+ method public void enableAdvertising(boolean, int, int);
method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
@@ -8023,8 +8035,8 @@
method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
- method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
- method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
}
@@ -8036,21 +8048,6 @@
method public void stopScan(android.bluetooth.le.ScanCallback);
}
- public abstract class PeriodicAdvertisingCallback {
- ctor public PeriodicAdvertisingCallback();
- method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
- method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
- method public void onSyncLost(int);
- field public static final int SYNC_NO_RESOURCES = 2; // 0x2
- field public static final int SYNC_NO_RESPONSE = 1; // 0x1
- }
-
- public final class PeriodicAdvertisingManager {
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
- method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
- }
-
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
method public boolean getEnable();
@@ -8068,21 +8065,6 @@
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
- public final class PeriodicAdvertisingReport implements android.os.Parcelable {
- ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
- method public int describeContents();
- method public android.bluetooth.le.ScanRecord getData();
- method public int getDataStatus();
- method public int getRssi();
- method public int getSyncHandle();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
- }
-
public abstract class ScanCallback {
ctor public ScanCallback();
method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -9294,6 +9276,8 @@
field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
@@ -9493,8 +9477,9 @@
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
- field public static final deprecated java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+ 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 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";
@@ -9853,6 +9838,7 @@
}
public abstract interface ServiceConnection {
+ method public default void onBindingDead(android.content.ComponentName);
method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
method public abstract void onServiceDisconnected(android.content.ComponentName);
}
@@ -10357,12 +10343,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
+ method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
+ field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10659,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";
@@ -10912,9 +10899,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public android.content.ComponentName[] getChooserComponentNames();
- method public android.os.PersistableBundle getChooserExtras();
- method public android.content.IntentFilter[] getChooserIntentFilters();
+ method public deprecated android.content.ComponentName[] getChooserComponentNames();
+ method public deprecated android.os.PersistableBundle getChooserExtras();
+ method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10927,7 +10914,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public boolean isChooser();
+ method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10940,11 +10927,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
+ method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12540,6 +12527,7 @@
field public int inTargetDensity;
field public byte[] inTempStorage;
field public deprecated boolean mCancel;
+ field public android.graphics.ColorSpace outColorSpace;
field public android.graphics.Bitmap.Config outConfig;
field public int outHeight;
field public java.lang.String outMimeType;
@@ -12716,7 +12704,7 @@
enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
}
- public final class Color {
+ public class Color {
ctor public Color();
method public static int HSVToColor(float[]);
method public static int HSVToColor(int, float[]);
@@ -15995,11 +15983,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);
}
@@ -23012,6 +23000,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;
@@ -24554,19 +24543,19 @@
}
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_APP_LINK_INTENT_URI = "app_link_intent_uri";
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
@@ -24584,28 +24573,28 @@
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";
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -24784,10 +24773,10 @@
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 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 {
@@ -40020,7 +40009,7 @@
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public boolean isConcurrentVoiceAndDataAllowed();
+ method public boolean isConcurrentVoiceAndDataSupported();
method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
@@ -40033,7 +40022,7 @@
method public deprecated boolean sendDialerCode(java.lang.String);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
@@ -40109,14 +40098,17 @@
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
+ field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
+ field public static final int USSD_RETURN_SUCCESS = 100; // 0x64
field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
- public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
- ctor public TelephonyManager.OnReceiveUssdResponseCallback();
- method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
- method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ public static abstract class TelephonyManager.UssdResponseCallback {
+ ctor public TelephonyManager.UssdResponseCallback();
+ method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(android.telephony.TelephonyManager, java.lang.String, int);
}
public abstract class VisualVoicemailService extends android.app.Service {
@@ -46021,7 +46013,6 @@
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
method public static deprecated long getGlobalActionKeyTimeout();
- method public float getScaledHorizontalScrollFactor();
method public static int getJumpTapTimeout();
method public static int getKeyRepeatDelay();
method public static int getKeyRepeatTimeout();
@@ -46033,6 +46024,7 @@
method public int getScaledDoubleTapSlop();
method public int getScaledEdgeSlop();
method public int getScaledFadingEdgeLength();
+ method public float getScaledHorizontalScrollFactor();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
method public int getScaledMinimumFlingVelocity();
@@ -46041,6 +46033,7 @@
method public int getScaledPagingTouchSlop();
method public int getScaledScrollBarSize();
method public int getScaledTouchSlop();
+ method public float getScaledVerticalScrollFactor();
method public int getScaledWindowTouchSlop();
method public static int getScrollBarFadeDuration();
method public static deprecated int getScrollBarSize();
@@ -46048,7 +46041,6 @@
method public static float getScrollFriction();
method public static int getTapTimeout();
method public static deprecated int getTouchSlop();
- method public float getScaledVerticalScrollFactor();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
method public boolean hasPermanentMenuKey();
@@ -46410,6 +46402,7 @@
method public abstract int getTextSelectionStart();
method public abstract boolean hasExtras();
method public abstract android.view.ViewStructure newChild(int);
+ method public abstract android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(java.lang.String);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
@@ -46432,8 +46425,8 @@
method public abstract void setFocusable(boolean);
method public abstract void setFocused(boolean);
method public abstract void setHint(java.lang.CharSequence);
+ method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
- method public abstract void setIdEntry(java.lang.String);
method public abstract void setInputType(int);
method public abstract void setLocaleList(android.os.LocaleList);
method public abstract void setLongClickable(boolean);
@@ -46448,6 +46441,18 @@
method public abstract void setVisibility(int);
}
+ public static abstract class ViewStructure.HtmlInfo {
+ ctor public ViewStructure.HtmlInfo();
+ method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes();
+ method public abstract java.lang.String getTag();
+ }
+
+ public static abstract class ViewStructure.HtmlInfo.Builder {
+ ctor public ViewStructure.HtmlInfo.Builder();
+ method public abstract android.view.ViewStructure.HtmlInfo.Builder addAttribute(java.lang.String, java.lang.String);
+ method public abstract android.view.ViewStructure.HtmlInfo build();
+ }
+
public final class ViewStub extends android.view.View {
ctor public ViewStub(android.content.Context);
ctor public ViewStub(android.content.Context, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 887a025..a5f10cd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -182,7 +182,7 @@
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
field public static final java.lang.String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
field public static final java.lang.String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
- field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
+ field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
@@ -3801,7 +3801,8 @@
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
method public void onMovedToDisplay(int, android.content.res.Configuration);
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
method public boolean onNavigateUpFromChild(android.app.Activity);
method protected void onNewIntent(android.content.Intent);
@@ -3809,7 +3810,8 @@
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method protected void onPostCreate(android.os.Bundle);
method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
@@ -4325,7 +4327,7 @@
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
- field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBERS = "android:read_phone_numbers";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -4775,11 +4777,13 @@
method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method public void onPrepareOptionsMenu(android.view.Menu);
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method public void onResume();
@@ -4864,11 +4868,13 @@
method public void dispatchDestroy();
method public void dispatchDestroyView();
method public void dispatchLowMemory();
- method public void dispatchMultiWindowModeChanged(boolean);
+ method public deprecated void dispatchMultiWindowModeChanged(boolean);
+ method public void dispatchMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
method public void dispatchOptionsMenuClosed(android.view.Menu);
method public void dispatchPause();
- method public void dispatchPictureInPictureModeChanged(boolean);
+ method public deprecated void dispatchPictureInPictureModeChanged(boolean);
+ method public void dispatchPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
method public void dispatchResume();
method public void dispatchStart();
@@ -6429,6 +6435,11 @@
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
+ public class DeviceAdminService extends android.app.Service {
+ ctor public DeviceAdminService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ }
+
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6616,6 +6627,7 @@
field public static final java.lang.String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+ field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -6832,6 +6844,7 @@
method public android.os.Bundle getExtras();
method public int getHeight();
method public java.lang.String getHint();
+ method public android.view.ViewStructure.HtmlInfo getHtmlInfo();
method public int getId();
method public java.lang.String getIdEntry();
method public java.lang.String getIdPackage();
@@ -7607,7 +7620,6 @@
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
- method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -8413,7 +8425,7 @@
}
public final class AdvertisingSet {
- method public void enableAdvertising(boolean, int);
+ method public void enableAdvertising(boolean, int, int);
method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
@@ -8489,8 +8501,8 @@
method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
- method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
- method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
}
@@ -8505,21 +8517,6 @@
method public void stopScan(android.bluetooth.le.ScanCallback);
}
- public abstract class PeriodicAdvertisingCallback {
- ctor public PeriodicAdvertisingCallback();
- method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
- method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
- method public void onSyncLost(int);
- field public static final int SYNC_NO_RESOURCES = 2; // 0x2
- field public static final int SYNC_NO_RESPONSE = 1; // 0x1
- }
-
- public final class PeriodicAdvertisingManager {
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
- method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
- }
-
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
method public boolean getEnable();
@@ -8537,21 +8534,6 @@
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
- public final class PeriodicAdvertisingReport implements android.os.Parcelable {
- ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
- method public int describeContents();
- method public android.bluetooth.le.ScanRecord getData();
- method public int getDataStatus();
- method public int getRssi();
- method public int getSyncHandle();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
- }
-
public final class ResultStorageDescriptor implements android.os.Parcelable {
ctor public ResultStorageDescriptor(int, int, int);
method public int describeContents();
@@ -9793,6 +9775,8 @@
field public static final java.lang.String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT";
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
+ field public static final java.lang.String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
+ field public static final java.lang.String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
@@ -9803,6 +9787,8 @@
field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
@@ -10022,8 +10008,9 @@
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
- field public static final deprecated java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+ 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 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";
@@ -10384,6 +10371,7 @@
}
public abstract interface ServiceConnection {
+ method public default void onBindingDead(android.content.ComponentName);
method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
method public abstract void onServiceDisconnected(android.content.ComponentName);
}
@@ -10979,12 +10967,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
+ method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
+ field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11310,6 +11298,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";
@@ -11628,9 +11617,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public android.content.ComponentName[] getChooserComponentNames();
- method public android.os.PersistableBundle getChooserExtras();
- method public android.content.IntentFilter[] getChooserIntentFilters();
+ method public deprecated android.content.ComponentName[] getChooserComponentNames();
+ method public deprecated android.os.PersistableBundle getChooserExtras();
+ method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -11643,7 +11632,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public boolean isChooser();
+ method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -11656,11 +11645,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
+ method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -13270,6 +13259,7 @@
field public int inTargetDensity;
field public byte[] inTempStorage;
field public deprecated boolean mCancel;
+ field public android.graphics.ColorSpace outColorSpace;
field public android.graphics.Bitmap.Config outConfig;
field public int outHeight;
field public java.lang.String outMimeType;
@@ -13446,7 +13436,7 @@
enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
}
- public final class Color {
+ public class Color {
ctor public Color();
method public static int HSVToColor(float[]);
method public static int HSVToColor(int, float[]);
@@ -17453,11 +17443,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);
}
@@ -24804,6 +24794,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;
@@ -26497,19 +26488,19 @@
}
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_APP_LINK_INTENT_URI = "app_link_intent_uri";
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
@@ -26527,28 +26518,28 @@
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";
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -26728,10 +26719,10 @@
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 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 {
@@ -43424,7 +43415,7 @@
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public boolean isConcurrentVoiceAndDataAllowed();
+ method public boolean isConcurrentVoiceAndDataSupported();
method public boolean isDataConnectivityPossible();
method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
@@ -43445,7 +43436,7 @@
method public deprecated boolean sendDialerCode(java.lang.String);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
@@ -43537,14 +43528,17 @@
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
+ field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
+ field public static final int USSD_RETURN_SUCCESS = 100; // 0x64
field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
- public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
- ctor public TelephonyManager.OnReceiveUssdResponseCallback();
- method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
- method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ public static abstract class TelephonyManager.UssdResponseCallback {
+ ctor public TelephonyManager.UssdResponseCallback();
+ method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(android.telephony.TelephonyManager, java.lang.String, int);
}
public abstract class VisualVoicemailService extends android.app.Service {
@@ -49482,7 +49476,6 @@
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
method public static deprecated long getGlobalActionKeyTimeout();
- method public float getScaledHorizontalScrollFactor();
method public static int getJumpTapTimeout();
method public static int getKeyRepeatDelay();
method public static int getKeyRepeatTimeout();
@@ -49494,6 +49487,7 @@
method public int getScaledDoubleTapSlop();
method public int getScaledEdgeSlop();
method public int getScaledFadingEdgeLength();
+ method public float getScaledHorizontalScrollFactor();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
method public int getScaledMinimumFlingVelocity();
@@ -49502,6 +49496,7 @@
method public int getScaledPagingTouchSlop();
method public int getScaledScrollBarSize();
method public int getScaledTouchSlop();
+ method public float getScaledVerticalScrollFactor();
method public int getScaledWindowTouchSlop();
method public static int getScrollBarFadeDuration();
method public static deprecated int getScrollBarSize();
@@ -49509,7 +49504,6 @@
method public static float getScrollFriction();
method public static int getTapTimeout();
method public static deprecated int getTouchSlop();
- method public float getScaledVerticalScrollFactor();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
method public boolean hasPermanentMenuKey();
@@ -49871,6 +49865,7 @@
method public abstract int getTextSelectionStart();
method public abstract boolean hasExtras();
method public abstract android.view.ViewStructure newChild(int);
+ method public abstract android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(java.lang.String);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
@@ -49893,8 +49888,8 @@
method public abstract void setFocusable(boolean);
method public abstract void setFocused(boolean);
method public abstract void setHint(java.lang.CharSequence);
+ method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
- method public abstract void setIdEntry(java.lang.String);
method public abstract void setInputType(int);
method public abstract void setLocaleList(android.os.LocaleList);
method public abstract void setLongClickable(boolean);
@@ -49909,6 +49904,18 @@
method public abstract void setVisibility(int);
}
+ public static abstract class ViewStructure.HtmlInfo {
+ ctor public ViewStructure.HtmlInfo();
+ method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes();
+ method public abstract java.lang.String getTag();
+ }
+
+ public static abstract class ViewStructure.HtmlInfo.Builder {
+ ctor public ViewStructure.HtmlInfo.Builder();
+ method public abstract android.view.ViewStructure.HtmlInfo.Builder addAttribute(java.lang.String, java.lang.String);
+ method public abstract android.view.ViewStructure.HtmlInfo build();
+ }
+
public final class ViewStub extends android.view.View {
ctor public ViewStub(android.content.Context);
ctor public ViewStub(android.content.Context, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 6fba51a..1b5eeed 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -104,7 +104,7 @@
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
- field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
+ field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
@@ -3677,7 +3677,8 @@
method public boolean onMenuItemSelected(int, android.view.MenuItem);
method public boolean onMenuOpened(int, android.view.Menu);
method public void onMovedToDisplay(int, android.content.res.Configuration);
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onNavigateUp();
method public boolean onNavigateUpFromChild(android.app.Activity);
method protected void onNewIntent(android.content.Intent);
@@ -3685,7 +3686,8 @@
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method protected void onPostCreate(android.os.Bundle);
method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
@@ -4192,7 +4194,7 @@
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
- field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBERS = "android:read_phone_numbers";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -4628,11 +4630,13 @@
method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
- method public void onMultiWindowModeChanged(boolean);
+ method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onMultiWindowModeChanged(boolean);
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
method public void onPause();
- method public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ method public deprecated void onPictureInPictureModeChanged(boolean);
method public void onPrepareOptionsMenu(android.view.Menu);
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method public void onResume();
@@ -4717,11 +4721,13 @@
method public void dispatchDestroy();
method public void dispatchDestroyView();
method public void dispatchLowMemory();
- method public void dispatchMultiWindowModeChanged(boolean);
+ method public deprecated void dispatchMultiWindowModeChanged(boolean);
+ method public void dispatchMultiWindowModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
method public void dispatchOptionsMenuClosed(android.view.Menu);
method public void dispatchPause();
- method public void dispatchPictureInPictureModeChanged(boolean);
+ method public deprecated void dispatchPictureInPictureModeChanged(boolean);
+ method public void dispatchPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
method public void dispatchResume();
method public void dispatchStart();
@@ -6245,6 +6251,11 @@
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
+ public class DeviceAdminService extends android.app.Service {
+ ctor public DeviceAdminService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ }
+
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6420,6 +6431,7 @@
field public static final java.lang.String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+ field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -6624,6 +6636,7 @@
method public android.os.Bundle getExtras();
method public int getHeight();
method public java.lang.String getHint();
+ method public android.view.ViewStructure.HtmlInfo getHtmlInfo();
method public int getId();
method public java.lang.String getIdEntry();
method public java.lang.String getIdPackage();
@@ -7177,7 +7190,6 @@
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
method public int getLeMaximumAdvertisingDataLength();
method public java.lang.String getName();
- method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7977,7 +7989,7 @@
}
public final class AdvertisingSet {
- method public void enableAdvertising(boolean, int);
+ method public void enableAdvertising(boolean, int, int);
method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
@@ -8053,8 +8065,8 @@
method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
- method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
- method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
+ method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
}
@@ -8066,21 +8078,6 @@
method public void stopScan(android.bluetooth.le.ScanCallback);
}
- public abstract class PeriodicAdvertisingCallback {
- ctor public PeriodicAdvertisingCallback();
- method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
- method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
- method public void onSyncLost(int);
- field public static final int SYNC_NO_RESOURCES = 2; // 0x2
- field public static final int SYNC_NO_RESPONSE = 1; // 0x1
- }
-
- public final class PeriodicAdvertisingManager {
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
- method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
- method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
- }
-
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
method public boolean getEnable();
@@ -8098,21 +8095,6 @@
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
- public final class PeriodicAdvertisingReport implements android.os.Parcelable {
- ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
- method public int describeContents();
- method public android.bluetooth.le.ScanRecord getData();
- method public int getDataStatus();
- method public int getRssi();
- method public int getSyncHandle();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
- }
-
public abstract class ScanCallback {
ctor public ScanCallback();
method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -9327,6 +9309,8 @@
field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
@@ -9526,8 +9510,9 @@
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
- field public static final deprecated java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+ 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 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";
@@ -9886,6 +9871,7 @@
}
public abstract interface ServiceConnection {
+ method public default void onBindingDead(android.content.ComponentName);
method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
method public abstract void onServiceDisconnected(android.content.ComponentName);
}
@@ -10393,12 +10379,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
+ method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
+ field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10698,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";
@@ -10952,9 +10939,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public android.content.ComponentName[] getChooserComponentNames();
- method public android.os.PersistableBundle getChooserExtras();
- method public android.content.IntentFilter[] getChooserIntentFilters();
+ method public deprecated android.content.ComponentName[] getChooserComponentNames();
+ method public deprecated android.os.PersistableBundle getChooserExtras();
+ method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10967,7 +10954,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public boolean isChooser();
+ method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10980,11 +10967,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
+ method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12590,6 +12577,7 @@
field public int inTargetDensity;
field public byte[] inTempStorage;
field public deprecated boolean mCancel;
+ field public android.graphics.ColorSpace outColorSpace;
field public android.graphics.Bitmap.Config outConfig;
field public int outHeight;
field public java.lang.String outMimeType;
@@ -12766,7 +12754,7 @@
enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
}
- public final class Color {
+ public class Color {
ctor public Color();
method public static int HSVToColor(float[]);
method public static int HSVToColor(int, float[]);
@@ -16050,11 +16038,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);
}
@@ -23125,6 +23113,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;
@@ -24667,19 +24656,19 @@
}
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_APP_LINK_INTENT_URI = "app_link_intent_uri";
+ field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+ field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+ field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+ field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+ field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+ field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
@@ -24697,28 +24686,28 @@
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";
+ field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+ field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+ field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+ field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+ field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+ field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+ field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+ field public static final int TYPE_ALBUM = 8; // 0x8
+ field public static final int TYPE_ARTIST = 9; // 0x9
+ field public static final int TYPE_CHANNEL = 6; // 0x6
+ field public static final int TYPE_CLIP = 4; // 0x4
+ field public static final int TYPE_EVENT = 5; // 0x5
+ field public static final int TYPE_MOVIE = 0; // 0x0
+ field public static final int TYPE_PLAYLIST = 10; // 0xa
+ field public static final int TYPE_STATION = 11; // 0xb
+ field public static final int TYPE_TRACK = 7; // 0x7
+ field public static final int TYPE_TV_EPISODE = 3; // 0x3
+ field public static final int TYPE_TV_SEASON = 2; // 0x2
+ field public static final int TYPE_TV_SERIES = 1; // 0x1
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -24897,10 +24886,10 @@
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 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 {
@@ -37551,6 +37540,7 @@
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
method public final boolean isLocked();
+ method public static boolean isQuickSettingsSupported();
method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
@@ -40223,7 +40213,7 @@
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
- method public boolean isConcurrentVoiceAndDataAllowed();
+ method public boolean isConcurrentVoiceAndDataSupported();
method public boolean isDataEnabled();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
@@ -40236,7 +40226,7 @@
method public deprecated boolean sendDialerCode(java.lang.String);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
@@ -40312,14 +40302,17 @@
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
+ field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
+ field public static final int USSD_RETURN_SUCCESS = 100; // 0x64
field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
- public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
- ctor public TelephonyManager.OnReceiveUssdResponseCallback();
- method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
- method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ public static abstract class TelephonyManager.UssdResponseCallback {
+ ctor public TelephonyManager.UssdResponseCallback();
+ method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(android.telephony.TelephonyManager, java.lang.String, int);
}
public abstract class VisualVoicemailService extends android.app.Service {
@@ -46398,7 +46391,6 @@
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
method public static deprecated long getGlobalActionKeyTimeout();
- method public float getScaledHorizontalScrollFactor();
method public static int getHoverTooltipHideShortTimeout();
method public static int getHoverTooltipHideTimeout();
method public static int getHoverTooltipShowTimeout();
@@ -46414,6 +46406,7 @@
method public int getScaledDoubleTapSlop();
method public int getScaledEdgeSlop();
method public int getScaledFadingEdgeLength();
+ method public float getScaledHorizontalScrollFactor();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
method public int getScaledMinimumFlingVelocity();
@@ -46422,6 +46415,7 @@
method public int getScaledPagingTouchSlop();
method public int getScaledScrollBarSize();
method public int getScaledTouchSlop();
+ method public float getScaledVerticalScrollFactor();
method public int getScaledWindowTouchSlop();
method public static int getScrollBarFadeDuration();
method public static deprecated int getScrollBarSize();
@@ -46429,7 +46423,6 @@
method public static float getScrollFriction();
method public static int getTapTimeout();
method public static deprecated int getTouchSlop();
- method public float getScaledVerticalScrollFactor();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
method public boolean hasPermanentMenuKey();
@@ -46791,6 +46784,7 @@
method public abstract int getTextSelectionStart();
method public abstract boolean hasExtras();
method public abstract android.view.ViewStructure newChild(int);
+ method public abstract android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(java.lang.String);
method public abstract void setAccessibilityFocused(boolean);
method public abstract void setActivated(boolean);
method public abstract void setAlpha(float);
@@ -46813,8 +46807,8 @@
method public abstract void setFocusable(boolean);
method public abstract void setFocused(boolean);
method public abstract void setHint(java.lang.CharSequence);
+ method public abstract void setHtmlInfo(android.view.ViewStructure.HtmlInfo);
method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
- method public abstract void setIdEntry(java.lang.String);
method public abstract void setInputType(int);
method public abstract void setLocaleList(android.os.LocaleList);
method public abstract void setLongClickable(boolean);
@@ -46829,6 +46823,18 @@
method public abstract void setVisibility(int);
}
+ public static abstract class ViewStructure.HtmlInfo {
+ ctor public ViewStructure.HtmlInfo();
+ method public abstract java.util.ArrayList<android.util.Pair<java.lang.String, java.lang.String>> getAttributes();
+ method public abstract java.lang.String getTag();
+ }
+
+ public static abstract class ViewStructure.HtmlInfo.Builder {
+ ctor public ViewStructure.HtmlInfo.Builder();
+ method public abstract android.view.ViewStructure.HtmlInfo.Builder addAttribute(java.lang.String, java.lang.String);
+ method public abstract android.view.ViewStructure.HtmlInfo build();
+ }
+
public final class ViewStub extends android.view.View {
ctor public ViewStub(android.content.Context);
ctor public ViewStub(android.content.Context, int);
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..2435ffa 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;
}
@@ -1047,7 +1065,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 +1093,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/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 5c7a12c..fe496e3 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -431,12 +431,10 @@
// Force all the animations to end when the duration scale is 0.
private void forceToEnd() {
- // TODO: Below is commented out to temp work around b/36241584, uncomment this when it's
- // fixed.
-// if (mEndCanBeCalled) {
-// end();
-// return;
-// }
+ if (mEndCanBeCalled) {
+ end();
+ return;
+ }
// Note: we don't want to combine this case with the end() method below because in
// the case of developer calling end(), we still need to make sure end() is explicitly
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 147b5d0..dbf81f9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1889,11 +1889,32 @@
/**
* Called by the system when the activity changes from fullscreen mode to multi-window mode and
- * visa-versa.
+ * visa-versa. This method provides the same configuration that will be sent in the following
+ * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode.
+ *
* @see android.R.attr#resizeableActivity
*
* @param isInMultiWindowMode True if the activity is in multi-window mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInMultiWindowMode}.
*/
+ public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ // Left deliberately empty. There should be no side effects if a direct
+ // subclass of Activity does not call super.
+ onMultiWindowModeChanged(isInMultiWindowMode);
+ }
+
+ /**
+ * Called by the system when the activity changes from fullscreen mode to multi-window mode and
+ * visa-versa.
+ *
+ * @see android.R.attr#resizeableActivity
+ *
+ * @param isInMultiWindowMode True if the activity is in multi-window mode.
+ *
+ * @deprecated Use {@link #onMultiWindowModeChanged(boolean, Configuration)} instead.
+ */
+ @Deprecated
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
// Left deliberately empty. There should be no side effects if a direct
// subclass of Activity does not call super.
@@ -1914,11 +1935,33 @@
}
/**
- * Called by the system when the activity changes to and from picture-in-picture mode.
+ * Called by the system when the activity changes to and from picture-in-picture mode. This
+ * method provides the same configuration that will be sent in the following
+ * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode.
+ *
* @see android.R.attr#supportsPictureInPicture
*
* @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInPictureInPictureMode}.
*/
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ // Left deliberately empty. There should be no side effects if a direct
+ // subclass of Activity does not call super.
+ onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+
+ /**
+ * Called by the system when the activity changes to and from picture-in-picture mode.
+ *
+ * @see android.R.attr#supportsPictureInPicture
+ *
+ * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ *
+ * @deprecated Use {@link #onPictureInPictureModeChanged(boolean, Configuration)} instead.
+ */
+ @Deprecated
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
// Left deliberately empty. There should be no side effects if a direct
// subclass of Activity does not call super.
@@ -6993,21 +7036,25 @@
}
}
- final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
+ final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
+ Configuration newConfig) {
if (DEBUG_LIFECYCLE) Slog.v(TAG,
- "dispatchMultiWindowModeChanged " + this + ": " + isInMultiWindowMode);
- mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode);
+ "dispatchMultiWindowModeChanged " + this + ": " + isInMultiWindowMode
+ + " " + newConfig);
+ mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
if (mWindow != null) {
mWindow.onMultiWindowModeChanged();
}
- onMultiWindowModeChanged(isInMultiWindowMode);
+ onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
}
- final void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ final void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
if (DEBUG_LIFECYCLE) Slog.v(TAG,
- "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode);
- mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
- onPictureInPictureModeChanged(isInPictureInPictureMode);
+ "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode
+ + " " + newConfig);
+ mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b5d1fa8..e49aad2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1411,15 +1411,23 @@
}
@Override
- public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode)
- throws RemoteException {
- sendMessage(H.MULTI_WINDOW_MODE_CHANGED, token, isInMultiWindowMode ? 1 : 0);
+ public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
+ Configuration overrideConfig) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = token;
+ args.arg2 = overrideConfig;
+ args.argi1 = isInMultiWindowMode ? 1 : 0;
+ sendMessage(H.MULTI_WINDOW_MODE_CHANGED, args);
}
@Override
- public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode)
- throws RemoteException {
- sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, token, isInPipMode ? 1 : 0);
+ public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
+ Configuration overrideConfig) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = token;
+ args.arg2 = overrideConfig;
+ args.argi1 = isInPipMode ? 1 : 0;
+ sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, args);
}
@Override
@@ -1816,10 +1824,14 @@
handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
break;
case MULTI_WINDOW_MODE_CHANGED:
- handleMultiWindowModeChanged((IBinder) msg.obj, msg.arg1 == 1);
+ handleMultiWindowModeChanged((IBinder) ((SomeArgs) msg.obj).arg1,
+ ((SomeArgs) msg.obj).argi1 == 1,
+ (Configuration) ((SomeArgs) msg.obj).arg2);
break;
case PICTURE_IN_PICTURE_MODE_CHANGED:
- handlePictureInPictureModeChanged((IBinder) msg.obj, msg.arg1 == 1);
+ handlePictureInPictureModeChanged((IBinder) ((SomeArgs) msg.obj).arg1,
+ ((SomeArgs) msg.obj).argi1 == 1,
+ (Configuration) ((SomeArgs) msg.obj).arg2);
break;
case LOCAL_VOICE_INTERACTION_STARTED:
handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
@@ -3119,17 +3131,27 @@
}
}
- private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) {
+ private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
+ Configuration overrideConfig) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
- r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode);
+ final Configuration newConfig = new Configuration(mConfiguration);
+ if (overrideConfig != null) {
+ newConfig.updateFrom(overrideConfig);
+ }
+ r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
}
}
- private void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode) {
+ private void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
+ Configuration overrideConfig) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
- r.activity.dispatchPictureInPictureModeChanged(isInPipMode);
+ final Configuration newConfig = new Configuration(mConfiguration);
+ if (overrideConfig != null) {
+ newConfig.updateFrom(overrideConfig);
+ }
+ r.activity.dispatchPictureInPictureModeChanged(isInPipMode, newConfig);
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index cbd7b9d..8292152 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -242,7 +242,7 @@
/** @hide */
public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64;
/** @hide Read the phone number. */
- public static final int OP_READ_PHONE_NUMBER = 65;
+ public static final int OP_READ_PHONE_NUMBERS = 65;
/** @hide Request package installs through package installer */
public static final int OP_REQUEST_INSTALL_PACKAGES = 66;
/** @hide Enter picture-in-picture. */
@@ -353,8 +353,8 @@
/** @hide Get device accounts. */
public static final String OPSTR_GET_ACCOUNTS
= "android:get_accounts";
- public static final String OPSTR_READ_PHONE_NUMBER
- = "android:read_phone_number";
+ public static final String OPSTR_READ_PHONE_NUMBERS
+ = "android:read_phone_numbers";
/** Access to picture-in-picture. */
public static final String OPSTR_PICTURE_IN_PICTURE
= "android:picture_in_picture";
@@ -391,7 +391,7 @@
OP_FINE_LOCATION,
// Phone
OP_READ_PHONE_STATE,
- OP_READ_PHONE_NUMBER,
+ OP_READ_PHONE_NUMBERS,
OP_CALL_PHONE,
OP_READ_CALL_LOG,
OP_WRITE_CALL_LOG,
@@ -487,7 +487,7 @@
OP_GET_ACCOUNTS,
OP_RUN_IN_BACKGROUND,
OP_AUDIO_ACCESSIBILITY_VOLUME,
- OP_READ_PHONE_NUMBER,
+ OP_READ_PHONE_NUMBERS,
OP_REQUEST_INSTALL_PACKAGES,
OP_PICTURE_IN_PICTURE,
OP_INSTANT_APP_START_FOREGROUND,
@@ -564,7 +564,7 @@
OPSTR_GET_ACCOUNTS,
null,
null, // OP_AUDIO_ACCESSIBILITY_VOLUME
- OPSTR_READ_PHONE_NUMBER,
+ OPSTR_READ_PHONE_NUMBERS,
null, // OP_REQUEST_INSTALL_PACKAGES
OPSTR_PICTURE_IN_PICTURE,
OPSTR_INSTANT_APP_START_FOREGROUND,
@@ -641,7 +641,7 @@
"GET_ACCOUNTS",
"RUN_IN_BACKGROUND",
"AUDIO_ACCESSIBILITY_VOLUME",
- "READ_PHONE_NUMBER",
+ "READ_PHONE_NUMBERS",
"REQUEST_INSTALL_PACKAGES",
"PICTURE_IN_PICTURE",
"INSTANT_APP_START_FOREGROUND",
@@ -718,7 +718,7 @@
Manifest.permission.GET_ACCOUNTS,
null, // no permission for running in background
null, // no permission for changing accessibility volume
- Manifest.permission.READ_PHONE_NUMBER,
+ Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.REQUEST_INSTALL_PACKAGES,
null, // no permission for entering picture-in-picture on hide
Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
@@ -796,7 +796,7 @@
null, // GET_ACCOUNTS
null, // RUN_IN_BACKGROUND
UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME
- null, // READ_PHONE_NUMBER
+ null, // READ_PHONE_NUMBERS
null, // REQUEST_INSTALL_PACKAGES
null, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
null, // INSTANT_APP_START_FOREGROUND
@@ -873,7 +873,7 @@
false, // GET_ACCOUNTS
false, // RUN_IN_BACKGROUND
false, // AUDIO_ACCESSIBILITY_VOLUME
- false, // READ_PHONE_NUMBER
+ false, // READ_PHONE_NUMBERS
false, // REQUEST_INSTALL_PACKAGES
false, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
false, // INSTANT_APP_START_FOREGROUND
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 02fe101..3102a93 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1716,19 +1716,55 @@
/**
* Called when the Fragment's activity changes from fullscreen mode to multi-window mode and
* visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the
+ * containing Activity. This method provides the same configuration that will be sent in the
+ * following {@link #onConfigurationChanged(Configuration)} call after the activity enters this
+ * mode.
+ *
+ * @param isInMultiWindowMode True if the activity is in multi-window mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInMultiWindowMode}.
+ */
+ public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ onMultiWindowModeChanged(isInMultiWindowMode);
+ }
+
+ /**
+ * Called when the Fragment's activity changes from fullscreen mode to multi-window mode and
+ * visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the
* containing Activity.
*
* @param isInMultiWindowMode True if the activity is in multi-window mode.
+ *
+ * @deprecated Use {@link #onMultiWindowModeChanged(boolean, Configuration)} instead.
*/
+ @Deprecated
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
}
/**
* Called by the system when the activity changes to and from picture-in-picture mode. This is
* generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity.
+ * This method provides the same configuration that will be sent in the following
+ * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode.
+ *
+ * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ * @param newConfig The new configuration of the activity with the state
+ * {@param isInPictureInPictureMode}.
+ */
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+
+ /**
+ * Called by the system when the activity changes to and from picture-in-picture mode. This is
+ * generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity.
*
* @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
+ *
+ * @deprecated Use {@link #onPictureInPictureModeChanged(boolean, Configuration)} instead.
*/
+ @Deprecated
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
}
@@ -2572,6 +2608,7 @@
}
}
+ @Deprecated
void performMultiWindowModeChanged(boolean isInMultiWindowMode) {
onMultiWindowModeChanged(isInMultiWindowMode);
if (mChildFragmentManager != null) {
@@ -2579,6 +2616,14 @@
}
}
+ void performMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ }
+ }
+
+ @Deprecated
void performPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
onPictureInPictureModeChanged(isInPictureInPictureMode);
if (mChildFragmentManager != null) {
@@ -2586,6 +2631,15 @@
}
}
+ void performPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode,
+ newConfig);
+ }
+ }
+
void performConfigurationChanged(Configuration newConfig) {
onConfigurationChanged(newConfig);
if (mChildFragmentManager != null) {
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 9ea15a0..cff94d8 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -250,20 +250,49 @@
* <p>Call when the multi-window mode of the activity changed.
*
* @see Fragment#onMultiWindowModeChanged
+ * @deprecated use {@link #dispatchMultiWindowModeChanged(boolean, Configuration)}
*/
+ @Deprecated
public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
mHost.mFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode);
}
/**
+ * Lets all Fragments managed by the controller's FragmentManager know the multi-window mode of
+ * the activity changed.
+ * <p>Call when the multi-window mode of the activity changed.
+ *
+ * @see Fragment#onMultiWindowModeChanged
+ */
+ public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
+ Configuration newConfig) {
+ mHost.mFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ }
+
+ /**
+ * Lets all Fragments managed by the controller's FragmentManager know the picture-in-picture
+ * mode of the activity changed.
+ * <p>Call when the picture-in-picture mode of the activity changed.
+ *
+ * @see Fragment#onPictureInPictureModeChanged
+ * @deprecated use {@link #dispatchPictureInPictureModeChanged(boolean, Configuration)}
+ */
+ @Deprecated
+ public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ mHost.mFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+
+ /**
* Lets all Fragments managed by the controller's FragmentManager know the picture-in-picture
* mode of the activity changed.
* <p>Call when the picture-in-picture mode of the activity changed.
*
* @see Fragment#onPictureInPictureModeChanged
*/
- public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
- mHost.mFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
+ public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ mHost.mFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode,
+ newConfig);
}
/**
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 0c1be07..279b900 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1844,6 +1844,10 @@
}
synchronized (this) {
if (mDestroyed || mHost == null) {
+ if (allowStateLoss) {
+ // This FragmentManager isn't attached, so drop the entire transaction.
+ return;
+ }
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
@@ -1960,6 +1964,10 @@
}
public void execSingleAction(OpGenerator action, boolean allowStateLoss) {
+ if (allowStateLoss && (mHost == null || mDestroyed)) {
+ // This FragmentManager isn't attached, so drop the entire transaction.
+ return;
+ }
ensureExecReady(allowStateLoss);
if (action.generateOps(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
@@ -2944,6 +2952,10 @@
}
}
+ /**
+ * @deprecated use {@link #dispatchMultiWindowModeChanged(boolean, Configuration)}
+ */
+ @Deprecated
public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
if (mAdded == null) {
return;
@@ -2956,6 +2968,23 @@
}
}
+ public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
+ Configuration newConfig) {
+ if (mAdded == null) {
+ return;
+ }
+ for (int i = mAdded.size() - 1; i >= 0; --i) {
+ final Fragment f = mAdded.get(i);
+ if (f != null) {
+ f.performMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ }
+ }
+ }
+
+ /**
+ * @deprecated use {@link #dispatchPictureInPictureModeChanged(boolean, Configuration)}
+ */
+ @Deprecated
public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
if (mAdded == null) {
return;
@@ -2968,6 +2997,19 @@
}
}
+ public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode,
+ Configuration newConfig) {
+ if (mAdded == null) {
+ return;
+ }
+ for (int i = mAdded.size() - 1; i >= 0; --i) {
+ final Fragment f = mAdded.get(i);
+ if (f != null) {
+ f.performPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+ }
+ }
+ }
+
public void dispatchConfigurationChanged(Configuration newConfig) {
if (mAdded != null) {
for (int i=0; i<mAdded.size(); i++) {
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index e99691d..6c43fe3 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -146,9 +146,10 @@
void notifyCleartextNetwork(in byte[] firstPacket);
void startBinderTracking();
void stopBinderTrackingAndDump(in ParcelFileDescriptor fd);
- void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode);
- void schedulePictureInPictureModeChanged(IBinder token,
- boolean isInPictureInPictureMode);
+ void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
+ in Configuration newConfig);
+ void schedulePictureInPictureModeChanged(IBinder token, boolean isInPictureInPictureMode,
+ in Configuration newConfig);
void scheduleLocalVoiceInteractionStarted(IBinder token,
IVoiceInteractor voiceInteractor);
void handleTrustStorageUpdate();
diff --git a/core/java/android/app/IServiceConnection.aidl b/core/java/android/app/IServiceConnection.aidl
index 6804071..97042aa 100644
--- a/core/java/android/app/IServiceConnection.aidl
+++ b/core/java/android/app/IServiceConnection.aidl
@@ -21,6 +21,6 @@
/** @hide */
oneway interface IServiceConnection {
- void connected(in ComponentName name, IBinder service);
+ void connected(in ComponentName name, IBinder service, boolean dead);
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index dbed1be..4205db0 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -88,8 +88,8 @@
* @hide
*/
public final class LoadedApk {
-
- private static final String TAG = "LoadedApk";
+ static final String TAG = "LoadedApk";
+ static final boolean DEBUG = false;
private final ActivityThread mActivityThread;
final String mPackageName;
@@ -641,8 +641,7 @@
final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
TextUtils.join(File.pathSeparator, zipPaths);
- if (ActivityThread.localLOGV)
- Slog.v(ActivityThread.TAG, "Class path: " + zip +
+ if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip +
", JNI path: " + librarySearchPath);
boolean needToSetupJitProfiles = false;
@@ -1371,12 +1370,14 @@
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
+ if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
+ if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
- map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
+ map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
@@ -1396,6 +1397,7 @@
if (map != null) {
sd = map.get(c);
if (sd != null) {
+ if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
map.remove(c);
sd.doForget();
if (map.size() == 0) {
@@ -1461,10 +1463,11 @@
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
- public void connected(ComponentName name, IBinder service) throws RemoteException {
+ public void connected(ComponentName name, IBinder service, boolean dead)
+ throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
- sd.connected(name, service);
+ sd.connected(name, service, dead);
}
}
}
@@ -1533,23 +1536,23 @@
return mUnbindLocation;
}
- public void connected(ComponentName name, IBinder service) {
+ public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 0));
+ mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
- doConnected(name, service);
+ doConnected(name, service, dead);
}
}
public void death(ComponentName name, IBinder service) {
if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 1));
+ mActivityThread.post(new RunConnection(name, service, 1, false));
} else {
doDeath(name, service);
}
}
- public void doConnected(ComponentName name, IBinder service) {
+ public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
@@ -1594,6 +1597,9 @@
if (old != null) {
mConnection.onServiceDisconnected(name);
}
+ if (dead) {
+ mConnection.onBindingDead(name);
+ }
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
@@ -1616,15 +1622,16 @@
}
private final class RunConnection implements Runnable {
- RunConnection(ComponentName name, IBinder service, int command) {
+ RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
+ mDead = dead;
}
public void run() {
if (mCommand == 0) {
- doConnected(mName, mService);
+ doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
@@ -1633,6 +1640,7 @@
final ComponentName mName;
final IBinder mService;
final int mCommand;
+ final boolean mDead;
}
private final class DeathMonitor implements IBinder.DeathRecipient
diff --git a/core/java/android/app/admin/DeviceAdminService.java b/core/java/android/app/admin/DeviceAdminService.java
new file mode 100644
index 0000000..cd0b1bf
--- /dev/null
+++ b/core/java/android/app/admin/DeviceAdminService.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.admin;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * Base class for a service that device owner/profile owners can optionally have.
+ *
+ * <p>The system searches for it with an intent filter with the
+ * {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} action, and tries to keep a bound
+ * connection as long as the hosting user is running, so that the device/profile owner is always
+ * considered to be in the foreground.
+ *
+ * <p>Device/profile owners can use
+ * {@link android.content.pm.PackageManager#setComponentEnabledSetting(ComponentName, int, int)}
+ * to disable/enable its own service. For example, when a device/profile owner no longer needs
+ * to be in the foreground, it can (and should) disable its service.
+ *
+ * <p>The service must not be exported.
+ *
+ * <p>TODO: Describe how the system handles crashes in DO/PO.
+ */
+public class DeviceAdminService extends Service {
+ private final IDeviceAdminServiceImpl mImpl;
+
+ public DeviceAdminService() {
+ mImpl = new IDeviceAdminServiceImpl();
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
+ return mImpl.asBinder();
+ }
+
+ private class IDeviceAdminServiceImpl extends IDeviceAdminService.Stub {
+ }
+
+ // So far, we have no methods in this class.
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6d8d5e9..2f0a630 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1515,6 +1515,16 @@
public @interface ProvisioningPreCondition {}
/**
+ * Service action: Action for a service that device owner and profile owner can optionally
+ * own. If a device owner or a profile owner has such a service, the system tries to keep
+ * a bound connection to it, in order to keep their process always running.
+ * The service must not be exported.
+ */
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_DEVICE_ADMIN_SERVICE
+ = "android.app.action.DEVICE_ADMIN_SERVICE";
+
+ /**
* Return true if the given administrator component is currently active (enabled) in the system.
*
* @param admin The administrator component to check for.
diff --git a/core/java/android/app/admin/IDeviceAdminService.aidl b/core/java/android/app/admin/IDeviceAdminService.aidl
new file mode 100644
index 0000000..5276ed5
--- /dev/null
+++ b/core/java/android/app/admin/IDeviceAdminService.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+/**
+ * @hide
+ */
+interface IDeviceAdminService {
+}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 124267b..7d2db5c 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -19,9 +19,12 @@
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.ViewStructure;
+import android.view.ViewStructure.HtmlInfo;
+import android.view.ViewStructure.HtmlInfo.Builder;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.autofill.AutoFillId;
@@ -597,6 +600,7 @@
AutofillValue mAutofillValue;
String[] mAutofillOptions;
boolean mSanitized;
+ HtmlInfo mHtmlInfo;
int mX;
int mY;
@@ -641,7 +645,6 @@
static final int FLAGS_HAS_CHILDREN = 0x00100000;
static final int FLAGS_HAS_URL = 0x00080000;
static final int FLAGS_HAS_INPUT_TYPE = 0x00040000;
- static final int FLAGS_HAS_ENTRY_ID = 0x00020000;
static final int FLAGS_HAS_LOCALE_LIST = 0x00010000;
static final int FLAGS_ALL_CONTROL = 0xfff00000;
@@ -677,8 +680,6 @@
mIdPackage = preader.readString();
}
}
- } else if ((flags&FLAGS_HAS_ENTRY_ID) != 0) {
- mIdEntry = preader.readString();
}
if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0) {
@@ -688,6 +689,10 @@
mAutofillHints = in.readStringArray();
mAutofillValue = in.readParcelable(null);
mAutofillOptions = in.readStringArray();
+ final Parcelable p = in.readParcelable(null);
+ if (p instanceof HtmlInfo) {
+ mHtmlInfo = (HtmlInfo) p;
+ }
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
mX = in.readInt();
@@ -756,8 +761,6 @@
int flags = mFlags & ~FLAGS_ALL_CONTROL;
if (mId != View.NO_ID) {
flags |= FLAGS_HAS_ID;
- } else if (mIdEntry != null ){
- flags |= FLAGS_HAS_ENTRY_ID;
}
if (mAutofillId != null) {
flags |= FLAGS_HAS_AUTOFILL_DATA;
@@ -821,8 +824,6 @@
pwriter.writeString(mIdPackage);
}
}
- } else if ((flags&FLAGS_HAS_ENTRY_ID) != 0) {
- pwriter.writeString(mIdEntry);
}
if ((flags&FLAGS_HAS_AUTOFILL_DATA) != 0) {
@@ -834,6 +835,11 @@
final AutofillValue sanitizedValue = writeSensitive ? mAutofillValue : null;
out.writeParcelable(sanitizedValue, 0);
out.writeStringArray(mAutofillOptions);
+ if (mHtmlInfo instanceof Parcelable) {
+ out.writeParcelable((Parcelable) mHtmlInfo, 0);
+ } else {
+ out.writeParcelable(null, 0);
+ }
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
out.writeInt(mX);
@@ -908,10 +914,6 @@
* If {@link #getId()} is a resource identifier, this is the entry name of that
* identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
* for more information.
- *
- * <p>If the node represents a virtual view, it could also represent the entry id set by
- * {@link android.view.ViewStructure#setIdEntry ViewStructure.setIdEntry}
- *
*/
public String getIdEntry() {
return mIdEntry;
@@ -1233,12 +1235,8 @@
/**
* Returns the URL represented by this node.
*
- * <p>Typically used in 2 categories of nodes:
- *
- * <ol>
- * <li>Root node (containing the URL of the HTML page)
- * <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
- * </ol>
+ * <p>Typically used when the view associated with the node is a container for an HTML
+ * document.
*
* <strong>WARNING:</strong> a {@link android.service.autofill.AutofillService} should only
* use this URL for autofill purposes when it trusts the app generating it (i.e., the app
@@ -1249,6 +1247,16 @@
}
/**
+ * Returns the HTML properties associated with this node.
+ *
+ * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
+ * for assist.
+ */
+ public HtmlInfo getHtmlInfo() {
+ return mHtmlInfo;
+ }
+
+ /**
* Returns the the list of locales associated with this node.
*/
public LocaleList getLocaleList() {
@@ -1393,11 +1401,6 @@
}
@Override
- public void setIdEntry(String entryName) {
- mNode.mIdEntry = entryName;
- }
-
- @Override
public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
mNode.mX = left;
mNode.mY = top;
@@ -1711,6 +1714,123 @@
public void setLocaleList(LocaleList localeList) {
mNode.mLocaleList = localeList;
}
+
+ @Override
+ public HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName) {
+ return new HtmlInfoNodeBuilder(tagName);
+ }
+
+ @Override
+ public void setHtmlInfo(@NonNull HtmlInfo htmlInfo) {
+ mNode.mHtmlInfo = htmlInfo;
+ }
+ }
+
+ private static final class HtmlInfoNode extends HtmlInfo implements Parcelable {
+ private final String mTag;
+ private final String[] mNames;
+ private final String[] mValues;
+
+ // Not parcelable
+ private ArrayList<Pair<String, String>> mAttributes;
+
+ private HtmlInfoNode(HtmlInfoNodeBuilder builder) {
+ mTag = builder.mTag;
+ if (builder.mNames == null) {
+ mNames = null;
+ mValues = null;
+ } else {
+ mNames = new String[builder.mNames.size()];
+ mValues = new String[builder.mValues.size()];
+ builder.mNames.toArray(mNames);
+ builder.mValues.toArray(mValues);
+ }
+ }
+
+ @Override
+ public String getTag() {
+ return mTag;
+ }
+
+ @Override
+ public ArrayList<Pair<String, String>> getAttributes() {
+ if (mAttributes == null && mNames != null) {
+ mAttributes = new ArrayList<>(mNames.length);
+ for (int i = 0; i < mNames.length; i++) {
+ final Pair<String, String> pair = new Pair<>(mNames[i], mValues[i]);
+ mAttributes.add(i, pair);
+ }
+ }
+ return mAttributes;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(mTag);
+ parcel.writeStringArray(mNames);
+ parcel.writeStringArray(mValues);
+ }
+
+ @SuppressWarnings("hiding")
+ public static final Creator<HtmlInfoNode> CREATOR = new Creator<HtmlInfoNode>() {
+ @Override
+ public HtmlInfoNode createFromParcel(Parcel parcel) {
+ // Always go through the builder to ensure the data ingested by
+ // the system obeys the contract of the builder to avoid attacks
+ // using specially crafted parcels.
+ final String tag = parcel.readString();
+ final HtmlInfoNodeBuilder builder = new HtmlInfoNodeBuilder(tag);
+ final String[] names = parcel.readStringArray();
+ final String[] values = parcel.readStringArray();
+ if (names != null && values != null) {
+ if (names.length != values.length) {
+ Log.w(TAG, "HtmlInfo attributes mismatch: names=" + names.length
+ + ", values=" + values.length);
+ } else {
+ for (int i = 0; i < names.length; i++) {
+ builder.addAttribute(names[i], values[i]);
+ }
+ }
+ }
+ return builder.build();
+ }
+
+ @Override
+ public HtmlInfoNode[] newArray(int size) {
+ return new HtmlInfoNode[size];
+ }
+ };
+ }
+
+ private static final class HtmlInfoNodeBuilder extends HtmlInfo.Builder {
+ private final String mTag;
+ private ArrayList<String> mNames;
+ private ArrayList<String> mValues;
+
+ HtmlInfoNodeBuilder(String tag) {
+ mTag = tag;
+ }
+
+ @Override
+ public Builder addAttribute(String name, String value) {
+ if (mNames == null) {
+ mNames = new ArrayList<>();
+ mValues = new ArrayList<>();
+ }
+ mNames.add(name);
+ mValues.add(value);
+ return this;
+ }
+
+ @Override
+ public HtmlInfoNode build() {
+ return new HtmlInfoNode(this);
+ }
}
/** @hide */
@@ -1813,6 +1933,12 @@
if (url != null) {
Log.i(TAG, prefix + " URL: " + url);
}
+ HtmlInfo htmlInfo = node.getHtmlInfo();
+ if (htmlInfo != null) {
+ Log.i(TAG, prefix + " HtmlInfo: tag=" + htmlInfo.getTag()
+ + ", attr="+ htmlInfo.getAttributes());
+ }
+
LocaleList localeList = node.getLocaleList();
if (localeList != null) {
Log.i(TAG, prefix + " LocaleList: " + localeList);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4e1e42d..845a47d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -638,6 +638,7 @@
* <p>
* Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
* supported on this device before calling this method.
+ * @hide
*/
public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
if (!getLeAccess())
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index aa61ce2..5d1e8ec 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -778,7 +778,7 @@
/**
* Set the preferred connection PHY for this app. Please note that this is just a
- * recommendation, wether the PHY change will happen depends on other applications peferences,
+ * recommendation, whether the PHY change will happen depends on other applications peferences,
* local and remote controller capabilities. Controller can override these settings.
* <p>
* {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index b35a593..2df2ed8 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -550,7 +550,7 @@
/**
* Set the preferred connection PHY for this app. Please note that this is just a
- * recommendation, wether the PHY change will happen depends on other applications peferences,
+ * recommendation, whether the PHY change will happen depends on other applications peferences,
* local and remote controller capabilities. Controller can override these settings.
* <p>
* {@link BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 98a5341..6bf6aa0 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -416,6 +416,11 @@
if(mSocketState != SocketState.INIT) return EBADFD;
if(mPfd == null) return -1;
FileDescriptor fd = mPfd.getFileDescriptor();
+ if (fd == null) {
+ Log.e(TAG, "bindListen(), null file descriptor");
+ return -1;
+ }
+
if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
mSocket = LocalSocket.createConnectedLocalSocket(fd);
if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
@@ -556,8 +561,9 @@
@Override
public void close() throws IOException {
- if (DBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: "
- + mSocketState);
+ Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
+ ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
+ "mSocket: " + mSocket + ", mSocketState: " + mSocketState);
if(mSocketState == SocketState.CLOSED)
return;
else
@@ -567,9 +573,6 @@
if(mSocketState == SocketState.CLOSED)
return;
mSocketState = SocketState.CLOSED;
- if (DBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort +
- ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS +
- "mSocket: " + mSocket);
if(mSocket != null) {
if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket);
mSocket.shutdownInput();
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 0825ee8..334e88b 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -52,10 +52,11 @@
void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
- in AdvertiseData periodicData, in int timeout, in IAdvertisingSetCallback callback);
+ in AdvertiseData periodicData, in int duration, in int maxExtAdvEvents,
+ in IAdvertisingSetCallback callback);
void stopAdvertisingSet(in IAdvertisingSetCallback callback);
- void enableAdvertisingSet(in int advertiserId, in boolean enable, in int timeout);
+ void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents);
void setAdvertisingData(in int advertiserId, in AdvertiseData data);
void setScanResponseData(in int advertiserId, in AdvertiseData data);
void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters);
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 7355b0d..51571b2 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
import android.bluetooth.le.IAdvertisingSetCallback;
@@ -57,15 +58,23 @@
/**
* Enables Advertising. This method returns immediately, the operation status is
- * delivered
- * through {@code callback.onAdvertisingEnabled()}.
+ * delivered through {@code callback.onAdvertisingEnabled()}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
*
+ * @param enable whether the advertising should be enabled (true), or disabled (false)
+ * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+ * 65535 (655,350 ms)
+ * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+ * controller shall attempt to send prior to terminating the extended
+ * advertising, even if the duration has not expired. Valid range is
+ * from 1 to 255.
*/
- public void enableAdvertising(boolean enable, int timeout) {
+ public void enableAdvertising(boolean enable, int duration,
+ int maxExtendedAdvertisingEvents) {
try {
- gatt.enableAdvertisingSet(this.advertiserId, enable, timeout);
+ gatt.enableAdvertisingSet(this.advertiserId, enable, duration,
+ maxExtendedAdvertisingEvents);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -77,10 +86,16 @@
* delivered through {@code callback.onAdvertisingDataSet()}.
* <p>
* Advertising data must be empty if non-legacy scannable advertising is used.
+ *
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags. If the
+ * update takes place when the advertising set is enabled, the data can be
+ * maximum 251 bytes long.
*/
- public void setAdvertisingData(AdvertiseData data) {
+ public void setAdvertisingData(AdvertiseData advertiseData) {
try {
- gatt.setAdvertisingData(this.advertiserId, data);
+ gatt.setAdvertisingData(this.advertiserId, advertiseData);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -90,10 +105,15 @@
* Set/update scan response data. Make sure that data doesn't exceed the size limit for
* specified AdvertisingSetParameters. This method returns immediately, the operation status
* is delivered through {@code callback.onScanResponseDataSet()}.
+ *
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * update takes place when the advertising set is enabled, the data can be
+ * maximum 251 bytes long.
*/
- public void setScanResponseData(AdvertiseData data) {
+ public void setScanResponseData(AdvertiseData scanResponse) {
try {
- gatt.setScanResponseData(this.advertiserId, data);
+ gatt.setScanResponseData(this.advertiserId, scanResponse);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -103,6 +123,8 @@
* Update advertising parameters associated with this AdvertisingSet. Must be called when
* advertising is not active. This method returns immediately, the operation status is delivered
* through {@code callback.onAdvertisingParametersUpdated}.
+ *
+ * @param parameters advertising set parameters.
*/
public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
try {
@@ -130,10 +152,15 @@
* or after advertising was started with periodic advertising data set. This method returns
* immediately, the operation status is delivered through
* {@code callback.onPeriodicAdvertisingDataSet()}.
+ *
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * update takes place when the periodic advertising is enabled for this set,
+ * the data can be maximum 251 bytes long.
*/
- public void setPeriodicAdvertisingData(AdvertiseData data) {
+ public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
try {
- gatt.setPeriodicAdvertisingData(this.advertiserId, data);
+ gatt.setPeriodicAdvertisingData(this.advertiserId, periodicData);
} catch (RemoteException e) {
Log.e(TAG, "remote exception - ", e);
}
@@ -142,6 +169,8 @@
/**
* Used to enable/disable periodic advertising. This method returns immediately, the operation
* status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
+ *
+ * @param enable whether the periodic advertising should be enabled (true), or disabled (false).
*/
public void setPeriodicAdvertisingEnable(boolean enable) {
try {
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index fe1f425..f5c1f08 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.bluetooth.BluetoothAdapter;
import android.os.Parcel;
import android.os.Parcelable;
@@ -279,7 +280,7 @@
* When set to true, advertising set will advertise 4.x Spec compliant
* advertisements.
*
- * @param isLegacy wether legacy advertising mode should be used.
+ * @param isLegacy whether legacy advertising mode should be used.
*/
public Builder setLegacyMode(boolean isLegacy) {
this.isLegacy = isLegacy;
@@ -287,12 +288,12 @@
}
/**
- * Set wether advertiser address should be ommited from all packets. If this
+ * Set whether advertiser address should be ommited from all packets. If this
* mode is used, periodic advertising can't be enabled for this set.
*
* This is used only if legacy mode is not used.
*
- * @param isAnonymous wether anonymous advertising should be used.
+ * @param isAnonymous whether anonymous advertising should be used.
*/
public Builder setAnonymous(boolean isAnonymous) {
this.isAnonymous = isAnonymous;
@@ -300,12 +301,12 @@
}
/**
- * Set wether TX power should be included in the extended header.
+ * Set whether TX power should be included in the extended header.
*
* This is used only if legacy mode is not used.
*
- * @param includeTxPower wether TX power should be included in extended
- * header
+ * @param includeTxPower whether TX power should be included in extended
+ * header
*/
public Builder setIncludeTxPower(boolean includeTxPower) {
this.includeTxPower = includeTxPower;
@@ -317,6 +318,8 @@
*
* This is used only if legacy mode is not used.
*
+ * Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
+ * supported on this device.
* @param primaryPhy Primary advertising physical channel, can only be
* {@link AdvertisingSetParameters#PHY_LE_1M} or
* {@link AdvertisingSetParameters#PHY_LE_CODED}.
@@ -335,6 +338,10 @@
*
* This is used only if legacy mode is not used.
*
+ * Use {@link BluetoothAdapter#isLeCodedPhySupported} and
+ * {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is
+ * supported on this device.
+ *
* @param secondaryPhy Secondary advertising physical channel, can only be
* one of {@link AdvertisingSetParameters#PHY_LE_1M},
* {@link AdvertisingSetParameters#PHY_LE_2M} or
@@ -393,6 +400,32 @@
* Build the {@link AdvertisingSetParameters} object.
*/
public AdvertisingSetParameters build() {
+ if (isLegacy) {
+ if (isAnonymous) {
+ throw new IllegalArgumentException("Legacy advertising can't be anonymous");
+ }
+
+ if (connectable == true && scannable == false) {
+ throw new IllegalArgumentException(
+ "Legacy advertisement can't be connectable and non-scannable");
+ }
+
+ if (includeTxPower) {
+ throw new IllegalArgumentException(
+ "Legacy advertising can't include TX power level in header");
+ }
+ } else {
+ if (connectable && scannable) {
+ throw new IllegalArgumentException(
+ "Advertising can't be both connectable and scannable");
+ }
+
+ if (isAnonymous && connectable) {
+ throw new IllegalArgumentException(
+ "Advertising can't be both connectable and anonymous");
+ }
+ }
+
return new AdvertisingSetParameters(connectable, scannable, isLegacy, isAnonymous,
includeTxPower, primaryPhy,
secondaryPhy, interval, txPowerLevel);
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 242ee77..a9deb75 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -50,13 +50,13 @@
private static final String TAG = "BluetoothLeAdvertiser";
- private static final int MAX_ADVERTISING_DATA_BYTES = 31;
+ private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
+ private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31;
// Each fields need one byte for field length and another byte for field type.
private static final int OVERHEAD_BYTES_PER_FIELD = 2;
// Flags field will be set by system.
private static final int FLAGS_FIELD_BYTES = 3;
private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
- private static final int SERVICE_DATA_UUID_LENGTH = 2;
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
@@ -117,8 +117,8 @@
throw new IllegalArgumentException("callback cannot be null");
}
boolean isConnectable = settings.isConnectable();
- if (totalBytes(advertiseData, isConnectable) > MAX_ADVERTISING_DATA_BYTES ||
- totalBytes(scanResponse, false) > MAX_ADVERTISING_DATA_BYTES) {
+ if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES ||
+ totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
return;
}
@@ -149,10 +149,16 @@
parameters.setTxPowerLevel(1);
}
+ int duration = 0;
+ int timeoutMillis = settings.getTimeout();
+ if (timeoutMillis > 0) {
+ duration = (timeoutMillis < 10) ? 1 : timeoutMillis/10;
+ }
+
AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
mLegacyAdvertisers.put(callback, wrapped);
startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
- settings.getTimeout(), wrapped);
+ duration, 0, wrapped);
}
}
@@ -206,90 +212,202 @@
}
/**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicData Periodic advertising data.
- * @param callback Callback for advertising set.
- */
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param callback Callback for advertising set.
+ * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller.
+ */
public void startAdvertisingSet(AdvertisingSetParameters parameters,
AdvertiseData advertiseData, AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData, AdvertisingSetCallback callback) {
startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, 0, callback, new Handler(Looper.getMainLooper()));
+ periodicData, 0, 0, callback, new Handler(Looper.getMainLooper()));
}
/**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicData Periodic advertising data.
- * @param callback Callback for advertising set.
- * @param handler thread upon which the callbacks will be invoked.
- */
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param callback Callback for advertising set.
+ * @param handler thread upon which the callbacks will be invoked.
+ * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller.
+ */
public void startAdvertisingSet(AdvertisingSetParameters parameters,
AdvertiseData advertiseData, AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData, AdvertisingSetCallback callback,
Handler handler) {
startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, 0, callback, handler);
+ periodicData, 0, 0, callback, handler);
}
/**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicData Periodic advertising data.
- * @param timeoutMillis Advertising time limit. May not exceed 180000
- * @param callback Callback for advertising set.
- */
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
+ * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+ * 65535 (655,350 ms). 0 means advertising should continue until stopped.
+ * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+ * controller shall attempt to send prior to terminating the extended
+ * advertising, even if the duration has not expired. Valid range is
+ * from 1 to 255. 0 means no maximum.
+ * @param callback Callback for advertising set.
+ * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller.
+ */
public void startAdvertisingSet(AdvertisingSetParameters parameters,
AdvertiseData advertiseData, AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
- AdvertiseData periodicData, int timeoutMillis,
+ AdvertiseData periodicData, int duration,
+ int maxExtendedAdvertisingEvents,
AdvertisingSetCallback callback) {
startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, timeoutMillis, callback, new Handler(Looper.getMainLooper()));
+ periodicData, duration, maxExtendedAdvertisingEvents, callback,
+ new Handler(Looper.getMainLooper()));
}
/**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicData Periodic advertising data.
- * @param timeoutMillis Advertising time limit. May not exceed 180000
- * @param callback Callback for advertising set.
- * @param handler thread upon which the callbacks will be invoked.
- */
+ * Creates a new advertising set. If operation succeed, device will start advertising. This
+ * method returns immediately, the operation status is delivered through
+ * {@code callback.onAdvertisingSetStarted()}.
+ * <p>
+ * @param parameters Advertising set parameters.
+ * @param advertiseData Advertisement data to be broadcasted. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
+ * advertisement is connectable, three bytes will be added for flags.
+ * @param scanResponse Scan response associated with the advertisement data. Size must not
+ * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
+ * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will
+ * not be started.
+ * @param periodicData Periodic advertising data. Size must not exceed
+ * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
+ * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to
+ * 65535 (655,350 ms). 0 means advertising should continue until stopped.
+ * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
+ * controller shall attempt to send prior to terminating the extended
+ * advertising, even if the duration has not expired. Valid range is
+ * from 1 to 255. 0 means no maximum.
+ * @param callback Callback for advertising set.
+ * @param handler Thread upon which the callbacks will be invoked.
+ * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable
+ * size, or unsupported advertising PHY is selected, or when attempt to use
+ * Periodic Advertising feature is made when it's not supported by the
+ * controller, or when maxExtendedAdvertisingEvents is used on a controller
+ * that doesn't support the LE Extended Advertising
+ */
public void startAdvertisingSet(AdvertisingSetParameters parameters,
AdvertiseData advertiseData, AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
- AdvertiseData periodicData, int timeoutMillis,
- AdvertisingSetCallback callback, Handler handler) {
+ AdvertiseData periodicData, int duration,
+ int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback,
+ Handler handler) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
+ boolean isConnectable = parameters.isConnectable();
+ if (parameters.isLegacy()) {
+ if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
+ throw new IllegalArgumentException("Legacy advertising data too big");
+ }
+
+ if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
+ throw new IllegalArgumentException("Legacy scan response data too big");
+ }
+ } else {
+ boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
+ boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
+ int pphy = parameters.getPrimaryPhy();
+ int sphy = parameters.getSecondaryPhy();
+ if (pphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy) {
+ throw new IllegalArgumentException("Unsupported primary PHY selected");
+ }
+
+ if ((sphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy)
+ || (sphy == AdvertisingSetParameters.PHY_LE_2M && !support2MPhy)) {
+ throw new IllegalArgumentException("Unsupported secondary PHY selected");
+ }
+
+ int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
+ if (totalBytes(advertiseData, isConnectable) > maxData) {
+ throw new IllegalArgumentException("Advertising data too big");
+ }
+
+ if (totalBytes(scanResponse, false) > maxData) {
+ throw new IllegalArgumentException("Scan response data too big");
+ }
+
+ if (totalBytes(periodicData, false) > maxData) {
+ throw new IllegalArgumentException("Periodic advertising data too big");
+ }
+
+ boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
+ if (periodicParameters != null && periodicParameters.getEnable() && !supportPeriodic) {
+ throw new IllegalArgumentException(
+ "Controller does not support LE Periodic Advertising");
+ }
+ }
+
+ if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) {
+ throw new IllegalArgumentException(
+ "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents);
+ }
+
+ if (maxExtendedAdvertisingEvents != 0 &&
+ !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
+ throw new IllegalArgumentException(
+ "Can't use maxExtendedAdvertisingEvents with controller that don't support " +
+ "LE Extended Advertising");
+ }
+
+ if (duration < 0 || duration > 65535) {
+ throw new IllegalArgumentException("duration out of range: " + duration);
+ }
+
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
@@ -306,7 +424,7 @@
try {
gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, timeoutMillis, wrapped);
+ periodicData, duration, maxExtendedAdvertisingEvents, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start advertising set - ", e);
throw new IllegalStateException("Failed to start advertising set");
@@ -383,7 +501,8 @@
}
}
for (ParcelUuid uuid : data.getServiceData().keySet()) {
- size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH
+ int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
+ size += OVERHEAD_BYTES_PER_FIELD + uuidLen
+ byteLength(data.getServiceData().get(uuid));
}
for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
index 6616231..364b575 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
@@ -23,6 +23,7 @@
* advertising operation status.
*
* @see PeriodicAdvertisingManager#createSync
+ * @hide
*/
public abstract class PeriodicAdvertisingCallback {
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
index 12c8a8c..d9c2d88 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
@@ -37,6 +37,7 @@
* <p>
* <b>Note:</b> Most of the methods here require
* {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ * @hide
*/
public final class PeriodicAdvertisingManager {
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
index ebc92bd..149540c 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
@@ -93,7 +93,7 @@
private int interval = INTERVAL_MAX;
/**
- * Set wether the Periodic Advertising should be enabled for this set.
+ * Set whether the Periodic Advertising should be enabled for this set.
*/
public Builder setEnable(boolean enable) {
this.enable = enable;
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
index 3ff4ca5..51b93cb 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
@@ -24,6 +24,7 @@
/**
* PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
+ * @hide
*/
public final class PeriodicAdvertisingReport implements Parcelable {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 116224b..da887af 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -16,8 +16,6 @@
package android.content;
-import static android.content.ContentProvider.maybeAddUserId;
-
import android.annotation.AnyRes;
import android.annotation.BroadcastBehavior;
import android.annotation.IntDef;
@@ -43,6 +41,7 @@
import android.os.ShellCommand;
import android.os.StrictMode;
import android.os.UserHandle;
+import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
@@ -50,9 +49,7 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
-
import com.android.internal.util.XmlUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -70,6 +67,8 @@
import java.util.Objects;
import java.util.Set;
+import static android.content.ContentProvider.maybeAddUserId;
+
/**
* An intent is an abstract description of an operation to be performed. It
* can be used with {@link Context#startActivity(Intent) startActivity} to
@@ -1093,6 +1092,8 @@
* <p>Output: nothing.
* @hide
*/
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
/**
* Activity action: Perform a call to any number (emergency or not)
@@ -1102,6 +1103,8 @@
* <p>Output: nothing.
* @hide
*/
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
/**
@@ -3349,6 +3352,32 @@
ACTION_DYNAMIC_SENSOR_CHANGED = "android.intent.action.DYNAMIC_SENSOR_CHANGED";
/**
+ * Broadcast Action: The default subscription has changed. This has the following
+ * extra values:</p>
+ * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED
+ = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
+
+ /**
+ * Broadcast Action: The default sms subscription has changed. This has the following
+ * extra values:</p>
+ * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms
+ * subscription index
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
+ = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+
+ /**
+ * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and
+ * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription
+ * which has changed.
+ */
+ public static final String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
+
+ /**
* Deprecated - use {@link #ACTION_FACTORY_RESET} instead.
*
* {@hide}
@@ -3868,23 +3897,9 @@
public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
/**
- * A content: URI holding a stream of data associated with the Intent, used
- * with {@link #ACTION_SEND} to supply the data being sent.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN} this value
- * will be automatically promoted to {@link Intent#setClipData(ClipData)}
- * when that value is not already defined.
- * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#O} this value will be
- * automatically demoted from {@link Intent#getClipData()} when this value
- * is not already defined.
- *
- * @deprecated apps should use {@link Intent#setClipData(ClipData)} and
- * {@link Intent#getClipData()} instead of this extra, since
- * only those APIs can extend temporary permission grants to the
- * underlying resource.
+ * A content: URI holding a stream of data associated with the Intent,
+ * used with {@link #ACTION_SEND} to supply the data being sent.
*/
- @Deprecated
public static final String EXTRA_STREAM = "android.intent.extra.STREAM";
/**
@@ -9429,21 +9444,6 @@
mContentUserHint = UserHandle.USER_CURRENT;
}
}
-
- // If someone is sending us ClipData, but not EXTRA_STREAM, offer to
- // downgrade that content for older apps to find
- if (mClipData != null && mClipData.getItemCount() > 0 && !hasExtra(EXTRA_STREAM)) {
- final String action = getAction();
- if (ACTION_SEND.equals(action)) {
- putExtra(EXTRA_STREAM, mClipData.getItemAt(0).getUri());
- } else if (ACTION_SEND_MULTIPLE.equals(action)) {
- final ArrayList<Uri> list = new ArrayList<>();
- for (int i = 0; i < mClipData.getItemCount(); i++) {
- list.add(mClipData.getItemAt(i).getUri());
- }
- putExtra(EXTRA_STREAM, list);
- }
- }
}
/**
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index d115ce4..8e428f9 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -37,7 +37,7 @@
* @param service The IBinder of the Service's communication channel,
* which you can now make calls on.
*/
- public void onServiceConnected(ComponentName name, IBinder service);
+ void onServiceConnected(ComponentName name, IBinder service);
/**
* Called when a connection to the Service has been lost. This typically
@@ -49,5 +49,18 @@
* @param name The concrete component name of the service whose
* connection has been lost.
*/
- public void onServiceDisconnected(ComponentName name);
+ void onServiceDisconnected(ComponentName name);
+
+ /**
+ * Called when the binding to this connection is dead. This means the
+ * interface will never receive another connection. The application will
+ * need to unbind and rebind the connection to activate it again. This may
+ * happen, for example, if the application hosting the service it is bound to
+ * has been updated.
+ *
+ * @param name The concrete component name of the service whose
+ * connection is dead.
+ */
+ default void onBindingDead(ComponentName name) {
+ }
}
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 41311eb..c08bd1d 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -55,8 +55,7 @@
String callingPackage, String packageName, int flags, in UserHandle user);
ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
- in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
- in UserHandle user);
+ in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
boolean startShortcut(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index abdef08..4d76755 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -275,11 +275,8 @@
@Deprecated
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
- /**
- * Include chooser shortcuts in the result.
- * STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
- * relevant fields from the Shortcut. This should also be adequately documented.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public static final int FLAG_MATCH_CHOOSER = 1 << 4;
/**
@@ -319,7 +316,6 @@
FLAG_MATCH_DYNAMIC,
FLAG_MATCH_PINNED,
FLAG_MATCH_MANIFEST,
- FLAG_MATCH_CHOOSER,
FLAG_GET_KEY_FIELDS_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
@@ -336,9 +332,6 @@
@Nullable
ComponentName mActivity;
- @Nullable
- Intent mIntent;
-
@QueryFlags
int mQueryFlags;
@@ -382,11 +375,9 @@
return this;
}
- /**
- * If non-null, returns only shortcuts with intent filters that match this intent.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public ShortcutQuery setIntent(@Nullable Intent intent) {
- mIntent = intent;
return this;
}
@@ -428,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.");
}
}
@@ -704,7 +695,7 @@
try {
return mService.getShortcuts(mContext.getPackageName(),
query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
- query.mIntent, query.mQueryFlags, user)
+ query.mQueryFlags, user)
.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 136c13b..a493f33 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2158,7 +2158,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";
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 16d582ef..7bfde75 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -310,12 +310,18 @@
List<String> overlayPackageNames);
/**
- * Resolves an intent, allowing instant apps to be resolved.
+ * Resolves an activity intent, allowing instant apps to be resolved.
*/
public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId);
/**
+ * Resolves a service intent, allowing instant apps to be resolved.
+ */
+ public abstract ResolveInfo resolveService(Intent intent, String resolvedType,
+ int flags, int userId, int callingUid);
+
+ /**
* Track the creator of a new isolated uid.
* @param isolatedUid The newly created isolated uid.
* @param ownerUid The uid of the app that created the isolated process.
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 5201694..3f4a090 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,7 +21,6 @@
import android.annotation.UserIdInt;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -40,12 +39,10 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -99,14 +96,6 @@
public static final int FLAG_ADAPTIVE_BITMAP = 1 << 9;
/** @hide */
- public static final int FLAG_CHOOSER = 1 << 10;
-
- /**
- * TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
- * due to the context in which it was retrieved.
- * TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
- * @hide
- */
@IntDef(flag = true,
value = {
FLAG_DYNAMIC,
@@ -119,7 +108,6 @@
FLAG_STRINGS_RESOLVED,
FLAG_IMMUTABLE,
FLAG_ADAPTIVE_BITMAP,
- FLAG_CHOOSER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -214,24 +202,6 @@
@Nullable
private PersistableBundle[] mIntentPersistableExtrases;
- /**
- * If used in a chooser, extras that should be added into the intent passed through.
- */
- @Nullable
- private PersistableBundle mChooserExtras;
-
- /**
- * Intent filters to be used if the shortcut is to be used in a chooser context.
- */
- @Nullable
- private IntentFilter[] mChooserIntentFilters;
-
- /**
- * Component names corresponding to the above intent filters.
- */
- @Nullable
- private ComponentName[] mChooserComponentNames;
-
private int mRank;
/**
@@ -281,13 +251,6 @@
mDisabledMessageResId = b.mDisabledMessageResId;
mCategories = cloneCategories(b.mCategories);
mIntents = cloneIntents(b.mIntents);
- if (b.mChooserIntentFilters != null) {
- mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
- }
- if (b.mChooserComponentNames != null) {
- mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
- }
- mChooserExtras = b.mChooserExtras;
fixUpIntentExtras();
mRank = b.mRank;
mExtras = b.mExtras;
@@ -368,28 +331,8 @@
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
-
- // For a shortcut to be valid, there should either be an Intent, or a non-empty set of
- // intent filters.
- if (mIntents == null || mIntents.length == 0) {
- Preconditions.checkNotNull(mChooserIntentFilters,
- "Intent must be provided if not a chooser target");
- Preconditions.checkNotNull(mChooserComponentNames,
- "Intent must be provided if not a chooser target");
- }
-
- // If ChooserIntentFilter are provided, they should match the length of the provided
- // component names.
- if (mChooserIntentFilters != null) {
- if (mChooserComponentNames == null
- || mChooserIntentFilters.length != mChooserComponentNames.length) {
- throw new IllegalArgumentException("Inconsistent intent filters and "
- + "component names given");
- }
- if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
- throw new IllegalArgumentException("Empty intent filter and component names given");
- }
- }
+ Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
+ Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
}
/**
@@ -434,10 +377,6 @@
mDisabledMessageResName = source.mDisabledMessageResName;
mIconResName = source.mIconResName;
}
- // TODO: Omit these by default and add a new clone flag.
- mChooserIntentFilters = source.mChooserIntentFilters;
- mChooserComponentNames = source.mChooserComponentNames;
- mChooserExtras = source.mChooserExtras;
} else {
// Set this bit.
mFlags |= FLAG_KEY_FIELDS_ONLY;
@@ -565,25 +504,6 @@
}
/**
- * Whether the shortcut has any intentFilter matching the passed in one.
- * @hide
- */
- @VisibleForTesting
- public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
- if (mChooserIntentFilters == null) {
- return false;
- }
- for (IntentFilter filter : mChooserIntentFilters) {
- int match = filter.match(resolver, intent, false, TAG);
- if (match > 0) {
- return true;
- }
- }
- return false;
- }
-
-
- /**
* Extract the entry name from a fully-donated resource name.
* e.g. "com.android.app1:drawable/icon1" -> "icon1"
* @hide
@@ -766,15 +686,6 @@
if (source.mExtras != null) {
mExtras = source.mExtras;
}
- if (source.mChooserExtras != null) {
- mChooserExtras = source.mChooserExtras;
- }
- if (source.mChooserIntentFilters != null) {
- mChooserIntentFilters = source.mChooserIntentFilters;
- }
- if (source.mChooserComponentNames != null) {
- mChooserComponentNames = source.mChooserComponentNames;
- }
}
/**
@@ -836,12 +747,6 @@
private PersistableBundle mExtras;
- private PersistableBundle mChooserExtras;
-
- private List<IntentFilter> mChooserIntentFilters;
-
- private List<ComponentName> mChooserComponentNames;
-
/**
* Old style constructor.
* @hide
@@ -1127,37 +1032,17 @@
return this;
}
- /**
- * Extras that can be added which will be added to the Intent used to launch the app if
- * launched from a chooser context.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public Builder setChooserExtras(@NonNull PersistableBundle extras) {
- mChooserExtras = extras;
return this;
}
- /**
- * IntentFilters and the components that should resolve a match for a given chooser target.
- * If multiple matches are found, the component corresponding to the closest match will be
- * used.
- *
- * @param filter IntendFilter that if matched will have the intent forwarded to the given
- * component
- * @param name The component that an intent that passes this filter will resolve to.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
@NonNull ComponentName name) {
- Preconditions.checkNotNull(filter, "intent filter cannot be null");
- Preconditions.checkNotNull(name, "component name cannot be null");
-
- if (mChooserIntentFilters == null || mChooserComponentNames == null) {
- mChooserIntentFilters = new ArrayList<>();
- mChooserComponentNames = new ArrayList<>();
- }
-
- mChooserIntentFilters.add(filter);
- mChooserComponentNames.add(name);
return this;
}
@@ -1361,28 +1246,25 @@
return mIntentPersistableExtrases;
}
- /**
- * Retrieve the extras that will be added in to any intent launched through the chooser.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public PersistableBundle getChooserExtras() {
- return mChooserExtras;
+ return new PersistableBundle();
}
- /**
- * Retrieve the list of intent filters for chooser targets.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public IntentFilter[] getChooserIntentFilters() {
- return mChooserIntentFilters;
+ return new IntentFilter[0];
}
- /**
- * Retrieve the list of component names corresponding to the above intent filters.
- */
+ /** @deprecated punted, don't use. */
+ @Deprecated
@NonNull
public ComponentName[] getChooserComponentNames() {
- return mChooserComponentNames;
+ return new ComponentName[0];
}
/**
@@ -1506,9 +1388,10 @@
return hasFlags(FLAG_PINNED);
}
- /** Return whether a shortcut can be shown in the chooser. */
+ /** @deprecated punted, don't use. */
+ @Deprecated
public boolean isChooser() {
- return hasFlags(FLAG_CHOOSER);
+ return false;
}
/**
@@ -1539,14 +1422,6 @@
return isPinned() && !(isDynamic() || isManifestShortcut());
}
- /**
- * @return true if pinned but neither static nor dynamic.
- * @hide
- */
- public boolean isDynamicOrChooser() {
- return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
- }
-
/** @hide */
public boolean isOriginallyFromManifest() {
return hasFlags(FLAG_IMMUTABLE);
@@ -1829,19 +1704,6 @@
mCategories.add(source.readString().intern());
}
}
-
- // We put a placeholder empty array in to keep the parcelable order, but can do away with
- // them at this point if they're empty.
- mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
- if (mChooserComponentNames.length == 0) {
- mChooserComponentNames = null;
- }
-
- mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
- if (mChooserIntentFilters.length == 0) {
- mChooserIntentFilters = null;
- }
- mChooserExtras = source.readPersistableBundle(cl);
}
@Override
@@ -1888,17 +1750,6 @@
} else {
dest.writeInt(0);
}
- if (mChooserComponentNames != null) {
- dest.writeParcelableArray(mChooserComponentNames, flags);
- } else {
- dest.writeParcelableArray(new ComponentName[0], flags);
- }
- if (mChooserIntentFilters != null) {
- dest.writeParcelableArray(mChooserIntentFilters, flags);
- } else {
- dest.writeParcelableArray(new IntentFilter[0], flags);
- }
- dest.writePersistableBundle(mChooserExtras);
}
public static final Creator<ShortcutInfo> CREATOR =
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 3de19d1..7b7d8ae 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -45,8 +45,8 @@
getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName, @Nullable Intent intent,
- @ShortcutQuery.QueryFlags int flags, int userId);
+ @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
+ int userId);
public abstract boolean
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 99fbee1..c8353c9 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,6 +16,11 @@
package android.content.res;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.DisplayInfo;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -293,6 +298,16 @@
*/
public int screenLayout;
+ /**
+ * @hide
+ * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
+ * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
+ * the display level. Lower levels can override these values to provide custom bounds to enforce
+ * features such as a max aspect ratio.
+ * TODO(b/36812336): Move appBounds out of {@link Configuration}.
+ */
+ public Rect appBounds;
+
/** @hide */
static public int resetScreenLayout(int curLayout) {
return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
@@ -882,6 +897,7 @@
compatScreenWidthDp = o.compatScreenWidthDp;
compatScreenHeightDp = o.compatScreenHeightDp;
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
+ setAppBounds(o.appBounds);
assetsSeq = o.assetsSeq;
seq = o.seq;
}
@@ -1032,6 +1048,9 @@
case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
default: sb.append("/"); sb.append(navigationHidden); break;
}
+ if (appBounds != null) {
+ sb.append(" appBounds="); sb.append(appBounds);
+ }
if (assetsSeq != 0) {
sb.append(" as.").append(assetsSeq);
}
@@ -1066,6 +1085,7 @@
smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
densityDpi = DENSITY_DPI_UNDEFINED;
assetsSeq = ASSETS_SEQ_UNDEFINED;
+ appBounds = null;
seq = 0;
}
@@ -1253,6 +1273,10 @@
if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
}
+ if (delta.appBounds != null && !delta.appBounds.equals(appBounds)) {
+ changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ setAppBounds(delta.appBounds);
+ }
if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED) {
changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
assetsSeq = delta.assetsSeq;
@@ -1399,6 +1423,13 @@
changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
}
+ // Make sure that one of the values is not null and that they are not equal.
+ if ((compareUndefined || delta.appBounds != null)
+ && appBounds != delta.appBounds
+ && (appBounds == null || !appBounds.equals(delta.appBounds))) {
+ changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ }
+
return changed;
}
@@ -1494,6 +1525,7 @@
dest.writeInt(compatScreenWidthDp);
dest.writeInt(compatScreenHeightDp);
dest.writeInt(compatSmallestScreenWidthDp);
+ dest.writeValue(appBounds);
dest.writeInt(assetsSeq);
dest.writeInt(seq);
}
@@ -1529,6 +1561,7 @@
compatScreenWidthDp = source.readInt();
compatScreenHeightDp = source.readInt();
compatSmallestScreenWidthDp = source.readInt();
+ appBounds = (Rect) source.readValue(null);
assetsSeq = source.readInt();
seq = source.readInt();
}
@@ -1706,6 +1739,33 @@
/**
* @hide
*
+ * Helper method for setting the app bounds.
+ */
+ public void setAppBounds(Rect rect) {
+ if (rect == null) {
+ appBounds = null;
+ return;
+ }
+
+ setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
+ }
+
+ /**
+ * @hide
+ *
+ * Helper method for setting the app bounds.
+ */
+ public void setAppBounds(int left, int top, int right, int bottom) {
+ if (appBounds == null) {
+ appBounds = new Rect();
+ }
+
+ appBounds.set(left, top, right, bottom);
+ }
+
+ /**
+ * @hide
+ *
* Clears the locale without changing layout direction.
*/
public void clearLocales() {
@@ -2212,6 +2272,7 @@
private static final String XML_ATTR_SCREEN_HEIGHT = "height";
private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
private static final String XML_ATTR_DENSITY = "density";
+ private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
/**
* Reads the attributes corresponding to Configuration member fields from the Xml parser.
@@ -2261,6 +2322,8 @@
SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
DENSITY_DPI_UNDEFINED);
+ configOut.appBounds =
+ Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
// For persistence, we don't care about assetsSeq, so do not read it out.
}
@@ -2332,6 +2395,11 @@
XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
}
+ if (config.appBounds != null) {
+ XmlUtils.writeStringAttribute(xml, XML_ATTR_APP_BOUNDS,
+ config.appBounds.flattenToString());
+ }
+
// For persistence, we do not care about assetsSeq, so do not write it out.
}
}
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/StatFs.java b/core/java/android/os/StatFs.java
index 13e9a15..d9e516c 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -61,15 +61,15 @@
*/
@Deprecated
public int getBlockSize() {
- return (int) mStat.f_bsize;
+ return (int) mStat.f_frsize;
}
/**
* The size, in bytes, of a block on the file system. This corresponds to
- * the Unix {@code statvfs.f_bsize} field.
+ * the Unix {@code statvfs.f_frsize} field.
*/
public long getBlockSizeLong() {
- return mStat.f_bsize;
+ return mStat.f_frsize;
}
/**
@@ -112,7 +112,7 @@
* will want to use {@link #getAvailableBytes()} instead.
*/
public long getFreeBytes() {
- return mStat.f_bfree * mStat.f_bsize;
+ return mStat.f_bfree * mStat.f_frsize;
}
/**
@@ -136,13 +136,13 @@
* applications.
*/
public long getAvailableBytes() {
- return mStat.f_bavail * mStat.f_bsize;
+ return mStat.f_bavail * mStat.f_frsize;
}
/**
* The total number of bytes supported by the file system.
*/
public long getTotalBytes() {
- return mStat.f_blocks * mStat.f_bsize;
+ return mStat.f_blocks * mStat.f_frsize;
}
}
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 23134cd..d921ed4 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -29,6 +29,8 @@
* new alarm or timer should use
* {@link android.content.Context#startActivity Context.startActivity()} so that
* the user has the option of choosing which alarm clock application to use.
+ *
+ * Android TV devices may not support the alarm intents.
*/
public final class AlarmClock {
/**
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/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 8e01030..56b267f 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -19,11 +19,13 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Dialog;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Handler;
import android.os.IBinder;
@@ -34,6 +36,8 @@
import android.view.View.OnAttachStateChangeListener;
import android.view.WindowManager;
+import com.android.internal.R;
+
/**
* A TileService provides the user a tile that can be added to Quick Settings.
* Quick Settings is a space provided that allows the user to change settings and
@@ -425,6 +429,15 @@
}
/**
+ * @return True if the device supports quick settings and its assocated APIs.
+ * @hide
+ */
+ @TestApi
+ public static boolean isQuickSettingsSupported() {
+ return Resources.getSystem().getBoolean(R.bool.config_quickSettingsSupported);
+ }
+
+ /**
* Requests that a tile be put in the listening state so it can send an update.
*
* This method is only applicable to tiles that have {@link #META_DATA_ACTIVE_TILE} defined
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index d84502f..f65f397 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -592,10 +592,21 @@
static {
DIR_TYPE_CACHE = new byte[DIR_TYPE_CACHE_SIZE];
for (int i = 0; i < DIR_TYPE_CACHE_SIZE; i++) {
+ // Calling Character.getDirectionality() is OK here, since new emojis start after
+ // the end of our cache.
DIR_TYPE_CACHE[i] = Character.getDirectionality(i);
}
}
+ private static byte getDirectionality(int codePoint) {
+ if (Emoji.isNewEmoji(codePoint)) {
+ // TODO: Fix or remove once emoji-data.text 5.0 is in ICU or update to 6.0.
+ return Character.DIRECTIONALITY_OTHER_NEUTRALS;
+ } else {
+ return Character.getDirectionality(codePoint);
+ }
+ }
+
// Internal instance variables.
/**
@@ -809,7 +820,7 @@
* cache.
*/
private static byte getCachedDirectionality(char c) {
- return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : Character.getDirectionality(c);
+ return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : getDirectionality(c);
}
/**
@@ -826,7 +837,7 @@
if (Character.isHighSurrogate(lastChar)) {
int codePoint = Character.codePointAt(text, charIndex);
charIndex += Character.charCount(codePoint);
- return Character.getDirectionality(codePoint);
+ return getDirectionality(codePoint);
}
charIndex++;
byte dirType = getCachedDirectionality(lastChar);
@@ -856,7 +867,7 @@
if (Character.isLowSurrogate(lastChar)) {
int codePoint = Character.codePointBefore(text, charIndex);
charIndex -= Character.charCount(codePoint);
- return Character.getDirectionality(codePoint);
+ return getDirectionality(codePoint);
}
charIndex--;
byte dirType = getCachedDirectionality(lastChar);
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index ee016c1..d33aad9 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -65,22 +65,32 @@
return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER_BASE);
}
- // Returns true if the character has Emoji property.
- public static boolean isEmoji(int codePoint) {
+ /**
+ * Returns true if the character is a new emoji still not supported in our version of ICU.
+ */
+ public static boolean isNewEmoji(int codePoint) {
// Emoji characters new in Unicode emoji 5.0.
// From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
// TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
- if ((0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
+ if (codePoint < 0x1F6F7 || codePoint > 0x1F9E6) {
+ // Optimization for characters outside the new emoji range.
+ return false;
+ }
+ return (0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
|| codePoint == 0x1F91F
|| (0x1F928 <= codePoint && codePoint <= 0x1F92F)
|| (0x1F931 <= codePoint && codePoint <= 0x1F932)
|| codePoint == 0x1F94C
|| (0x1F95F <= codePoint && codePoint <= 0x1F96B)
|| (0x1F992 <= codePoint && codePoint <= 0x1F997)
- || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6)) {
- return true;
- }
- return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);
+ || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6);
+ }
+
+ /**
+ * Returns true if the character has Emoji property.
+ */
+ public static boolean isEmoji(int codePoint) {
+ return isNewEmoji(codePoint) || UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);
}
// Returns true if the character can be a base character of COMBINING ENCLOSING KEYCAP.
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/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 3d11dcb..0cec496 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -562,12 +562,10 @@
outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
- width = (configuration != null
- && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED)
- ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width;
- height = (configuration != null
- && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED)
- ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height;
+ width = configuration != null && configuration.appBounds != null
+ ? configuration.appBounds.width() : width;
+ height = configuration != null && configuration.appBounds != null
+ ? configuration.appBounds.height() : height;
outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index ae1ee42..d25e5f0 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -118,7 +118,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();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 884283d..b12a767 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -25523,7 +25523,7 @@
* <p>
* The tooltip will be displayed:
* <ul>
- * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
+ * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
* menu). </li>
* <li>On hover, after a brief delay since the pointer has stopped moving </li>
* </ul>
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 65f3c90..b157709 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -22,9 +22,12 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.LocaleList;
+import android.util.Pair;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
+import java.util.ArrayList;
+
/**
* Container for storing additional per-view data generated by {@link View#onProvideStructure
* View.onProvideStructure} and {@link View#onProvideAutofillStructure
@@ -43,17 +46,6 @@
public abstract void setId(int id, String packageName, String typeName, String entryName);
/**
- * Sets the name of the identifier for this view.
- *
- * <p>Typically used when adding virtual children (through
- * {@link #asyncNewChild(int)}) that does not map to Android {@link View}
- * - otherwise, it's better to call {@link #setId(int, String, String, String)}.
- *
- * @param entryName The entry name of the view's identifier, or {@code null} if there is none.
- */
- public abstract void setIdEntry(String entryName);
-
- /**
* Set the basic dimensions of this view.
*
* @param left The view's left position, in pixels relative to its parent's left edge.
@@ -372,13 +364,7 @@
/**
* Sets the URL represented by this node.
*
- * <p>Typically used in the following situations:
- *
- * <ol>
- * <li>In a {@link android.app.assist.AssistStructure.WindowNode#getRootViewNode()}, to set up
- * the main URL of an HTML page.
- * <li>On child nodes represening hyperlinks.
- * </ol>
+ * <p>Typically used when the view is a container for an HTML document.
*/
public abstract void setUrl(String url);
@@ -386,4 +372,64 @@
* Sets the the list of locales associated with this node.
*/
public abstract void setLocaleList(LocaleList localeList);
+
+ /**
+ * Creates a new {@link HtmlInfo.Builder} for the given HTML tag.
+ *
+ * @param tagName name of the HTML tag.
+ * @return a new builder.
+ */
+ public abstract HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName);
+
+ /**
+ * Sets the HTML properties of this node when it represents an HTML element.
+ *
+ * <p>Should only be set when the node is used for autofill purposes - it will be ignored
+ * when used for assist.
+ *
+ * @param htmlInfo HTML properties.
+ */
+ public abstract void setHtmlInfo(@NonNull HtmlInfo htmlInfo);
+
+ /**
+ * Simplified representation of the HTML properties of a node that represents an HTML element.
+ */
+ public abstract static class HtmlInfo {
+
+ /**
+ * Gets the HTML tag.
+ */
+ @NonNull
+ public abstract String getTag();
+
+ /**
+ * Gets the list of HTML attributes.
+ *
+ * @return list of key/value pairs; could contain pairs with the same keys.
+ */
+ @Nullable
+ public abstract ArrayList<Pair<String, String>> getAttributes();
+
+ /**
+ * Builder for {@link HtmlInfo} objects.
+ */
+ public abstract static class Builder {
+
+ /**
+ * Adds an HTML attribute.
+ *
+ * @param name name of the attribute.
+ * @param value value of the attribute.
+ * @return same builder, for chaining.
+ */
+ public abstract Builder addAttribute(@NonNull String name, @NonNull String value);
+
+ /**
+ * Builds the {@link HtmlInfo} object.
+ *
+ * @return a new {@link HtmlInfo} instance.
+ */
+ public abstract HtmlInfo build();
+ }
+ }
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 79b0420..958d761 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1018,9 +1018,20 @@
}
}
- /** @hide */
+ /**
+ * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
+ * is publicly released because previous implementations of that class had relied on this method
+ * via reflection.
+ *
+ * @deprecated This is a hidden API. You should never use this.
+ * @hide
+ */
+ @Deprecated
public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
try {
+ Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
+ + "soon. If you are using android.support.v7.widget.SearchView, please update "
+ + "to version 26.0 or newer version.");
mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 9582b72..3f72fde 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -42,7 +42,6 @@
import android.os.RemoteException;
import android.print.PrintDocumentAdapter;
import android.security.KeyChain;
-import android.text.InputType;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -2641,49 +2640,55 @@
* understood by the {@link android.service.autofill.AutofillService} implementations:
*
* <ol>
- * <li>{@link ViewStructure#setClassName(String)} should be use to describe the type of node:
- * <ol>
- * <li>If the Android SDK provides a similar View, the full-qualified class name of that
- * view should be used.
- * <li>Otherwise, the class name should be {@code HTML.iframe}.
- * </ol>
+ * <li>If the Android SDK provides a similar View, then should be set with the
+ * fully-qualified class name of such view.
* <li>The W3C autofill field ({@code autocomplete} tag attribute) maps to
* {@link ViewStructure#setAutofillHints(String[])}.
* <li>The {@code type} attribute of {@code INPUT} tags maps to
* {@link ViewStructure#setInputType(int)}.
- * <li>The {@code name} attribute maps to {@link ViewStructure#setIdEntry(String)}.
* <li>The {@code value} attribute maps to {@link ViewStructure#setText(CharSequence)}.
* <li>The {@code placeholder} attribute maps to {@link ViewStructure#setHint(CharSequence)}.
* <li>{@link ViewStructure#setDataIsSensitive(boolean)} whould only be called with
* {@code true} for form fields whose {@code value} attribute was not pre-loaded.
+ * <li>Other HTML attributes can be represented through
+ * {@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}.
* </ol>
*
* <p>Example1: an HTML form with 2 fields for username and password.
*
* <pre class="prettyprint">
- * <input type="text" name="username" value="mr.sparkle" autocomplete="username" placeholder="Email or username">
- * <input type="password" name="password" autocomplete="current-password" placeholder="Password">
+ * <input type="text" name="username" id="user" value="mr.sparkle" autocomplete="username" placeholder="Email or username">
+ * <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password">
* </pre>
*
* <p>Would map to:
*
* <pre class="prettyprint">
- * ViewStructure username = //structure.newChildForAutofill(...);
+ * int index = structure.addChildCount(2);
+ * ViewStructure username = structure.newChild(index);
+ * username.setAutofillId(structure, 1); // id 1 - first child
* username.setClassName("input");
* username.setInputType("android.widget.EditText");
* username.setAutofillHints("username");
- * username.setIdEntry("username");
+ * username.setHtmlInfo(child.newHtmlInfoBuilder("input")
+ * .addAttribute("name", "username")
+ * .addAttribute("id", "user")
+ * .build());
* username.setHint("Email or username");
* username.setAutofillType(View.AUTOFILL_TYPE_TEXT);
* username.setAutofillValue(AutofillValue.forText("mr.sparkle"));
* username.setText("mr.sparkle");
* username.setDataIsSensitive(true); // Contains real username, which is sensitive
*
- * ViewStructure password = //structure.newChildForAutofill(...);
+ * ViewStructure password = structure.newChild(index + 1);
+ * username.setAutofillId(structure, 2); // id 2 - second child
* password.setInputType("android.widget.EditText");
* password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
* password.setAutofillHints("current-password");
- * password.setIdEntry("password");
+ * password.setHtmlInfo(child.newHtmlInfoBuilder("input")
+ * .addAttribute("name", "password")
+ * .addAttribute("id", "pass")
+ * .build());
* password.setHint("Password");
* password.setAutofillType(View.AUTOFILL_TYPE_TEXT);
* password.setDataIsSensitive(false); // Value is not set
@@ -2698,9 +2703,11 @@
* <p>Would map to:
*
* <pre class="prettyprint">
- * ViewStructure iframe = //structure.newChildForAutofill(...);
- * iframe.setClassName("HTML.iframe");
- * iframe.setUrl("http://example.com/login");
+ * int index = structure.addChildCount(1);
+ * ViewStructure iframe = structure.newChildFor(index);
+ * iframe.setHtmlInfo(child.newHtmlInfoBuilder("iframe")
+ * .addAttribute("url", "http://example.com/login")
+ * .build());
* </pre>
*/
@Override
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c235ebd..df65659 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -23,21 +23,15 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
-import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
@@ -362,7 +356,6 @@
mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
}
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
- mChooserRowAdapter.updateRowScales();
mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
adapterView.setAdapter(mChooserRowAdapter);
if (listView != null) {
@@ -849,9 +842,7 @@
return false;
}
intent.setComponent(mChooserTarget.getComponentName());
- if (mChooserTarget.getIntentExtras() != null) {
- intent.putExtras(mChooserTarget.getIntentExtras());
- }
+ intent.putExtras(mChooserTarget.getIntentExtras());
// Important: we will ignore the target security checks in ActivityManager
// if and only if the ChooserTarget's target package is the same package
@@ -934,8 +925,6 @@
private static final int MAX_SERVICE_TARGETS = 8;
private static final int MAX_TARGETS_PER_SERVICE = 4;
- private boolean mAreChooserShortcutsRetrieved;
-
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
private final List<TargetInfo> mCallerTargets = new ArrayList<>();
private boolean mShowServiceTargets;
@@ -1027,21 +1016,6 @@
if (mServiceTargets != null) {
pruneServiceTargets();
}
-
- if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
-
- if (!mAreChooserShortcutsRetrieved) {
- LauncherApps launcherApps = getLauncherApps();
- LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
- query.setIntent(getTargetIntent());
- query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
- List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query,
- android.os.Process.myUserHandle());
- if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
- addShortcuts(shortcuts);
- mAreChooserShortcutsRetrieved = true;
- }
-
if (DEBUG) Log.d(TAG, "List built querying services");
queryTargetServices(this);
}
@@ -1067,7 +1041,6 @@
public int getServiceTargetCount() {
if (!mShowServiceTargets) {
- if (DEBUG) Log.d("TAG", "Hiding service targets");
return 0;
}
return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
@@ -1159,71 +1132,6 @@
notifyDataSetChanged();
}
- // TODO: Pushed targets need to be scored correctly
- public void addShortcuts(List<ShortcutInfo> infos) {
- for (ShortcutInfo info : infos) {
- List<ChooserTarget> newTargets = new ArrayList<>();
- final ComponentName cn = info.getActivity();
- ActivityInfo ai;
- ResolveInfo ri = new ResolveInfo();
- if (cn != null) {
- try {
- ai = getPackageManager().getActivityInfo(cn, 0);
- ri.activityInfo = ai;
- UserManager userManager =
- (UserManager) getSystemService(Context.USER_SERVICE);
- ri.iconResourceId = ai.icon;
- ri.labelRes = ai.labelRes;
- ri.resolvePackageName = ai.packageName;
- ri.activityInfo.applicationInfo = new ApplicationInfo(
- ri.activityInfo.applicationInfo);
- ri.activityInfo.applicationInfo = ai.applicationInfo;
- ri.activityInfo.applicationInfo.uid = getUserId();
- } catch (PackageManager.NameNotFoundException ignored) {
- if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
- continue;
- }
- }
-
- DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
- ri,
- info.getShortLabel(),
- info.getLongLabel(),
- getTargetIntent());
-
- int bestMatch = 0;
- ComponentName bestComponent = null;
- for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
- int newMatch = info.getChooserIntentFilters()[i]
- .match(getContentResolver(), getTargetIntent(), false, TAG);
- if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
- if (newMatch > bestMatch) {
- bestMatch = newMatch;
- bestComponent = info.getChooserComponentNames()[i];
- }
- }
- if (bestMatch == 0) {
- Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
- return;
- }
-
- Bundle extrasToAdd =
- info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
- if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
- newTargets.add(new ChooserTarget(
- info.getShortLabel(),
- info.getIcon(),
- 1,
- bestComponent,
- extrasToAdd));
- addServiceResults(resolveInfo, newTargets);
- }
- if (mChooserRowAdapter != null) {
- mChooserRowAdapter.updateRowScales();
- }
- setShowServiceTargets(true);
- }
-
/**
* Set to true to reveal all service targets at once.
*/
@@ -1338,7 +1246,37 @@
@Override
public void onChanged() {
super.onChanged();
- updateRowScales();
+ final int rcount = getServiceTargetRowCount();
+ if (mServiceTargetScale == null
+ || mServiceTargetScale.length != rcount) {
+ RowScale[] old = mServiceTargetScale;
+ int oldRCount = old != null ? old.length : 0;
+ mServiceTargetScale = new RowScale[rcount];
+ if (old != null && rcount > 0) {
+ System.arraycopy(old, 0, mServiceTargetScale, 0,
+ Math.min(old.length, rcount));
+ }
+
+ for (int i = rcount; i < oldRCount; i++) {
+ old[i].cancelAnimation();
+ }
+
+ for (int i = oldRCount; i < rcount; i++) {
+ final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
+ .setInterpolator(mInterpolator);
+ mServiceTargetScale[i] = rs;
+ }
+
+ // Start the animations in a separate loop.
+ // The process of starting animations will result in
+ // binding views to set up initial values, and we must
+ // have ALL of the new RowScale objects created above before
+ // we get started.
+ for (int i = oldRCount; i < rcount; i++) {
+ mServiceTargetScale[i].startAnimation();
+ }
+ }
+
notifyDataSetChanged();
}
@@ -1355,40 +1293,6 @@
});
}
- void updateRowScales() {
- final int rcount = getServiceTargetRowCount();
- if (mServiceTargetScale == null
- || mServiceTargetScale.length != rcount) {
- if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
- RowScale[] old = mServiceTargetScale;
- int oldRCount = old != null ? old.length : 0;
- mServiceTargetScale = new RowScale[rcount];
- if (old != null && rcount > 0) {
- System.arraycopy(old, 0, mServiceTargetScale, 0,
- Math.min(old.length, rcount));
- }
-
- for (int i = rcount; i < oldRCount; i++) {
- old[i].cancelAnimation();
- }
-
- for (int i = oldRCount; i < rcount; i++) {
- final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
- .setInterpolator(mInterpolator);
- mServiceTargetScale[i] = rs;
- }
-
- // Start the animations in a separate loop.
- // The process of starting animations will result in
- // binding views to set up initial values, and we must
- // have ALL of the new RowScale objects created above before
- // we get started.
- for (int i = oldRCount; i < rcount; i++) {
- mServiceTargetScale[i].startAnimation();
- }
- }
- }
-
private float getRowScale(int rowPosition) {
final int start = getCallerTargetRowCount();
final int end = start + getServiceTargetRowCount();
@@ -1659,10 +1563,6 @@
}
}
- public LauncherApps getLauncherApps() {
- return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
- }
-
static class ServiceResultInfo {
public final DisplayResolveInfo originalTarget;
public final List<ChooserTarget> resultTargets;
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index 8edd637..088e726 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.os.ProxyFileDescriptorCallback;
import android.os.Handler;
+import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.OsConstants;
@@ -28,10 +29,11 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ThreadFactory;
-public class FuseAppLoop {
+public class FuseAppLoop implements Handler.Callback {
private static final String TAG = "FuseAppLoop";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final int ROOT_INODE = 1;
@@ -43,13 +45,11 @@
}
};
private static final int FUSE_OK = 0;
+ private static final int ARGS_POOL_SIZE = 50;
private final Object mLock = new Object();
private final int mMountPointId;
private final Thread mThread;
- private final Handler mDefaultHandler;
-
- private static final int CMD_FSYNC = 1;
@GuardedBy("mLock")
private final SparseArray<CallbackEntry> mCallbackMap = new SparseArray<>();
@@ -57,6 +57,9 @@
@GuardedBy("mLock")
private final BytesMap mBytesMap = new BytesMap();
+ @GuardedBy("mLock")
+ private final LinkedList<Args> mArgsPool = new LinkedList<>();
+
/**
* Sequential number can be used as file name and inode in AppFuse.
* 0 is regarded as an error, 1 is mount point. So we start the number from 2.
@@ -83,7 +86,6 @@
}
});
mThread.start();
- mDefaultHandler = null;
}
public int registerCallback(@NonNull ProxyFileDescriptorCallback callback,
@@ -110,7 +112,8 @@
break;
}
}
- mCallbackMap.put(id, new CallbackEntry(callback, handler));
+ mCallbackMap.put(id, new CallbackEntry(
+ callback, new Handler(handler.getLooper(), this)));
return id;
}
}
@@ -137,78 +140,113 @@
// Defined in FuseBuffer.h
private static final int FUSE_MAX_WRITE = 256 * 1024;
+ @Override
+ public boolean handleMessage(Message msg) {
+ final Args args = (Args) msg.obj;
+ final CallbackEntry entry = args.entry;
+ final long inode = args.inode;
+ final long unique = args.unique;
+ final int size = args.size;
+ final long offset = args.offset;
+ final byte[] data = args.data;
+
+ try {
+ switch (msg.what) {
+ case FUSE_LOOKUP: {
+ final long fileSize = entry.callback.onGetSize();
+ synchronized (mLock) {
+ if (mInstance != 0) {
+ native_replyLookup(mInstance, unique, inode, fileSize);
+ }
+ recycleLocked(args);
+ }
+ break;
+ }
+ case FUSE_GETATTR: {
+ final long fileSize = entry.callback.onGetSize();
+ synchronized (mLock) {
+ if (mInstance != 0) {
+ native_replyGetAttr(mInstance, unique, inode, fileSize);
+ }
+ recycleLocked(args);
+ }
+ break;
+ }
+ case FUSE_READ:
+ final int readSize = entry.callback.onRead(
+ offset, size, data);
+ synchronized (mLock) {
+ if (mInstance != 0) {
+ native_replyRead(mInstance, unique, readSize, data);
+ }
+ recycleLocked(args);
+ }
+ break;
+ case FUSE_WRITE:
+ final int writeSize = entry.callback.onWrite(offset, size, data);
+ synchronized (mLock) {
+ if (mInstance != 0) {
+ native_replyWrite(mInstance, unique, writeSize);
+ }
+ recycleLocked(args);
+ }
+ break;
+ case FUSE_FSYNC:
+ entry.callback.onFsync();
+ synchronized (mLock) {
+ if (mInstance != 0) {
+ native_replySimple(mInstance, unique, FUSE_OK);
+ }
+ recycleLocked(args);
+ }
+ break;
+ case FUSE_RELEASE:
+ entry.callback.onRelease();
+ synchronized (mLock) {
+ if (mInstance != 0) {
+ native_replySimple(mInstance, unique, FUSE_OK);
+ }
+ mBytesMap.stopUsing(entry.getThreadId());
+ recycleLocked(args);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown FUSE command: " + msg.what);
+ }
+ } catch (Exception error) {
+ synchronized (mLock) {
+ Log.e(TAG, "", error);
+ replySimpleLocked(unique, getError(error));
+ recycleLocked(args);
+ }
+ }
+
+ return true;
+ }
+
// Called by JNI.
@SuppressWarnings("unused")
private void onCommand(int command, long unique, long inode, long offset, int size,
byte[] data) {
- synchronized(mLock) {
+ synchronized (mLock) {
try {
- final CallbackEntry entry = getCallbackEntryOrThrowLocked(inode);
- entry.postRunnable(() -> {
- try {
- switch (command) {
- case FUSE_LOOKUP: {
- final long fileSize = entry.callback.onGetSize();
- synchronized (mLock) {
- if (mInstance != 0) {
- native_replyLookup(mInstance, unique, inode, fileSize);
- }
- }
- break;
- }
- case FUSE_GETATTR: {
- final long fileSize = entry.callback.onGetSize();
- synchronized (mLock) {
- if (mInstance != 0) {
- native_replyGetAttr(mInstance, unique, inode, fileSize);
- }
- }
- break;
- }
- case FUSE_READ:
- final int readSize = entry.callback.onRead(offset, size, data);
- synchronized (mLock) {
- if (mInstance != 0) {
- native_replyRead(mInstance, unique, readSize, data);
- }
- }
- break;
- case FUSE_WRITE:
- final int writeSize = entry.callback.onWrite(offset, size, data);
- synchronized (mLock) {
- if (mInstance != 0) {
- native_replyWrite(mInstance, unique, writeSize);
- }
- }
- break;
- case FUSE_FSYNC:
- entry.callback.onFsync();
- synchronized (mLock) {
- if (mInstance != 0) {
- native_replySimple(mInstance, unique, FUSE_OK);
- }
- }
- break;
- case FUSE_RELEASE:
- entry.callback.onRelease();
- synchronized (mLock) {
- if (mInstance != 0) {
- native_replySimple(mInstance, unique, FUSE_OK);
- }
- mBytesMap.stopUsing(entry.getThreadId());
- }
- break;
- default:
- throw new IllegalArgumentException(
- "Unknown FUSE command: " + command);
- }
- } catch (Exception error) {
- Log.e(TAG, "", error);
- replySimple(unique, getError(error));
- }
- });
- } catch (ErrnoException error) {
- Log.e(TAG, "", error);
+ final Args args;
+ if (mArgsPool.size() == 0) {
+ args = new Args();
+ } else {
+ args = mArgsPool.pop();
+ }
+ args.unique = unique;
+ args.inode = inode;
+ args.offset = offset;
+ args.size = size;
+ args.data = data;
+ args.entry = getCallbackEntryOrThrowLocked(inode);
+ if (!args.entry.handler.sendMessage(
+ Message.obtain(args.entry.handler, command, 0, 0, args))) {
+ throw new ErrnoException("onCommand", OsConstants.EBADF);
+ }
+ } catch (Exception error) {
replySimpleLocked(unique, getError(error));
}
}
@@ -253,9 +291,9 @@
return entry;
}
- private void replySimple(long unique, int result) {
- synchronized (mLock) {
- replySimpleLocked(unique, result);
+ private void recycleLocked(Args args) {
+ if (mArgsPool.size() < ARGS_POOL_SIZE) {
+ mArgsPool.add(args);
}
}
@@ -296,13 +334,6 @@
long getThreadId() {
return handler.getLooper().getThread().getId();
}
-
- void postRunnable(Runnable runnable) throws ErrnoException {
- final boolean result = handler.post(runnable);
- if (!result) {
- throw new ErrnoException("postRunnable", OsConstants.EBADF);
- }
- }
}
/**
@@ -342,4 +373,13 @@
mEntries.clear();
}
}
+
+ private static class Args {
+ long unique;
+ long inode;
+ long offset;
+ int size;
+ byte[] data;
+ CallbackEntry entry;
+ }
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 64e1d10..4659d3c 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -16,7 +16,12 @@
package com.android.internal.util;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Handler;
+import android.util.Slog;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -25,6 +30,9 @@
* Helper functions for dumping the state of system services.
*/
public final class DumpUtils {
+ private static final String TAG = "DumpUtils";
+ private static final boolean DEBUG = true;
+
private DumpUtils() {
}
@@ -55,4 +63,90 @@
public interface Dump {
void dump(PrintWriter pw, String prefix);
}
+
+ private static void logMessage(PrintWriter pw, String msg) {
+ if (DEBUG) Slog.v(TAG, msg);
+ pw.println(msg);
+ }
+
+ /**
+ * Verify that caller holds {@link android.Manifest.permission#DUMP}.
+ *
+ * @return true if access should be granted.
+ * @hide
+ */
+ public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+ if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " due to missing android.permission.DUMP permission");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Verify that caller holds
+ * {@link android.Manifest.permission#PACKAGE_USAGE_STATS} and that they
+ * have {@link AppOpsManager#OP_GET_USAGE_STATS} access.
+ *
+ * @return true if access should be granted.
+ * @hide
+ */
+ public static boolean checkUsageStatsPermission(Context context, String tag, PrintWriter pw) {
+ // System internals always get access
+ final int uid = Binder.getCallingUid();
+ switch (uid) {
+ case android.os.Process.ROOT_UID:
+ case android.os.Process.SYSTEM_UID:
+ case android.os.Process.SHELL_UID:
+ return true;
+ }
+
+ // Caller always needs to hold permission
+ if (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+ != PackageManager.PERMISSION_GRANTED) {
+ logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " due to missing android.permission.PACKAGE_USAGE_STATS permission");
+ return false;
+ }
+
+ // And finally, caller needs to have appops access; this is totally
+ // hacky, but it's the easiest way to wire this up without retrofitting
+ // Binder.dump() to pass through package names.
+ final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+ final String[] pkgs = context.getPackageManager().getPackagesForUid(uid);
+ if (pkgs != null) {
+ for (String pkg : pkgs) {
+ if (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid,
+ pkg) == AppOpsManager.MODE_ALLOWED) {
+ appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg);
+ if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+ + "android:get_usage_stats access");
+ return true;
+ }
+ }
+ }
+
+ logMessage(pw, "Permission Denial: can't dump " + tag + " from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " due to android:get_usage_stats app-op not allowed");
+ return false;
+ }
+
+ /**
+ * Verify that caller holds both {@link android.Manifest.permission#DUMP}
+ * and {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, and that
+ * they have {@link AppOpsManager#OP_GET_USAGE_STATS} access.
+ *
+ * @return true if access should be granted.
+ * @hide
+ */
+ public static boolean checkDumpAndUsageStatsPermission(Context context, String tag,
+ PrintWriter pw) {
+ return checkDumpPermission(context, tag, pw) && checkUsageStatsPermission(context, tag, pw);
+ }
}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index e64a574..3dc1be6 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -39,6 +39,7 @@
jfieldID gOptions_heightFieldID;
jfieldID gOptions_mimeFieldID;
jfieldID gOptions_outConfigFieldID;
+jfieldID gOptions_outColorSpaceFieldID;
jfieldID gOptions_mCancelID;
jfieldID gOptions_bitmapFieldID;
@@ -50,6 +51,20 @@
jclass gBitmapConfig_class;
jmethodID gBitmapConfig_nativeToConfigMethodID;
+jclass gColorSpace_class;
+jmethodID gColorSpace_getMethodID;
+jmethodID gColorSpace_matchMethodID;
+
+jclass gColorSpaceRGB_class;
+jmethodID gColorSpaceRGB_constructorMethodID;
+
+jclass gColorSpace_Named_class;
+jfieldID gColorSpace_Named_sRGBFieldID;
+jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
+
+jclass gTransferParameters_class;
+jmethodID gTransferParameters_constructorMethodID;
+
using namespace android;
jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
@@ -228,6 +243,70 @@
needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
}
+static jobject getColorSpace(JNIEnv* env,
+ sk_sp<SkColorSpace>& decodeColorSpace, SkColorType decodeColorType) {
+ jobject colorSpace = nullptr;
+
+ // No need to match, we know what the output color space will be
+ if (decodeColorType == kRGBA_F16_SkColorType) {
+ jobject linearExtendedSRGB = env->GetStaticObjectField(
+ gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
+ colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_getMethodID, linearExtendedSRGB);
+ } else {
+ // Same here, no need to match
+ if (decodeColorSpace->isSRGB()) {
+ jobject sRGB = env->GetStaticObjectField(
+ gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
+ colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_getMethodID, sRGB);
+ } else if (decodeColorSpace.get() != nullptr) {
+ // Try to match against known RGB color spaces using the CIE XYZ D50
+ // conversion matrix and numerical transfer function parameters
+ SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+ LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
+
+ SkColorSpaceTransferFn transferParams;
+ // We can only handle numerical transfer functions at the moment
+ LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
+
+ jobject params = env->NewObject(gTransferParameters_class,
+ gTransferParameters_constructorMethodID,
+ transferParams.fA, transferParams.fB, transferParams.fC,
+ transferParams.fD, transferParams.fE, transferParams.fF,
+ transferParams.fG);
+
+ jfloatArray xyzArray = env->NewFloatArray(9);
+ jfloat xyz[9] = {
+ xyzMatrix.getFloat(0, 0),
+ xyzMatrix.getFloat(1, 0),
+ xyzMatrix.getFloat(2, 0),
+ xyzMatrix.getFloat(0, 1),
+ xyzMatrix.getFloat(1, 1),
+ xyzMatrix.getFloat(2, 1),
+ xyzMatrix.getFloat(0, 2),
+ xyzMatrix.getFloat(1, 2),
+ xyzMatrix.getFloat(2, 2)
+ };
+ env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
+
+ colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_matchMethodID, xyzArray, params);
+
+ if (colorSpace == nullptr) {
+ // We couldn't find an exact match, let's create a new color space
+ // instance with the 3x3 conversion matrix and transfer function
+ colorSpace = env->NewObject(gColorSpaceRGB_class,
+ gColorSpaceRGB_constructorMethodID,
+ env->NewStringUTF("Unknown"), xyzArray, params);
+ }
+
+ env->DeleteLocalRef(xyzArray);
+ }
+ }
+ return colorSpace;
+}
+
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
// This function takes ownership of the input stream. Since the SkAndroidCodec
// will take ownership of the stream, we don't necessarily need to take ownership
@@ -263,6 +342,7 @@
env->SetIntField(options, gOptions_heightFieldID, -1);
env->SetObjectField(options, gOptions_mimeFieldID, 0);
env->SetObjectField(options, gOptions_outConfigFieldID, 0);
+ env->SetObjectField(options, gOptions_outColorSpaceFieldID, 0);
jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
@@ -319,6 +399,7 @@
// Set the decode colorType
SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);
+ sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(decodeColorType);
// Set the options and return if the client only wants the size.
if (options != NULL) {
@@ -345,6 +426,9 @@
gBitmapConfig_nativeToConfigMethodID, configID);
env->SetObjectField(options, gOptions_outConfigFieldID, config);
+ env->SetObjectField(options, gOptions_outColorSpaceFieldID,
+ getColorSpace(env, decodeColorSpace, decodeColorType));
+
if (onlyDecodeSize) {
return nullptr;
}
@@ -412,7 +496,7 @@
SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied);
const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(),
- decodeColorType, alphaType, codec->computeOutputColorSpace(decodeColorType));
+ decodeColorType, alphaType, decodeColorSpace);
// For wide gamut images, we will leave the color space on the SkBitmap. Otherwise,
// use the default.
@@ -725,6 +809,8 @@
gOptions_mimeFieldID = GetFieldIDOrDie(env, options_class, "outMimeType", "Ljava/lang/String;");
gOptions_outConfigFieldID = GetFieldIDOrDie(env, options_class, "outConfig",
"Landroid/graphics/Bitmap$Config;");
+ gOptions_outColorSpaceFieldID = GetFieldIDOrDie(env, options_class, "outColorSpace",
+ "Landroid/graphics/ColorSpace;");
gOptions_mCancelID = GetFieldIDOrDie(env, options_class, "mCancel", "Z");
jclass bitmap_class = FindClassOrDie(env, "android/graphics/Bitmap");
@@ -741,6 +827,29 @@
gBitmapConfig_nativeToConfigMethodID = GetStaticMethodIDOrDie(env, gBitmapConfig_class,
"nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;");
+ gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
+ gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
+ "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
+ gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match",
+ "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;");
+
+ gColorSpaceRGB_class = MakeGlobalRefOrDie(env,
+ FindClassOrDie(env, "android/graphics/ColorSpace$Rgb"));
+ gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+ "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V");
+
+ gColorSpace_Named_class = MakeGlobalRefOrDie(env,
+ FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
+ gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
+ gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
+
+ gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
+ "android/graphics/ColorSpace$Rgb$TransferParameters"));
+ gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
+ "<init>", "(DDDDDDD)V");
+
return android::RegisterMethodsOrDie(env, "android/graphics/BitmapFactory",
gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index b926270..d606c2d 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -78,6 +78,9 @@
camera_frame_metadata_t *metadata);
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle);
+ virtual void postRecordingFrameHandleTimestampBatch(
+ const std::vector<nsecs_t>& timestamps,
+ const std::vector<native_handle_t*>& handles);
void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata);
void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType);
void setCallbackMode(JNIEnv *env, bool installed, bool manualMode);
@@ -362,6 +365,22 @@
}
}
+void JNICameraContext::postRecordingFrameHandleTimestampBatch(
+ const std::vector<nsecs_t>&,
+ const std::vector<native_handle_t*>& handles) {
+ // Video buffers are not needed at app layer so just return the video buffers here.
+ // This may be called when stagefright just releases camera but there are still outstanding
+ // video buffers.
+ if (mCamera != nullptr) {
+ mCamera->releaseRecordingFrameHandleBatch(handles);
+ } else {
+ for (auto& handle : handles) {
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ }
+ }
+}
+
void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata)
{
jobjectArray obj = NULL;
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_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index 2a3f036..d744b7c 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -22,6 +22,7 @@
#include "utils/misc.h"
#include "utils/Log.h"
#include "unicode/ubidi.h"
+#include <minikin/Emoji.h>
namespace android {
@@ -38,6 +39,9 @@
if (info != NULL) {
UErrorCode status = U_ZERO_ERROR;
UBiDi* bidi = ubidi_openSized(n, 0, &status);
+ // Set callbacks to override bidi classes of new emoji
+ ubidi_setClassCallback(
+ bidi, minikin::emojiBidiOverride, nullptr, nullptr, nullptr, &status);
ubidi_setPara(bidi, chs, n, dir, NULL, &status);
if (U_SUCCESS(status)) {
for (int i = 0; i < n; ++i) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 362794e..e7a447c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -798,13 +798,13 @@
android:description="@string/permdesc_readPhoneState"
android:protectionLevel="dangerous" />
- <!-- Allows read access to the device's phone number. This is a subset of the capabilities
+ <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
granted by {@link #READ_PHONE_STATE} but is exposed to ephemeral applications.
<p>Protection level: dangerous-->
- <permission android:name="android.permission.READ_PHONE_NUMBER"
+ <permission android:name="android.permission.READ_PHONE_NUMBERS"
android:permissionGroup="android.permission-group.PHONE"
android:label="@string/permlab_readPhoneNumber"
- android:description="@string/permdesc_readPhoneNumber"
+ android:description="@string/permdesc_readPhoneNumbers"
android:protectionLevel="dangerous|ephemeral" />
<!-- Allows an application to initiate a phone call without going through
@@ -3346,7 +3346,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 +3361,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 +3423,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 +3432,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 +3455,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/values/config.xml b/core/res/res/values/config.xml
index bcd8a8a..85ecaff 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2819,4 +2819,7 @@
density will be scaled accordingly to maintain aspect ratio. A value of 0 indicates no
constraint will be enforced. -->
<integer name="config_maxUiWidth">0</integer>
+
+ <!-- Whether the device supports quick settings and its associated APIs -->
+ <bool name="config_quickSettingsSupported">true</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4afa8dc..831cf89 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -20,10 +20,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Suffix added to a number to signify size in bytes. -->
<string name="byteShort">B</string>
- <!-- Suffix added to a number to signify size in kilobytes (1000 bytes).
- If you retain the Latin script for the localization, please use the lowercase
- 'k', as it signifies 1000 bytes as opposed to 1024 bytes. -->
- <string name="kilobyteShort">kB</string>
+ <!-- Suffix added to a number to signify size in kilobytes (1000 bytes). -->
+ <string name="kilobyteShort">KB</string>
<!-- Suffix added to a number to signify size in megabytes. -->
<string name="megabyteShort">MB</string>
<!-- Suffix added to a number to signify size in gigabytes. -->
@@ -1094,9 +1092,9 @@
order to improve the calling experience.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readPhoneNumber">read phone number</string>
+ <string name="permlab_readPhoneNumbers">read phone numbers</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_readPhoneNumber">Allows the app to access the phone number of the device.</string>
+ <string name="permdesc_readPhoneNumbers">Allows the app to access the phone numbers of the device.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock" product="tablet">prevent tablet from sleeping</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dfd18e7..ae05a69 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2955,4 +2955,5 @@
<java-symbol type="string" name="etws_primary_default_message_test" />
<java-symbol type="string" name="etws_primary_default_message_others" />
+ <java-symbol type="bool" name="config_quickSettingsSupported" />
</resources>
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 3dfecc6..1080a9f 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,17 +16,6 @@
package com.android.internal.app;
-import android.app.Instrumentation;
-import android.content.ComponentName;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
-import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
-import android.graphics.drawable.Icon;
-import android.os.SystemClock;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -59,31 +48,25 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.isA;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
/**
* Chooser activity instrumentation tests
*/
@RunWith(AndroidJUnit4.class)
public class ChooserActivityTest {
- private Instrumentation instrumentation;
-
- @Before
- public void setUp() {
- instrumentation = InstrumentationRegistry.getInstrumentation();
- sOverrides.reset();
- }
-
@Rule
public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
new ActivityTestRule<>(ChooserWrapperActivity.class, false,
false);
+ @Before
+ public void cleanOverrideData() {
+ sOverrides.reset();
+ }
+
@Test
public void customTitle() throws InterruptedException {
Intent sendIntent = createSendImageIntent();
@@ -252,6 +235,7 @@
chosen[0] = targetInfo.getResolveInfo();
return true;
};
+
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2);
@@ -340,32 +324,6 @@
assertThat(chosen[0], is(toChoose));
}
- public void pushedChooserTarget() {
- ResolveInfo[] chosen = new ResolveInfo[1];
- sOverrides.onSafelyStartCallback = targetInfo -> {
- chosen[0] = targetInfo.getResolveInfo();
- return true;
- };
-
- setChooserShortcuts(1);
- List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
- when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
- Mockito.anyBoolean(),
- Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
-
- Intent sendIntent = createSendImageIntent();
- final ChooserWrapperActivity activity = mActivityRule
- .launchActivity(Intent.createChooser(sendIntent, null));
-
- waitForIdle();
-
- onView(withText("short chooser label 0"))
- .perform(click());
- waitForIdle();
- assertThat(chosen[0].resolvePackageName,
- is(ResolverDataProvider.createActivityInfo(0).packageName));
- }
-
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -413,48 +371,4 @@
}
return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
}
-
- private void setChooserShortcuts(int numShortcuts) {
- ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
- for (int i = 0; i < numShortcuts; i++) {
- shortcuts.add(makeShortcut(i));
- }
- when(sOverrides.launcherApps.getShortcuts(
- Mockito.isA(LauncherApps.ShortcutQuery.class),
- Mockito.eq(UserHandle.SYSTEM)))
- .thenReturn(shortcuts);
- }
-
- private ShortcutInfo makeShortcut(int i) {
- try {
- IntentFilter filter = new IntentFilter(Intent.ACTION_SEND, "image/jpeg");
-
- ComponentName component = new ComponentName("foo.bar", "foo.bar" + ".MainActivity");
- ShortcutInfo.Builder b = new ShortcutInfo.Builder(instrumentation.getContext(), "" + i)
- .setActivity(component)
- .setShortLabel("short chooser label " + i)
- .setLongLabel("long chooser label" + i)
- .setRank(i)
- .setIntent(createSendImageIntent())
- .setIcon(Icon.createWithResource(instrumentation.getContext(),
- android.R.drawable.ic_menu_add))
- .addChooserIntentFilter(
- filter,
- component);
-
- sOverrides.createPackageManager = pm -> {
- final PackageManager spied = spy(pm);
- try {
- doAnswer(invocation -> ResolverDataProvider.createActivityInfo(i))
- .when(spied).getActivityInfo(
- Mockito.isA(ComponentName.class), Mockito.anyInt());
- } catch (Exception e) {
- // this is ok, just not found
- e.printStackTrace();
- }
- return spied;
- };
- return b.build();
- } catch (Exception e) {return null;}
- }
}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 0dac260..c446f3c 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -18,7 +18,6 @@
import android.app.usage.UsageStatsManager;
import android.content.Context;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import java.util.function.Function;
@@ -75,11 +74,6 @@
return super.getPackageManager();
}
- @Override
- public LauncherApps getLauncherApps() {
- return sOverrides.launcherApps;
- }
-
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -88,7 +82,6 @@
static class OverrideData {
@SuppressWarnings("Since15")
public Function<PackageManager, PackageManager> createPackageManager;
- public LauncherApps launcherApps;
public Function<TargetInfo, Boolean> onSafelyStartCallback;
public ResolverListController resolverListController;
public Boolean isVoiceInteraction;
@@ -97,7 +90,6 @@
onSafelyStartCallback = null;
isVoiceInteraction = null;
createPackageManager = null;
- launcherApps = mock(LauncherApps.class);
resolverListController = mock(ResolverListController.class);
}
}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 5e3488c..86ab3dc 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -181,9 +181,8 @@
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
- <!-- Package in charge of provisioning that needs to freely run in the background -->
- <!-- STOPSHIP: Revert this once it is fixed properly -->
- <allow-in-power-save package="com.android.managedprovisioning" />
+ <!-- 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/docs/html/reference/images/graphics/composite_ADD.png b/docs/html/reference/images/graphics/composite_ADD.png
new file mode 100644
index 0000000..90932c5
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_ADD.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_CLEAR.png b/docs/html/reference/images/graphics/composite_CLEAR.png
new file mode 100644
index 0000000..7c0731d
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_CLEAR.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DARKEN.png b/docs/html/reference/images/graphics/composite_DARKEN.png
new file mode 100644
index 0000000..a798b97
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DARKEN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST.png b/docs/html/reference/images/graphics/composite_DST.png
new file mode 100644
index 0000000..6dde48f
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_ATOP.png b/docs/html/reference/images/graphics/composite_DST_ATOP.png
new file mode 100644
index 0000000..c6767bd
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_ATOP.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_IN.png b/docs/html/reference/images/graphics/composite_DST_IN.png
new file mode 100644
index 0000000..cf50a7b
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_IN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_OUT.png b/docs/html/reference/images/graphics/composite_DST_OUT.png
new file mode 100644
index 0000000..ee8a46e
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_OUT.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_DST_OVER.png b/docs/html/reference/images/graphics/composite_DST_OVER.png
new file mode 100644
index 0000000..1838972
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_DST_OVER.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_LIGHTEN.png b/docs/html/reference/images/graphics/composite_LIGHTEN.png
new file mode 100644
index 0000000..8fc0a10
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_LIGHTEN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_MULTIPLY.png b/docs/html/reference/images/graphics/composite_MULTIPLY.png
new file mode 100644
index 0000000..8816ab0
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_MULTIPLY.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_OVERLAY.png b/docs/html/reference/images/graphics/composite_OVERLAY.png
new file mode 100644
index 0000000..700a6b2
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_OVERLAY.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SCREEN.png b/docs/html/reference/images/graphics/composite_SCREEN.png
new file mode 100644
index 0000000..b698819
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SCREEN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC.png b/docs/html/reference/images/graphics/composite_SRC.png
new file mode 100644
index 0000000..2d70a54
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_ATOP.png b/docs/html/reference/images/graphics/composite_SRC_ATOP.png
new file mode 100644
index 0000000..111869e
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_ATOP.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_IN.png b/docs/html/reference/images/graphics/composite_SRC_IN.png
new file mode 100644
index 0000000..1d6145b
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_IN.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_OUT.png b/docs/html/reference/images/graphics/composite_SRC_OUT.png
new file mode 100644
index 0000000..39c0c17
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_OUT.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_SRC_OVER.png b/docs/html/reference/images/graphics/composite_SRC_OVER.png
new file mode 100644
index 0000000..1489487
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_SRC_OVER.png
Binary files differ
diff --git a/docs/html/reference/images/graphics/composite_XOR.png b/docs/html/reference/images/graphics/composite_XOR.png
new file mode 100644
index 0000000..6d0c5ba
--- /dev/null
+++ b/docs/html/reference/images/graphics/composite_XOR.png
Binary files differ
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index a3c6c6e..ceedc1f 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -361,6 +361,15 @@
public Bitmap.Config outConfig;
/**
+ * If known, the color space the decoded bitmap will have. Note that the
+ * output color space is not guaranteed to be the color space the bitmap
+ * is encoded with. If not known (when the config is
+ * {@link Bitmap.Config#ALPHA_8} for instance), or there is an error,
+ * it is set to null.
+ */
+ public ColorSpace outColorSpace;
+
+ /**
* Temp storage to use for decoding. Suggest 16K or so.
*/
public byte[] inTempStorage;
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index d69f67d..218b857c 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -289,7 +289,7 @@
* and <code>(1.0, 0.0, 0.0, 0.5)</code>.</p>
*/
@AnyThread
-public final class Color {
+public class Color {
@ColorInt public static final int BLACK = 0xFF000000;
@ColorInt public static final int DKGRAY = 0xFF444444;
@ColorInt public static final int GRAY = 0xFF888888;
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 929ac22..e03dcf3 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -143,7 +143,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_renderer.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_renderer.png" />
* <figcaption style="text-align: center;">DCI-P3 vs ProPhoto RGB</figcaption>
* </p>
*
@@ -281,7 +281,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
* <figcaption style="text-align: center;">sRGB</figcaption>
* </p>
*/
@@ -308,7 +308,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
* <figcaption style="text-align: center;">sRGB</figcaption>
* </p>
*/
@@ -347,7 +347,7 @@
* <tr><td>Range</td><td colspan="4">\([-0.799..2.399[\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
* <figcaption style="text-align: center;">Extended sRGB (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -374,7 +374,7 @@
* <tr><td>Range</td><td colspan="4">\([-0.5..7.499[\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
* <figcaption style="text-align: center;">Extended sRGB (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -409,7 +409,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_bt709.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_bt709.png" />
* <figcaption style="text-align: center;">BT.709</figcaption>
* </p>
*/
@@ -444,7 +444,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_bt2020.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_bt2020.png" />
* <figcaption style="text-align: center;">BT.2020 (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -471,7 +471,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_dci_p3.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_dci_p3.png" />
* <figcaption style="text-align: center;">DCI-P3 (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -506,7 +506,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_display_p3.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_display_p3.png" />
* <figcaption style="text-align: center;">Display P3 (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -541,7 +541,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_ntsc_1953.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_ntsc_1953.png" />
* <figcaption style="text-align: center;">NTSC 1953 (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -576,7 +576,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_smpte_c.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_smpte_c.png" />
* <figcaption style="text-align: center;">SMPTE-C (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -603,7 +603,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_adobe_rgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_adobe_rgb.png" />
* <figcaption style="text-align: center;">Adobe RGB (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -638,7 +638,7 @@
* <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_pro_photo_rgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_pro_photo_rgb.png" />
* <figcaption style="text-align: center;">ProPhoto RGB (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -665,7 +665,7 @@
* <tr><td>Range</td><td colspan="4">\([-65504.0, 65504.0]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_aces.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_aces.png" />
* <figcaption style="text-align: center;">ACES (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -692,7 +692,7 @@
* <tr><td>Range</td><td colspan="4">\([-65504.0, 65504.0]\)</td></tr>
* </table>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_acescg.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_acescg.png" />
* <figcaption style="text-align: center;">ACEScg (orange) vs sRGB (white)</figcaption>
* </p>
*/
@@ -1931,7 +1931,7 @@
* are internally converted to xyY.</p>
*
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_srgb.png" />
* <figcaption style="text-align: center;">sRGB primaries and white point</figcaption>
* </p>
*
@@ -1989,7 +1989,7 @@
* the range \([-65504, 65504]\).</p>
*
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_scrgb.png" />
* <figcaption style="text-align: center;">Extended sRGB and its large range</figcaption>
* </p>
*
@@ -3703,7 +3703,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
* <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption>
* </p>
*
@@ -3746,7 +3746,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
* <figcaption style="text-align: center;">Clipping disabled</figcaption>
* </p>
*
@@ -3759,7 +3759,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_clipped.png" />
* <figcaption style="text-align: center;">Clipping enabled</figcaption>
* </p>
*
@@ -3789,7 +3789,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" />
* <figcaption style="text-align: center;">CIE 1976 UCS diagram</figcaption>
* </p>
*
@@ -3847,7 +3847,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison.png" />
* <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption>
* </p>
*
@@ -3863,7 +3863,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" />
* <figcaption style="text-align: center;">sRGB, DCI-P3, ACES and scRGB</figcaption>
* </p>
*
@@ -3901,7 +3901,7 @@
* .render();
* </pre>
* <p>
- * <img src="{@docRoot}reference/android/images/graphics/colorspace_points.png" />
+ * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_points.png" />
* <figcaption style="text-align: center;">
* Locating colors on the chromaticity diagram
* </figcaption>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f4bf079..c4f7dc3 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1067,19 +1067,23 @@
}
/**
- * Get the paint's xfermode object.
+ * Get the paint's transfer mode object.
*
- * @return the paint's xfermode (or null)
+ * @return the paint's transfer mode (or null)
*/
public Xfermode getXfermode() {
return mXfermode;
}
/**
- * Set or clear the xfermode object.
+ * Set or clear the transfer mode object. A transfer mode defines how
+ * source pixels (generate by a drawing command) are composited with
+ * the destination pixels (content of the render target).
* <p />
- * Pass null to clear any previous xfermode.
+ * Pass null to clear any previous transfer mode.
* As a convenience, the parameter passed is also returned.
+ * <p />
+ * {@link PorterDuffXfermode} is the most common transfer mode.
*
* @param xfermode May be null. The xfermode to be installed in the paint
* @return xfermode
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index 2bbbff3..d7d3049 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -16,46 +16,345 @@
package android.graphics;
+/**
+ * <p>This class contains the list of alpha compositing and blending modes
+ * that can be passed to {@link PorterDuffXfermode}, a specialized implementation
+ * of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}.
+ * All the available modes can be found in the {@link Mode} enum.</p>
+ */
public class PorterDuff {
+ /**
+ * {@usesMathJax}
+ *
+ * <h3>Porter-Duff</h3>
+ *
+ * <p>The name of the parent class is an homage to the work of Thomas Porter and
+ * Tom Duff, presented in their seminal 1984 paper titled "Compositing Digital Images".
+ * In this paper, the authors describe 12 compositing operators that govern how to
+ * compute the color resulting of the composition of a source (the graphics object
+ * to render) with a destination (the content of the render target).</p>
+ *
+ * <p>"Compositing Digital Images" was published in <em>Computer Graphics</em>
+ * Volume 18, Number 3 dated July 1984.</p>
+ *
+ * <p>Because the work of Porter and Duff focuses solely on the effects of the alpha
+ * channel of the source and destination, the 12 operators described in the original
+ * paper are called alpha compositing modes here.</p>
+ *
+ * <p>For convenience, this class also provides several blending modes, which similarly
+ * define the result of compositing a source and a destination but without being
+ * constrained to the alpha channel. These blending modes are not defined by Porter
+ * and Duff but have been included in this class for convenience purposes.</p>
+ *
+ * <h3>Diagrams</h3>
+ *
+ * <p>All the example diagrams presented below use the same source and destination
+ * images:</p>
+ *
+ * <table summary="Source and Destination" style="background-color: transparent;">
+ * <tr>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
+ * <figcaption>Source image</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
+ * <figcaption>Destination image</figcaption>
+ * </td>
+ * </tr>
+ * </table>
+ *
+ * <p>The order of drawing operations used to generate each diagram is shown in the
+ * following code snippet:</p>
+ *
+ * <pre class="prettyprint">
+ * Paint paint = new Paint();
+ * canvas.drawBitmap(destinationImage, 0, 0, paint);
+ *
+ * PorterDuff.Mode mode = // choose a mode
+ * paint.setXfermode(new PorterDuffXfermode(mode));
+ *
+ * canvas.drawBitmap(sourceImage, 0, 0, paint);
+ * </pre>
- // these value must match their native equivalents. See SkXfermode.h
+ *
+ * <h3>Alpha compositing modes</h3>
+ *
+ * <table summary="Alpha compositing modes" style="background-color: transparent;">
+ * <tr>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
+ * <figcaption>{@link #SRC Source}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
+ * <figcaption>{@link #SRC_OVER Source Over}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
+ * <figcaption>{@link #SRC_IN Source In}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
+ * <figcaption>{@link #SRC_ATOP Source Atop}</figcaption>
+ * </td>
+ * </tr>
+ * <tr>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
+ * <figcaption>{@link #DST Destination}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
+ * <figcaption>{@link #DST_OVER Destination Over}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
+ * <figcaption>{@link #DST_IN Destination In}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
+ * <figcaption>{@link #DST_ATOP Destination Atop}</figcaption>
+ * </td>
+ * </tr>
+ * <tr>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
+ * <figcaption>{@link #CLEAR Clear}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
+ * <figcaption>{@link #SRC_OUT Source Out}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
+ * <figcaption>{@link #DST_OUT Destination Out}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
+ * <figcaption>{@link #XOR Exclusive Or}</figcaption>
+ * </td>
+ * </tr>
+ * </table>
+ *
+ * <h3>Blending modes</h3>
+ *
+ * <table summary="Blending modes" style="background-color: transparent;">
+ * <tr>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
+ * <figcaption>{@link #DARKEN Darken}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
+ * <figcaption>{@link #LIGHTEN Lighten}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
+ * <figcaption>{@link #MULTIPLY Multiply}</figcaption>
+ * </td>
+ * </tr>
+ * <tr>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
+ * <figcaption>{@link #SCREEN Screen}</figcaption>
+ * </td>
+ * <td style="border: none; text-align: center;">
+ * <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
+ * <figcaption>{@link #OVERLAY Overlay}</figcaption>
+ * </td>
+ * </tr>
+ * </table>
+ *
+ * <h3>Compositing equations</h3>
+ *
+ * <p>The documentation of each individual alpha compositing or blending mode below
+ * provides the exact equation used to compute alpha and color value of the result
+ * of the composition of a source and destination.</p>
+ *
+ * <p>The result (or output) alpha value is noted \(\alpha_{out}\). The result (or output)
+ * color value is noted \(C_{out}\).</p>
+ */
public enum Mode {
- /** [0, 0] */
+ // these value must match their native equivalents. See SkXfermode.h
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
+ * <figcaption>Destination pixels covered by the source are cleared to 0.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = 0\)</p>
+ * <p>\(C_{out} = 0\)</p>
+ */
CLEAR (0),
- /** [Sa, Sc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
+ * <figcaption>The source pixels replace the destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src}\)</p>
+ * <p>\(C_{out} = C_{src}\)</p>
+ */
SRC (1),
- /** [Da, Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
+ * <figcaption>The source pixels are discarded, leaving the destination intact.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{dst}\)</p>
+ * <p>\(C_{out} = C_{dst}\)</p>
+ */
DST (2),
- /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
+ * <figcaption>The source pixels are drawn over the destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
+ */
SRC_OVER (3),
- /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
+ * <figcaption>The source pixels are drawn behind the destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{dst} + (1 - \alpha_{dst}) * \alpha_{src}\)</p>
+ * <p>\(C_{out} = C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
+ */
DST_OVER (4),
- /** [Sa * Da, Sc * Da] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
+ * <figcaption>Keeps the source pixels that cover the destination pixels,
+ * discards the remaining source and destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = C_{src} * \alpha_{dst}\)</p>
+ */
SRC_IN (5),
- /** [Sa * Da, Sa * Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
+ * <figcaption>Keeps the destination pixels that cover source pixels,
+ * discards the remaining source and destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = C_{dst} * \alpha_{src}\)</p>
+ */
DST_IN (6),
- /** [Sa * (1 - Da), Sc * (1 - Da)] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
+ * <figcaption>Keeps the source pixels that do not cover destination pixels.
+ * Discards source pixels that cover destination pixels. Discards all
+ * destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src}\)</p>
+ * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src}\)</p>
+ */
SRC_OUT (7),
- /** [Da * (1 - Sa), Dc * (1 - Sa)] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
+ * <figcaption>Keeps the destination pixels that are not covered by source pixels.
+ * Discards destination pixels that are covered by source pixels. Discards all
+ * source pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = (1 - \alpha_{src}) * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = (1 - \alpha_{src}) * C_{dst}\)</p>
+ */
DST_OUT (8),
- /** [Da, Sc * Da + (1 - Sa) * Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
+ * <figcaption>Discards the source pixels that do not cover destination pixels.
+ * Draws remaining source pixels over destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{dst}\)</p>
+ * <p>\(C_{out} = \alpha_{dst} * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
+ */
SRC_ATOP (9),
- /** [Sa, Sa * Dc + Sc * (1 - Da)] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
+ * <figcaption>Discards the destination pixels that are not covered by source pixels.
+ * Draws remaining destination pixels over source pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src}\)</p>
+ * <p>\(C_{out} = \alpha_{src} * C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
+ */
DST_ATOP (10),
- /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
+ * <figcaption>Discards the source and destination pixels where source pixels
+ * cover destination pixels. Draws remaining source pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
+ */
XOR (11),
- /** [Sa + Da - Sa*Da,
- Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
+ * <figcaption>Retains the smallest component of the source and
+ * destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + min(C_{src}, C_{dst})\)</p>
+ */
DARKEN (16),
- /** [Sa + Da - Sa*Da,
- Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
+ * <figcaption>Retains the largest component of the source and
+ * destination pixel.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + max(C_{src}, C_{dst})\)</p>
+ */
LIGHTEN (17),
- /** [Sa * Da, Sc * Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
+ * <figcaption>Multiplies the source and destination pixels.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = C_{src} * C_{dst}\)</p>
+ */
MULTIPLY (13),
- /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
+ * <figcaption>Adds the source and destination pixels, then subtracts the
+ * source pixels multiplied by the destination.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(C_{out} = C_{src} + C_{dst} - C_{src} * C_{dst}\)</p>
+ */
SCREEN (14),
- /** Saturate(S + D) */
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_ADD.png" />
+ * <figcaption>Adds the source pixels to the destination pixels and saturates
+ * the result.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = max(0, min(\alpha_{src} + \alpha_{dst}, 1))\)</p>
+ * <p>\(C_{out} = max(0, min(C_{src} + C_{dst}, 1))\)</p>
+ */
ADD (12),
+ /**
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
+ * <figcaption>Multiplies or screens the source and destination depending on the
+ * destination color.</figcaption>
+ * </p>
+ * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
+ * <p>\(\begin{equation}
+ * C_{out} = \begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} \lt \alpha_{dst} \\
+ * \alpha_{src} * \alpha_{dst} - 2 (\alpha_{dst} - C_{src}) (\alpha_{src} - C_{dst}) & otherwise \end{cases}
+ * \end{equation}\)</p>
+ */
OVERLAY (15);
Mode(int nativeInt) {
@@ -71,14 +370,14 @@
/**
* @hide
*/
- public static final int modeToInt(Mode mode) {
+ public static int modeToInt(Mode mode) {
return mode.nativeInt;
}
/**
* @hide
*/
- public static final Mode intToMode(int val) {
+ public static Mode intToMode(int val) {
switch (val) {
default:
case 0: return Mode.CLEAR;
diff --git a/graphics/java/android/graphics/PorterDuffXfermode.java b/graphics/java/android/graphics/PorterDuffXfermode.java
index 5104410..84d953d 100644
--- a/graphics/java/android/graphics/PorterDuffXfermode.java
+++ b/graphics/java/android/graphics/PorterDuffXfermode.java
@@ -16,6 +16,12 @@
package android.graphics;
+/**
+ * <p>Specialized implementation of {@link Paint}'s
+ * {@link Paint#setXfermode(Xfermode) transfer mode}. Refer to the
+ * documentation of the {@link PorterDuff.Mode} enum for more
+ * information on the available alpha compositing and blending modes.</p>
+ */
public class PorterDuffXfermode extends Xfermode {
/**
* Create an xfermode that uses the specified porter-duff mode.
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 7f579a2..deafb66 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -20,6 +20,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -170,6 +171,10 @@
* or null if the string is not of that form.
*/
public static Rect unflattenFromString(String str) {
+ if (TextUtils.isEmpty(str)) {
+ return null;
+ }
+
Matcher matcher = UnflattenHelper.getMatcher(str);
if (!matcher.matches()) {
return null;
@@ -179,7 +184,7 @@
Integer.parseInt(matcher.group(3)),
Integer.parseInt(matcher.group(4)));
}
-
+
/**
* Print short representation to given writer.
* @hide
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index c6c9271..643c0da 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -304,6 +304,9 @@
@Override
public void draw(Canvas canvas) {
+ if (mLayersBitmap == null) {
+ return;
+ }
if (mLayersShader == null) {
mCanvas.setBitmap(mLayersBitmap);
for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index d88aee9..04864bd 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -88,7 +88,9 @@
}
@Override
- public @Config int getChangingConfigurations() {
+ public
+ @Config
+ int getChangingConfigurations() {
return super.getChangingConfigurations()
| mDrawableContainerState.getChangingConfigurations();
}
@@ -210,6 +212,7 @@
/**
* Change the global fade duration when a new drawable is entering
* the scene.
+ *
* @param ms The amount of time to fade in milliseconds.
*/
public void setEnterFadeDuration(int ms) {
@@ -219,6 +222,7 @@
/**
* Change the global fade duration when a new drawable is leaving
* the scene.
+ *
* @param ms The amount of time to fade in milliseconds.
*/
public void setExitFadeDuration(int ms) {
@@ -375,6 +379,13 @@
@Override
public void invalidateDrawable(@NonNull Drawable who) {
+ // This may have been called as the result of a tint changing, in
+ // which case we may need to refresh the cached statefulness or
+ // opacity.
+ if (mDrawableContainerState != null) {
+ mDrawableContainerState.invalidateCache();
+ }
+
if (who == mCurrDrawable && getCallback() != null) {
getCallback().invalidateDrawable(this);
}
@@ -822,8 +833,8 @@
mDrawables[pos] = dr;
mNumChildren++;
mChildrenChangingConfigurations |= dr.getChangingConfigurations();
- mCheckedStateful = false;
- mCheckedOpacity = false;
+
+ invalidateCache();
mConstantPadding = null;
mCheckedPadding = false;
@@ -833,6 +844,14 @@
return pos;
}
+ /**
+ * Invalidates the cached opacity and statefulness.
+ */
+ void invalidateCache() {
+ mCheckedOpacity = false;
+ mCheckedStateful = false;
+ }
+
final int getCapacity() {
return mDrawables.length;
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 355e45e..322e55b 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -986,6 +986,11 @@
if (mSuspendChildInvalidation) {
mChildRequestedInvalidation = true;
} else {
+ // This may have been called as the result of a tint changing, in
+ // which case we may need to refresh the cached statefulness or
+ // opacity.
+ mLayerState.invalidateCache();
+
invalidateSelf();
}
}
@@ -2121,7 +2126,10 @@
return true;
}
- public void invalidateCache() {
+ /**
+ * Invalidates the cached opacity and statefulness.
+ */
+ void invalidateCache() {
mCheckedOpacity = false;
mCheckedStateful = false;
}
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/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 9739319..d8c3eca 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;
@@ -840,7 +841,7 @@
public interface BasePreviewProgramColumns extends BaseProgramColumns {
/** @hide */
- @StringDef({
+ @IntDef({
TYPE_MOVIE,
TYPE_TV_SERIES,
TYPE_TV_SEASON,
@@ -862,87 +863,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 +958,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 +966,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 +974,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 +982,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 +998,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 +1013,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 +1091,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 +1127,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 +1140,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 +1153,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 +1186,7 @@
* {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
* {@link #AVAILABILITY_PAID_CONTENT}.
*
- * <p>Type: TEXT
+ * <p>Type: INTEGER
*/
String COLUMN_AVAILABILITY = "availability";
@@ -1299,18 +1297,17 @@
String COLUMN_DURATION_MILLIS = "duration_millis";
/**
- * The intent URI which is launched when the preview video is selected.
+ * The intent URI which is launched when the preview program is selected.
*
* <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
* and converted back to the original intent with {@link Intent#parseUri}. The intent is
- * launched when the user selects the preview video item.
+ * launched when the user selects the preview program item.
*
* <p>Can be empty.
*
* <p>Type: TEXT
*/
- String COLUMN_APP_LINK_INTENT_URI =
- "app_link_intent_uri";
+ String COLUMN_INTENT_URI = "intent_uri";
/**
* The flag indicating whether this program is transient or not.
@@ -1328,15 +1325,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";
@@ -1364,7 +1361,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";
@@ -1802,8 +1799,9 @@
* {@link #TYPE_OTHER},
* {@link #TYPE_PAL},
* {@link #TYPE_SECAM},
- * {@link #TYPE_S_DMB}, and
- * {@link #TYPE_T_DMB}.
+ * {@link #TYPE_S_DMB},
+ * {@link #TYPE_T_DMB}, and
+ * {@link #TYPE_PREVIEW}.
*
* <p>This value cannot be changed once it's set. Trying to modify it will make the update
* fail.
@@ -2724,7 +2722,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 +2737,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 +2747,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 +2757,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 +2766,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 +2779,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/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index cc1e01a..37a68e0 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -220,14 +220,8 @@
public long[] getFileSystemStats(String path) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- try {
- final StructStatVfs stat = Os.statvfs(path);
- final long totalSize = stat.f_blocks * stat.f_bsize;
- final long availSize = stat.f_bavail * stat.f_bsize;
- return new long[] { totalSize, availSize };
- } catch (ErrnoException e) {
- throw new IllegalStateException(e);
- }
+ final File file = new File(path);
+ return new long[] { file.getTotalSpace(), file.getUsableSpace() };
}
@Override
diff --git a/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
index 18863ca..862f50b2 100644
--- a/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
+++ b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2017 The Android Open Source Project
*
@@ -123,10 +122,10 @@
StorageManager storageManager = getSystemService(StorageManager.class);
long freeBytes = 0;
if (uuid == StorageManager.UUID_PRIVATE_INTERNAL) { // regular equals because of null
- freeBytes = Environment.getDataDirectory().getFreeSpace();
+ freeBytes = Environment.getDataDirectory().getUsableSpace();
} else {
final VolumeInfo vol = storageManager.findVolumeByUuid(uuid);
- freeBytes = vol.getPath().getFreeSpace();
+ freeBytes = vol.getPath().getUsableSpace();
}
return Math.round(freeBytes * CACHE_RESERVE_RATIO);
}
diff --git a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
index cc1699a..df4738f 100644
--- a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
@@ -61,7 +61,7 @@
setContext(mContext);
when(mContext.getSystemService(Context.STORAGE_SERVICE)).thenReturn(mStorageManager);
- when(mFile.getFreeSpace()).thenReturn(10000L);
+ when(mFile.getUsableSpace()).thenReturn(10000L);
when(mVolume.getPath()).thenReturn(mFile);
when(mStorageManager.findVolumeByUuid(sTestVolUuid)).thenReturn(mVolume);
when(mStorageManager.findVolumeByUuid(sSecondTestVolUuid)).thenReturn(mVolume);
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index b60e2fe..b958c28 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -386,7 +386,7 @@
row.add(Root.COLUMN_TITLE, root.title);
row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
row.add(Root.COLUMN_AVAILABLE_BYTES,
- root.reportAvailableBytes ? root.path.getFreeSpace() : -1);
+ root.reportAvailableBytes ? root.path.getUsableSpace() : -1);
}
}
return result;
diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
index 1f35d3e..ea538fb 100644
--- a/packages/SettingsLib/res/values/attrs.xml
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -36,6 +36,9 @@
<declare-styleable name="WifiEncryptionState">
<attr name="state_encrypted" format="boolean" />
</declare-styleable>
+ <declare-styleable name="WifiMeteredState">
+ <attr name="state_metered" format="boolean" />
+ </declare-styleable>
<declare-styleable name="WifiSavedState">
<attr name="state_saved" format="boolean" />
</declare-styleable>
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/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index ca8edf5..40abb6c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -16,18 +16,15 @@
package com.android.settingslib.deviceinfo;
-import android.os.storage.StorageManager;
+import android.app.AppGlobals;
+import android.app.usage.StorageStatsManager;
+import android.content.Context;
import android.os.storage.VolumeInfo;
-import android.util.Log;
-
-import java.io.File;
-import java.util.Objects;
/**
* PrivateStorageInfo provides information about the total and free storage on the device.
*/
public class PrivateStorageInfo {
- private static final String TAG = "PrivateStorageInfo";
public final long freeBytes;
public final long totalBytes;
@@ -37,45 +34,23 @@
}
public static PrivateStorageInfo getPrivateStorageInfo(StorageVolumeProvider sm) {
- long totalInternalStorage = sm.getPrimaryStorageSize();
+ final Context context = AppGlobals.getInitialApplication();
+ final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
+
long privateFreeBytes = 0;
long privateTotalBytes = 0;
for (VolumeInfo info : sm.getVolumes()) {
- final File path = info.getPath();
- if (info.getType() != VolumeInfo.TYPE_PRIVATE || path == null) {
- continue;
+ if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
+ privateTotalBytes += stats.getTotalBytes(info.getFsUuid());
+ privateFreeBytes += stats.getFreeBytes(info.getFsUuid());
}
- privateTotalBytes += getTotalSize(info, totalInternalStorage);
- privateFreeBytes += path.getFreeSpace();
}
return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
}
- /**
- * Returns the total size in bytes for a given volume info.
- * @param info Info of the volume to check.
- * @param totalInternalStorage Total number of bytes in the internal storage to use if the
- * volume is the internal disk.
- */
public static long getTotalSize(VolumeInfo info, long totalInternalStorage) {
- // Device could have more than one primary storage, which could be located in the
- // internal flash (UUID_PRIVATE_INTERNAL) or in an external disk.
- // If it's internal, try to get its total size from StorageManager first
- // (totalInternalStorage), because that size is more precise because it accounts for
- // the system partition.
- if (info.getType() == VolumeInfo.TYPE_PRIVATE
- && Objects.equals(info.getFsUuid(), StorageManager.UUID_PRIVATE_INTERNAL)
- && totalInternalStorage > 0) {
- return totalInternalStorage;
- } else {
- final File path = info.getPath();
- if (path == null) {
- // Should not happen, caller should have checked.
- Log.e(TAG, "info's path is null on getTotalSize(): " + info);
- return 0;
- }
- return path.getTotalSpace();
- }
+ final Context context = AppGlobals.getInitialApplication();
+ final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
+ return stats.getTotalBytes(info.getFsUuid());
}
-
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 0f443d6..61ca13d 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -63,7 +63,7 @@
mPlusPaint;
private float mTextHeight, mWarningTextHeight;
private int mIconTint = Color.WHITE;
- private float mOldDarkIntensity = 0f;
+ private float mOldDarkIntensity = -1f;
private int mHeight;
private int mWidth;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index a9aaa05..8f8167e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -44,6 +44,10 @@
R.attr.state_encrypted
};
+ private static final int[] STATE_METERED = {
+ R.attr.state_metered
+ };
+
private static final int[] wifi_friction_attributes = { R.attr.wifi_friction };
private final StateListDrawable mFrictionSld;
@@ -179,6 +183,8 @@
}
if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
mFrictionSld.setState(STATE_SECURED);
+ } else if (mAccessPoint.getConfig() != null && mAccessPoint.getConfig().meteredHint) {
+ mFrictionSld.setState(STATE_METERED);
}
Drawable drawable = mFrictionSld.getCurrent();
frictionImageView.setImageDrawable(drawable);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 6f52dca..ec94841 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -26,7 +26,9 @@
private final WifiManager mWifiManager;
public boolean enabled;
+ public int state;
public boolean connected;
+ public boolean connecting;
public String ssid;
public int rssi;
public int level;
@@ -39,11 +41,18 @@
public void handleBroadcast(Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN);
+ enabled = state == WifiManager.WIFI_STATE_ENABLED;
+
+
enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final NetworkInfo networkInfo = (NetworkInfo)
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ connecting = networkInfo != null && !networkInfo.isConnected()
+ && networkInfo.isConnectedOrConnecting();
connected = networkInfo != null && networkInfo.isConnected();
WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
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/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 635c96f..53c5b1b 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -34,6 +34,7 @@
android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-appcompat \
+ android-support-v7-mediarouter \
android-support-v14-preference \
android-support-v17-leanback
diff --git a/packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml
new file mode 100644
index 0000000..26c6aa7
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_1_animation.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml
new file mode 100644
index 0000000..e1f8989
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_bluetooth_transient_group_2_animation.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_bluetooth_transient_animation_interpolator_0" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_bluetooth_transient_animation_interpolator_0" />
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml b/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml
new file mode 100644
index 0000000..919a4dd
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_signal_wifi_transient_wifi_1_animation.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="316"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 9.55569458008,-11.8414916992 9.55569458008,-11.8414916992 c 0.0,0.0 -3.32373046875,-3.83329772949 -9.59307861328,-3.7864074707 c -6.26933288574,0.046875 -9.61039733887,3.71441650391 -9.61039733887,3.71441650391 c 0.0,0.0 9.61378479004,11.913482666 9.61378479004,11.913482666 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="316"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="pathData"
+ android:valueFrom="M 0.0169982910156,18.4394989014 c 0.0,0.0 16.9385528564,-20.9904174805 16.9385528564,-20.9904174805 c -0.486480712891,-0.364868164062 -6.84008789062,-6.15798950195 -16.9654541016,-6.13645935059 c -10.1253662109,0.0215454101562 -16.4858551025,5.73852539062 -16.9723510742,6.10339355469 c 0.0,0.0 16.9652557373,21.0234832764 16.9652557373,21.0234832764 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueTo="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:valueType="pathType"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="16"
+ android:propertyName="fillAlpha"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml b/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml
new file mode 100644
index 0000000..76026af
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_bluetooth_transient.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="ic_bluetooth_transient"
+ android:width="48dp"
+ android:viewportWidth="48"
+ android:height="48dp"
+ android:viewportHeight="48" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_outlines_"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_outlines__pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <group
+ android:name="bluetooth"
+ android:translateX="22.08789"
+ android:translateY="18.72031" >
+ <group
+ android:name="bluetooth_pivot"
+ android:translateX="-22.08789"
+ android:translateY="-18.72031" >
+ <group
+ android:name="cross"
+ android:rotation="-1.88453" >
+ <path
+ android:name="extented_cross"
+ android:pathData="M 10.6188659668,6.56344604492 c 0.0,0.0 21.7386016846,23.1297454834 21.7386016846,23.1297454834"
+ android:strokeColor="#FFFFFFFF"
+ android:strokeWidth="4" />
+ </group>
+ <group
+ android:name="bluetooth_0"
+ android:translateX="23.38789"
+ android:translateY="18.72031" >
+ <path
+ android:name="b_shape_merged"
+ android:pathData="M 11.3999938965,-8.60000610352 c 0.0,0.0 -11.3999938965,-11.3999938965 -11.3999938965,-11.3999938965 c 0.0,0.0 -2.0,0.0 -2.0,0.0 c 0.0,0.0 0.0,15.1999969482 0.0,15.1999969482 c 0.0,0.0 -9.19999694824,-9.19999694824 -9.19999694824,-9.19999694824 c 0.0,0.0 -2.80000305176,2.80000305176 -2.80000305176,2.80000305176 c 0.0,0.0 11.1999969482,11.1999969482 11.1999969482,11.1999969482 c 0.0,0.0 -11.1999969482,11.1999969482 -11.1999969482,11.1999969482 c 0.0,0.0 2.80000305176,2.80000305176 2.80000305176,2.80000305176 c 0.0,0.0 9.19999694824,-9.19999694824 9.19999694824,-9.19999694824 c 0.0,0.0 0.0,15.1999969482 0.0,15.1999969482 c 0.0,0.0 2.0,0.0 2.0,0.0 c 0.0,0.0 11.3999938965,-11.3999938965 11.3999938965,-11.3999938965 c 0.0,0.0 -8.59999084473,-8.60000610352 -8.59999084473,-8.60000610352 c 0.0,0.0 8.59999084473,-8.60000610352 8.59999084473,-8.60000610352 Z M 2.0,-12.3000030518 c 0.0,0.0 3.80000305176,3.80000305176 3.80000305176,3.80000305176 c 0.0,0.0 -3.80000305176,3.69999694824 -3.80000305176,3.69999694824 c 0.0,0.0 0.0,-7.5 0.0,-7.5 Z M 5.80000305176,8.60000610352 c 0.0,0.0 -3.80000305176,3.69999694824 -3.80000305176,3.69999694824 c 0.0,0.0 0.0,-7.5 0.0,-7.5 c 0.0,0.0 3.80000305176,3.80000305176 3.80000305176,3.80000305176 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="dot_left"
+ android:translateX="20.16992"
+ android:translateY="18.64258" >
+ <group
+ android:name="dot_left_pivot"
+ android:translateX="-20.16992"
+ android:translateY="-18.64258" >
+ <group
+ android:name="group_1"
+ android:translateX="9.38789"
+ android:translateY="18.72031" >
+ <group
+ android:name="group_1_pivot"
+ android:translateX="-9.38789"
+ android:translateY="-18.72031" >
+ <path
+ android:name="dot_left_0"
+ android:pathData="M 13.3878936768,18.7203063965 c 0.0,0.0 -4.0,-4.0 -4.0,-4.0 c 0.0,0.0 -4.0,4.0 -4.0,4.0 c 0.0,0.0 4.0,4.0 4.0,4.0 c 0.0,0.0 4.0,-4.0 4.0,-4.0 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="dot_right"
+ android:translateX="26.16094"
+ android:translateY="18.60898" >
+ <group
+ android:name="dot_right_pivot"
+ android:translateX="-26.16094"
+ android:translateY="-18.60898" >
+ <group
+ android:name="group_2"
+ android:translateX="37.38789"
+ android:translateY="18.72031"
+ android:scaleX="0"
+ android:scaleY="0" >
+ <group
+ android:name="group_1_pivot_0"
+ android:translateX="-37.38789"
+ android:translateY="-18.72031" >
+ <path
+ android:name="dot_right_0"
+ android:pathData="M 37.3878936768,14.7203063965 c 0.0,0.0 -4.0,4.0 -4.0,4.0 c 0.0,0.0 4.0,4.0 4.0,4.0 c 0.0,0.0 4.0,-4.0 4.0,-4.0 c 0.0,0.0 -4.0,-4.0 -4.0,-4.0 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml b/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 0000000..f7eb23c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_bluetooth_transient" >
+ <target
+ android:name="group_1"
+ android:animation="@anim/ic_bluetooth_transient_group_1_animation" />
+ <target
+ android:name="group_2"
+ android:animation="@anim/ic_bluetooth_transient_group_2_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml b/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml
new file mode 100644
index 0000000..880e1bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_wifi_transient.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="ic_signal_wifi_transient"
+ android:width="48dp"
+ android:viewportWidth="48"
+ android:height="48dp"
+ android:viewportHeight="48" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_2"
+ android:translateX="24.25"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_wifi_4_bar_48px_2_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <group
+ android:name="wifi_2"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="wifi"
+ android:pathData="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0.5" />
+ </group>
+ <group
+ android:name="wifi_0"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="wifi_1"
+ android:pathData="M 0.0169982910156,18.4394989014 c 0.0,0.0 23.2140045166,-28.766998291 23.2140045166,-28.766998291 c -0.900009155273,-0.675003051758 -9.82899475098,-8.13400268555 -23.2320098877,-8.13400268555 c -13.4029998779,0.0 -22.3299865723,7.45899963379 -23.2299957275,8.13400268555 c 0.0,0.0 23.2140045166,28.766998291 23.2140045166,28.766998291 c 0.0,0.0 0.0159912109375,0.0220031738281 0.0159912109375,0.0220031738281 c 0.0,0.0 0.00100708007812,-0.00100708007812 0.00100708007812,-0.0010070800781 c 0.0,0.0 0.00100708007812,0.00100708007812 0.00100708007812,0.0010070800781 c 0.0,0.0 0.0159912109375,-0.0220031738281 0.0159912109375,-0.0220031738281 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="0" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 0000000..9f5aaeb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/ic_signal_wifi_transient" >
+ <target
+ android:name="wifi_1"
+ android:animation="@anim/ic_signal_wifi_transient_wifi_1_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml
new file mode 100644
index 0000000..c421f9e
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_bluetooth_transient_animation_interpolator_0.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pathInterpolator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.16666666667,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 6bd79a4..8078c41 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -27,6 +27,7 @@
android:layout_marginEnd="2dp"
android:scaleType="centerInside"
systemui:keyCode="82"
+ systemui:playSound="false"
android:visibility="invisible"
android:contentDescription="@string/accessibility_menu"
/>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index f405943..008fcf0 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -20,6 +20,8 @@
<attr name="keyCode" format="integer" />
<!-- does this button generate longpress / repeat events? -->
<attr name="keyRepeat" format="boolean" />
+ <!-- Should this button play sound effects, default true -->
+ <attr name="playSound" format="boolean" />
<attr name="android:contentDescription" />
</declare-styleable>
<declare-styleable name="ToggleSliderView">
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/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 8c1062b..d57e88c 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -98,6 +98,8 @@
addView(mBatteryIconView, mlp);
updateShowPercent();
+ // Init to not dark at all.
+ onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
}
public void setForceShowPercent(boolean show) {
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 17228b9..bcf1957 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -417,17 +417,17 @@
}
private void updateDismissFraction(float fraction) {
- setDecorViewVisibility(true);
int alpha;
if (mMenuVisible) {
- mMenuContainer.setAlpha(1-fraction);
+ mMenuContainer.setAlpha(1 - fraction);
final float interpolatedAlpha =
MENU_BACKGROUND_ALPHA * (1.0f - fraction) + DISMISS_BACKGROUND_ALPHA * fraction;
- alpha = (int) (interpolatedAlpha*255);
+ alpha = (int) (interpolatedAlpha * 255);
} else {
- alpha = (int) (fraction*DISMISS_BACKGROUND_ALPHA*255);
+ alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
}
mBackgroundDrawable.setAlpha(alpha);
+ setDecorViewVisibility(alpha > 0);
}
private void notifyRegisterInputConsumer() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index dd8cd2b..ad290c3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -113,6 +113,7 @@
private IWindowManager mWindowManager;
private MediaSessionManager mMediaSessionManager;
private int mState = STATE_NO_PIP;
+ private int mResumeResizePinnedStackRunnable = STATE_NO_PIP;
private final Handler mHandler = new Handler();
private List<Listener> mListeners = new ArrayList<>();
private List<MediaListener> mMediaListeners = new ArrayList<>();
@@ -133,7 +134,7 @@
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
public void run() {
- resizePinnedStack(mState);
+ resizePinnedStack(mResumeResizePinnedStackRunnable);
}
};
private final Runnable mClosePipRunnable = new Runnable() {
@@ -364,16 +365,17 @@
void resizePinnedStack(int state) {
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
boolean wasStateNoPip = (mState == STATE_NO_PIP);
- mState = state;
+ mResumeResizePinnedStackRunnable = state;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onPipResizeAboutToStart();
}
if (mSuspendPipResizingReason != 0) {
- if (DEBUG) Log.d(TAG,
- "resizePinnedStack() deferring mSuspendPipResizingReason=" +
- mSuspendPipResizingReason);
+ if (DEBUG) Log.d(TAG, "resizePinnedStack() deferring"
+ + " mSuspendPipResizingReason=" + mSuspendPipResizingReason
+ + " mResumeResizePinnedStackRunnable=" + mResumeResizePinnedStackRunnable);
return;
}
+ mState = state;
switch (mState) {
case STATE_NO_PIP:
mCurrentPipBounds = null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 4e4de15..75e9d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -114,7 +114,8 @@
protected void handleUpdateState(BooleanState state, Object arg) {
final boolean enabled = mController.isBluetoothEnabled();
final boolean connected = mController.isBluetoothConnected();
- final boolean connecting = mController.isBluetoothConnecting();
+ state.isTransient = mController.isBluetoothConnecting()
+ || mController.getBluetoothState() == BluetoothAdapter.STATE_TURNING_ON;
state.dualTarget = true;
state.value = enabled;
if (enabled) {
@@ -124,8 +125,8 @@
state.label = mController.getLastDeviceName();
state.contentDescription = mContext.getString(
R.string.accessibility_bluetooth_name, state.label);
- } else if (connecting) {
- state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connecting);
+ } else if (state.isTransient) {
+ state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth_connecting);
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 22b6a63..2725a32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -20,22 +20,29 @@
import android.content.Intent;
import android.provider.Settings;
import android.service.quicksettings.Tile;
+import android.support.v7.app.MediaRouteChooserDialog;
+import android.support.v7.app.MediaRouteControllerDialog;
+import android.support.v7.media.MediaControlIntent;
+import android.support.v7.media.MediaRouteSelector;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.R.style;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
@@ -109,7 +116,6 @@
if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
showDetail(true);
- mHost.openPanels();
});
return;
}
@@ -117,6 +123,29 @@
}
@Override
+ public void showDetail(boolean show) {
+ mUiHandler.post(() -> {
+ Context context = new ContextThemeWrapper(mContext,
+ R.style.Theme_AppCompat_Light_Dialog_Alert);
+ if (mState.value) {
+ MediaRouteControllerDialog dialog = new MediaRouteControllerDialog(context);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+ dialog.show();
+ } else {
+ // Instead of showing detail, show standard media routing UI.
+ MediaRouteChooserDialog dialog = new MediaRouteChooserDialog(context);
+ MediaRouteSelector selector = new MediaRouteSelector.Builder()
+ .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
+ .build();
+ dialog.setRouteSelector(selector);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+ dialog.show();
+ }
+ mHost.collapsePanels();
+ });
+ }
+
+ @Override
public CharSequence getTileLabel() {
return mContext.getString(R.string.quick_settings_cast_title);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 04be7de..9b3ee30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -180,7 +180,7 @@
private final CallbackInfo mInfo = new CallbackInfo();
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
mInfo.wifiEnabled = enabled;
refreshState(mInfo);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 79b4c4a..7d2d210 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -157,7 +157,10 @@
state.activityOut = cb.enabled && cb.activityOut;
final StringBuffer minimalContentDescription = new StringBuffer();
final Resources r = mContext.getResources();
- if (!state.value) {
+ if (cb.isTransient) {
+ state.icon = ResourceIcon.get(R.drawable.ic_signal_wifi_transient_animation);
+ state.label = r.getString(R.string.quick_settings_wifi_label);
+ } else if (!state.value) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
state.label = r.getString(R.string.quick_settings_wifi_label);
} else if (wifiConnected) {
@@ -182,7 +185,7 @@
state.dualLabelContentDescription = r.getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
- state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ state.state = state.value || cb.isTransient ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
}
@Override
@@ -226,6 +229,7 @@
boolean activityIn;
boolean activityOut;
String wifiSignalContentDescription;
+ boolean isTransient;
@Override
public String toString() {
@@ -237,6 +241,7 @@
.append(",activityIn=").append(activityIn)
.append(",activityOut=").append(activityOut)
.append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
+ .append(",isTransient=").append(isTransient)
.append(']').toString();
}
}
@@ -246,7 +251,7 @@
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
mInfo.enabled = enabled;
mInfo.connected = qsIcon.visible;
@@ -255,6 +260,7 @@
mInfo.activityIn = activityIn;
mInfo.activityOut = activityOut;
mInfo.wifiSignalContentDescription = qsIcon.contentDescription;
+ mInfo.isTransient = isTransient;
refreshState(mInfo);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 67be99e5..88711fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -266,7 +266,7 @@
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {
mWifiVisible = statusIcon.visible && !mBlockWifi;
mWifiStrengthId = statusIcon.icon;
mWifiBadgeId = statusIcon.iconOverlay;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index c339da7..a3ef91d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -15,6 +15,7 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.ArraySet;
import android.view.Gravity;
@@ -22,6 +23,7 @@
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dependency;
@@ -71,13 +73,18 @@
}
@Override
- protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
+ protected void onIconAdded(int index, String slot, boolean blocked,
+ StatusBarIcon icon) {
+ StatusBarIconView v = addIcon(index, slot, blocked, icon);
+ mDarkIconDispatcher.addDarkReceiver(v);
+ }
+
+ @Override
+ protected LayoutParams onCreateLayoutParams() {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
- mGroup.addView(view, index, lp);
- mDarkIconDispatcher.addDarkReceiver(view);
+ return lp;
}
@Override
@@ -116,11 +123,26 @@
com.android.internal.R.dimen.status_bar_icon_size);
}
- protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
+ protected void onIconAdded(int index, String slot, boolean blocked,
+ StatusBarIcon icon) {
+ addIcon(index, slot, blocked, icon);
+ }
+
+ protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
+ StatusBarIcon icon) {
+ StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
view.set(icon);
- mGroup.addView(view, index, new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
+ mGroup.addView(view, index, onCreateLayoutParams());
+ return view;
+ }
+
+ @VisibleForTesting
+ protected StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+ return new StatusBarIconView(mContext, slot, null, blocked);
+ }
+
+ protected LinearLayout.LayoutParams onCreateLayoutParams() {
+ return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
}
protected void destroy() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index 5ab99e9..a456786 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -109,13 +109,13 @@
@Override
public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
final IconState qsIcon, final boolean activityIn, final boolean activityOut,
- final String description) {
+ final String description, boolean isTransient) {
post(new Runnable() {
@Override
public void run() {
for (SignalCallback callback : mSignalCallbacks) {
callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
- description);
+ description, isTransient);
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 882902e..b5d22b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -49,6 +49,7 @@
public class KeyButtonView extends ImageView implements ButtonInterface {
+ private final boolean mPlaySounds;
private int mContentDescriptionRes;
private long mDownTime;
private int mCode;
@@ -90,6 +91,7 @@
mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
+ mPlaySounds = a.getBoolean(R.styleable.KeyButtonView_playSound, true);
TypedValue value = new TypedValue();
if (a.getValue(R.styleable.KeyButtonView_android_contentDescription, value)) {
@@ -241,8 +243,9 @@
}
public void playSoundEffect(int soundConstant) {
+ if (!mPlaySounds) return;
mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
- };
+ }
public void sendEvent(int action, int flags) {
sendEvent(action, flags, SystemClock.uptimeMillis());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 5657560..c02ce0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -19,12 +19,10 @@
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
-import android.view.View;
import com.android.settingslib.net.DataUsageController;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.DemoMode;
-import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.List;
@@ -48,7 +46,7 @@
public interface SignalCallback {
default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
- boolean activityIn, boolean activityOut, String description) {}
+ boolean activityIn, boolean activityOut, String description, boolean isTransient) {}
default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 12b7098..2104cb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -150,7 +150,7 @@
Utils.getWifiBadgeResource(mCurrentState.badgeEnum), contentDescription);
callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
- wifiDesc);
+ wifiDesc, mCurrentState.isTransient);
}
@Override
@@ -170,6 +170,9 @@
mWifiTracker.handleBroadcast(intent);
updateScoreCacheIfNecessary(previousNetworkKey);
+ mCurrentState.isTransient = mWifiTracker.state == WifiManager.WIFI_STATE_ENABLING
+ || mWifiTracker.state == WifiManager.WIFI_AP_STATE_DISABLING
+ || mWifiTracker.connecting;
mCurrentState.enabled = mWifiTracker.enabled;
mCurrentState.connected = mWifiTracker.connected;
mCurrentState.ssid = mWifiTracker.ssid;
@@ -252,6 +255,7 @@
static class WifiState extends SignalController.State {
String ssid;
int badgeEnum;
+ boolean isTransient;
@Override
public void copyFrom(State s) {
@@ -259,19 +263,23 @@
WifiState state = (WifiState) s;
ssid = state.ssid;
badgeEnum = state.badgeEnum;
+ isTransient = state.isTransient;
}
@Override
protected void toString(StringBuilder builder) {
super.toString(builder);
builder.append(',').append("ssid=").append(ssid);
+ builder.append(',').append("badgeEnum=").append(badgeEnum);
+ builder.append(',').append("isTransient=").append(isTransient);
}
@Override
public boolean equals(Object o) {
return super.equals(o)
&& Objects.equals(((WifiState) o).ssid, ssid)
- && (((WifiState) o).badgeEnum == badgeEnum);
+ && (((WifiState) o).badgeEnum == badgeEnum)
+ && (((WifiState) o).isTransient == isTransient);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 4eb1db6..9c69b98 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -110,10 +110,35 @@
}
public static class SubSettingsFragment extends PreferenceFragment {
+ private PreferenceScreen mParentScreen;
+
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
- setPreferenceScreen((PreferenceScreen) ((PreferenceFragment) getTargetFragment())
- .getPreferenceScreen().findPreference(rootKey));
+ mParentScreen =
+ (PreferenceScreen) ((PreferenceFragment) getTargetFragment())
+ .getPreferenceScreen().findPreference(rootKey);
+ PreferenceScreen screen =
+ getPreferenceManager().createPreferenceScreen(
+ getPreferenceManager().getContext());
+ setPreferenceScreen(screen);
+ // Copy all the preferences over to this screen so they go into the attached state.
+ while (mParentScreen.getPreferenceCount() > 0) {
+ Preference p = mParentScreen.getPreference(0);
+ mParentScreen.removePreference(p);
+ screen.addPreference(p);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ // Copy all the preferences back so we don't lose them.
+ PreferenceScreen screen = getPreferenceScreen();
+ while (screen.getPreferenceCount() > 0) {
+ Preference p = screen.getPreference(0);
+ screen.removePreference(p);
+ mParentScreen.addPreference(p);
+ }
}
}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index ddd8d7b..8eedf31 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -41,6 +41,7 @@
android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-appcompat \
+ android-support-v7-mediarouter \
android-support-v14-preference \
android-support-v17-leanback
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
new file mode 100644
index 0000000..ecae39a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.phone;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class StatusBarIconControllerTest extends LeakCheckedTest {
+
+ @Before
+ public void setup() {
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ mDependency.injectMockDependency(DarkIconDispatcher.class);
+ }
+
+ @Test
+ public void testSetCalledOnAdd_IconManager() {
+ LinearLayout layout = new LinearLayout(mContext);
+ TestIconManager manager = new TestIconManager(layout);
+ StatusBarIcon icon = mock(StatusBarIcon.class);
+
+ manager.onIconAdded(0, "test_slot", false, icon);
+ verify(manager.mMock).set(eq(icon));
+ }
+
+ @Test
+ public void testSetCalledOnAdd_DarkIconManager() {
+ LinearLayout layout = new LinearLayout(mContext);
+ TestDarkIconManager manager = new TestDarkIconManager(layout);
+ StatusBarIcon icon = mock(StatusBarIcon.class);
+
+ manager.onIconAdded(0, "test_slot", false, icon);
+ verify(manager.mMock).set(eq(icon));
+ }
+
+ private static class TestDarkIconManager extends DarkIconManager {
+
+ private final StatusBarIconView mMock;
+
+ public TestDarkIconManager(LinearLayout group) {
+ super(group);
+ mMock = mock(StatusBarIconView.class);
+ }
+
+ @Override
+ protected StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+ return mMock;
+ }
+ }
+
+ private static class TestIconManager extends IconManager {
+
+ private final StatusBarIconView mMock;
+
+ public TestIconManager(ViewGroup group) {
+ super(group);
+ mMock = mock(StatusBarIconView.class);
+ }
+
+ @Override
+ protected StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+ return mMock;
+ }
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index b544d9d..3ed1681 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -79,7 +79,7 @@
boolean in = true;
boolean out = true;
String description = "Test";
- mHandler.setWifiIndicators(enabled, status, qs, in, out, description);
+ mHandler.setWifiIndicators(enabled, status, qs, in, out, description, true);
waitForCallbacks();
ArgumentCaptor<Boolean> enableArg = ArgumentCaptor.forClass(Boolean.class);
@@ -88,15 +88,17 @@
ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<Boolean> isTransient = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mSignalCallback).setWifiIndicators(enableArg.capture(),
statusArg.capture(), qsArg.capture(), inArg.capture(), outArg.capture(),
- descArg.capture());
+ descArg.capture(), isTransient.capture());
assertEquals(enabled, (boolean) enableArg.getValue());
assertEquals(status, statusArg.getValue());
assertEquals(qs, qsArg.getValue());
assertEquals(in, (boolean) inArg.getValue());
assertEquals(out, (boolean) outArg.getValue());
assertEquals(description, descArg.getValue());
+ assertTrue(isTransient.getValue());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index efa232b..483a837 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -122,7 +122,7 @@
ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(),
- any());
+ any(), anyBoolean());
IconState iconState = iconArg.getValue();
assertEquals("Badged Wifi Resource is set",
@@ -269,7 +269,7 @@
ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
- anyBoolean(), any(), any(), inArg.capture(), outArg.capture(), any());
+ anyBoolean(), any(), any(), inArg.capture(), outArg.capture(), any(), anyBoolean());
assertEquals("WiFi data in, in quick settings", in, (boolean) inArg.getValue());
assertEquals("WiFi data out, in quick settings", out, (boolean) outArg.getValue());
}
@@ -282,7 +282,7 @@
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
enabledArg.capture(), any(), iconArg.capture(), anyBoolean(),
- anyBoolean(), descArg.capture());
+ anyBoolean(), descArg.capture(), anyBoolean());
IconState iconState = iconArg.getValue();
assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue());
assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
@@ -295,7 +295,7 @@
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(),
- any());
+ any(), anyBoolean());
IconState iconState = iconArg.getValue();
assertEquals("WiFi visible, in status bar", visible, iconState.visible);
assertEquals("WiFi signal, in status bar", icon, iconState.icon);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index da441f5..78bc01d 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3188,21 +3188,21 @@
// ACTION: Logged when a provisioning session has completed
PROVISIONING_SESSION_COMPLETED = 735;
- // ACTION: An app requested the permission READ_PHONE_NUMBER
+ // ACTION: An app requested the permission READ_PHONE_NUMBERS
// PACKAGE: The package name of the app requesting the permission
- ACTION_PERMISSION_REQUEST_READ_PHONE_NUMBER = 736;
+ ACTION_PERMISSION_REQUEST_READ_PHONE_NUMBERS = 736;
- // ACTION: An app was granted the permission READ_PHONE_NUMBER
+ // ACTION: An app was granted the permission READ_PHONE_NUMBERS
// PACKAGE: The package name of the app that was granted the permission
- ACTION_PERMISSION_GRANT_READ_PHONE_NUMBER = 737;
+ ACTION_PERMISSION_GRANT_READ_PHONE_NUMBERS = 737;
- // ACTION: An app requested the permission READ_PHONE_NUMBER and the request was denied
+ // ACTION: An app requested the permission READ_PHONE_NUMBERS and the request was denied
// PACKAGE: The package name of the app requesting the permission
- ACTION_PERMISSION_DENIED_READ_PHONE_NUMBER = 738;
+ ACTION_PERMISSION_DENIED_READ_PHONE_NUMBERS = 738;
- // ACTION: The permission READ_PHONE_NUMBER was revoked for an app
+ // ACTION: The permission READ_PHONE_NUMBERS was revoked for an app
// PACKAGE: The package name of the app the permission was revoked for
- ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBER = 739;
+ ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBERS = 739;
// ACTION: QS Brightness Slider (with auto brightness disabled, and VR enabled)
// SUBTYPE: slider value
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 97099df..f6d91f4 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -153,10 +153,34 @@
// Package: android
NOTE_SSL_CERT_INFO = 33;
+ // Warn the user they are approaching their data limit.
+ // Package: android
+ NOTE_NET_WARNING = 34;
+
+ // Warn the user they have reached their data limit.
+ // Package: android
+ NOTE_NET_LIMIT = 35;
+
+ // Warn the user they have exceeded their data limit.
+ // Package: android
+ NOTE_NET_LIMIT_SNOOZED = 36;
+
// 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
+ // Network status notes, previously decleared in metrics_constants with these values
+ // Package: android
+ //
+ // A captive portal was detected during network validation
+ NOTE_NETWORK_SIGN_IN = 740;
+ // An unvalidated network without Internet was selected by the user
+ NOTE_NETWORK_NO_INTERNET = 741;
+ // A validated network failed revalidation and lost Internet access
+ NOTE_NETWORK_LOST_INTERNET = 742;
+ // The system default network switched to a different network
+ NOTE_NETWORK_SWITCH = 743;
+
// Notify the user that their work profile has been deleted
// Package: android
NOTE_PROFILE_WIPED = 1001;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index acaae7b..087c248 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -104,6 +104,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IntPair;
import com.android.server.LocalServices;
import com.android.server.policy.AccessibilityShortcutController;
@@ -2360,7 +2361,7 @@
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
synchronized (mLock) {
pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
pw.println();
@@ -3658,7 +3659,7 @@
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
synchronized (mLock) {
pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
.loadLabel(mContext.getPackageManager()));
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 8aa37ef..0482e73 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -97,6 +97,7 @@
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.widget.IRemoteViewsAdapterConnection;
import com.android.internal.widget.IRemoteViewsFactory;
@@ -714,10 +715,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
- "Permission Denial: can't dump from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
if (args.length > 0 && "--proto".equals(args[0])) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 72d37ad..be14440 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -60,6 +60,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -418,13 +419,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingPermission(
- Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump autofill from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
pw.print("Disabled users: "); pw.println(mDisabledUsers);
final int size = mServicesCache.size();
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 3aba723..20def0c 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -156,7 +156,7 @@
}
// Then checks if the session has a response waiting authentication; if so, uses it instead.
final FillResponse currentResponse = mSession.getCurrentResponse();
- if (currentResponse.getAuthentication() != null) {
+ if (currentResponse != null && currentResponse.getAuthentication() != null) {
mListener.onFillReady(currentResponse, this.id, mCurrentValue);
}
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 57d3570..413746f 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -117,6 +117,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
+import com.android.internal.util.DumpUtils;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
import com.android.server.SystemConfig;
@@ -11138,7 +11139,7 @@
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
long identityToken = Binder.clearCallingIdentity();
try {
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index c40f2ca..a109e631 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -35,6 +35,8 @@
import android.os.UserHandle;
import android.util.Slog;
+import com.android.internal.util.DumpUtils;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -372,7 +374,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
BackupManagerService svc = mService;
if (svc != null) {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index c6af290..8b32c16 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -80,6 +80,7 @@
import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
import static android.app.AlarmManager.ELAPSED_REALTIME;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.LocalLog;
class AlarmManagerService extends SystemService {
@@ -1384,14 +1385,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump AlarmManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
dumpImpl(pw);
}
};
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a5e357c..dcf6fd7 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -70,6 +70,7 @@
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -2028,13 +2029,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ApOps service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
if (args != null) {
for (int i=0; i<args.length; i++) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index fd44794..83bd9eb 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -24,6 +24,7 @@
import android.os.ShellCallback;
import android.os.ShellCommand;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.DumpUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
@@ -945,14 +946,7 @@
private final class BinderService extends Binder {
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump Battery service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
if (args.length > 0 && "--proto".equals(args[0])) {
dumpProto(fd);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 58e8631..6c4895c 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -60,6 +60,7 @@
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
+import com.android.internal.util.DumpUtils;
import com.android.server.pm.PackageManagerService;
import java.io.FileDescriptor;
@@ -2084,7 +2085,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
String errorMsg = null;
boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
diff --git a/services/core/java/com/android/server/CommonTimeManagementService.java b/services/core/java/com/android/server/CommonTimeManagementService.java
index 60b366a..07c8679 100644
--- a/services/core/java/com/android/server/CommonTimeManagementService.java
+++ b/services/core/java/com/android/server/CommonTimeManagementService.java
@@ -37,6 +37,7 @@
import android.os.SystemProperties;
import android.util.Log;
+import com.android.internal.util.DumpUtils;
import com.android.server.net.BaseNetworkObserver;
/**
@@ -177,13 +178,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println(String.format(
- "Permission Denial: can't dump CommonTimeManagement service from from " +
- "pid=%d, uid=%d", Binder.getCallingPid(), Binder.getCallingUid()));
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
if (!mDetectedAtStartup) {
pw.println("Native Common Time service was not detected at startup. " +
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d02b726..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;
@@ -125,10 +117,12 @@
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
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;
@@ -146,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;
@@ -220,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
@@ -245,6 +228,7 @@
private INetworkManagementService mNetd;
private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager;
+ private NetworkPolicyManagerInternal mPolicyManagerInternal;
private String mCurrentTcpBufferSizes;
@@ -714,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);
@@ -990,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) {
@@ -1480,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 + ")");
- }
}
};
@@ -1927,14 +1842,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ConnectivityService " +
- "from from pid=" + Binder.getCallingPid() + ", uid=" +
- Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
if (argsContain(args, "--diag")) {
dumpNetworkDiagnostics(pw);
@@ -1982,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()) {
@@ -3443,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);
@@ -4203,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/CountryDetectorService.java b/services/core/java/com/android/server/CountryDetectorService.java
index a478b2f..d8a2fe3 100644
--- a/services/core/java/com/android/server/CountryDetectorService.java
+++ b/services/core/java/com/android/server/CountryDetectorService.java
@@ -21,6 +21,7 @@
import java.util.HashMap;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.server.location.ComprehensiveCountryDetector;
import android.content.Context;
@@ -208,8 +209,7 @@
@SuppressWarnings("unused")
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
if (!DEBUG) return;
try {
final Printer p = new PrintWriterPrinter(fout);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 26b15d8..8945952 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -81,6 +81,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.AtomicFile;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
@@ -2879,13 +2880,7 @@
}
void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
if (args != null) {
int userId = UserHandle.USER_SYSTEM;
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 1bdff6b..800081e 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -30,6 +30,7 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.util.DumpUtils;
import com.android.server.storage.DiskStatsFileLogger;
import com.android.server.storage.DiskStatsLoggingService;
@@ -62,7 +63,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
// Run a quick-and-dirty performance test: write 512 bytes
byte[] junk = new byte[512];
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index 122074b..e5a7b4e 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -35,6 +35,8 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.util.DumpUtils;
+
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -252,14 +254,7 @@
private final class BinderService extends Binder {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump dock observer service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 040d22c..9d3d531 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -40,6 +40,7 @@
import libcore.io.IoUtils;
import com.android.internal.os.IDropBoxManagerService;
+import com.android.internal.util.DumpUtils;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -350,11 +351,7 @@
}
public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: Can't dump DropBoxManagerService");
- return;
- }
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
try {
init();
diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java
index 19bedfb..d3f77b6 100644
--- a/services/core/java/com/android/server/GraphicsStatsService.java
+++ b/services/core/java/com/android/server/GraphicsStatsService.java
@@ -37,6 +37,8 @@
import android.view.IGraphicsStats;
import android.view.IGraphicsStatsCallback;
+import com.android.internal.util.DumpUtils;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -345,7 +347,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, fout)) return;
boolean dumpProto = false;
for (String str : args) {
if ("--proto".equals(str)) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index e619e8b..39bfeda 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -33,6 +33,7 @@
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.TransferPipe;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethod;
@@ -4378,14 +4379,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump InputMethodManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
IInputMethod method;
ClientState client;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 979096e..f0720f3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -26,6 +26,7 @@
import com.android.internal.location.ProviderRequest;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.FlpHardwareProvider;
import com.android.server.location.FusedProxy;
@@ -3026,13 +3027,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump LocationManagerService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
pw.println("Current Location Manager state:");
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 6f3ff10..e26630b 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -79,6 +79,7 @@
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
@@ -2178,14 +2179,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump LockSettingsService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (this) {
pw.println("Current lock settings service state:");
diff --git a/services/core/java/com/android/server/LockSettingsShellCommand.java b/services/core/java/com/android/server/LockSettingsShellCommand.java
index 91bd98e..9d671e39 100644
--- a/services/core/java/com/android/server/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/LockSettingsShellCommand.java
@@ -35,6 +35,7 @@
private static final String COMMAND_SET_PASSWORD = "set-password";
private static final String COMMAND_CLEAR = "clear";
private static final String COMMAND_SP = "sp";
+ private static final String COMMAND_SET_DISABLED = "set-disabled";
private int mCurrentUserId;
private final LockPatternUtils mLockPatternUtils;
@@ -72,6 +73,9 @@
case COMMAND_SP:
runEnableSp();
break;
+ case COMMAND_SET_DISABLED:
+ runSetDisabled();
+ break;
default:
getErrPrintWriter().println("Unknown command: " + cmd);
break;
@@ -132,6 +136,12 @@
getOutPrintWriter().println("Lock credential cleared");
}
+ private void runSetDisabled() throws RemoteException {
+ final boolean disabled = Boolean.parseBoolean(mNew);
+ mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId);
+ getOutPrintWriter().println("Lock screen disabled set to " + disabled);
+ }
+
private boolean checkCredential() throws RemoteException, RequestThrottledException {
final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 74328c0..ce4efd1 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -95,6 +95,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.HexDump;
import com.android.internal.util.Preconditions;
import com.android.server.NativeDaemonConnector.Command;
@@ -2313,7 +2314,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("NetworkManagementService NativeDaemonConnector Log:");
mConnector.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 78c0fe6..a5debda 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -69,6 +69,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.TransferPipe;
+import com.android.internal.util.DumpUtils;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -925,7 +926,7 @@
@Override
protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) {
- mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
final long token = Binder.clearCallingIdentity();
try {
NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index b64c65d..ebcda44 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -40,6 +40,7 @@
import android.util.TrustedTime;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.DumpUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -323,15 +324,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump NetworkTimeUpdateService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " without permission "
- + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.print("PollingIntervalMs: ");
TimeUtils.formatDuration(mPollingIntervalMs, pw);
pw.print("\nPollingIntervalShorterMs: ");
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index a44b065..8ae95d5 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -41,6 +41,7 @@
import java.util.concurrent.CountDownLatch;
import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -811,13 +812,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
for (ClientInfo client : mClients.values()) {
pw.println("Client Info");
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index fa5a52c..a94bf79 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -37,6 +37,7 @@
import com.android.internal.app.ResolverActivity;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
@@ -333,7 +334,7 @@
private final class BinderService extends Binder {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("Pinned Files:");
synchronized(this) {
for (int i = 0; i < mPinnedFiles.size(); i++) {
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index cecd7e5..3b36c3c 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -18,14 +18,13 @@
import android.content.ContentResolver;
import android.content.Context;
-import android.content.pm.UserInfo;
import android.os.Build;
+import android.os.Environment;
import android.os.FileUtils;
import android.os.RecoverySystem;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.util.ExceptionUtils;
@@ -70,7 +69,7 @@
private static boolean isDisabled() {
// Check if we're explicitly enabled for testing
- if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, true)) {
+ if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, false)) {
return false;
}
@@ -203,7 +202,7 @@
} catch (Throwable t) {
res = new RuntimeException("Failed to reset global settings", t);
}
- for (int userId : getAllUserIds(context)) {
+ for (int userId : getAllUserIds()) {
try {
Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
} catch (Throwable t) {
@@ -314,13 +313,16 @@
@Override public void setStart(long start) { this.start = start; }
}
- private static int[] getAllUserIds(Context context) {
+ private static int[] getAllUserIds() {
int[] userIds = { UserHandle.USER_SYSTEM };
try {
- final UserManager um = context.getSystemService(UserManager.class);
- for (UserInfo user : um.getUsers()) {
- if (user.id != UserHandle.USER_SYSTEM) {
- userIds = ArrayUtils.appendInt(userIds, user.id);
+ for (File file : FileUtils.listFilesOrEmpty(Environment.getDataSystemDeDirectory())) {
+ try {
+ final int userId = Integer.parseInt(file.getName());
+ if (userId != UserHandle.USER_SYSTEM) {
+ userIds = ArrayUtils.appendInt(userIds, userId);
+ }
+ } catch (NumberFormatException ignored) {
}
}
} catch (Throwable t) {
diff --git a/services/core/java/com/android/server/SamplingProfilerService.java b/services/core/java/com/android/server/SamplingProfilerService.java
index fbf1aa4..5f92695 100644
--- a/services/core/java/com/android/server/SamplingProfilerService.java
+++ b/services/core/java/com/android/server/SamplingProfilerService.java
@@ -27,6 +27,7 @@
import android.os.SystemProperties;
import android.provider.Settings;
import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.util.DumpUtils;
import java.io.File;
import java.io.FileDescriptor;
@@ -96,7 +97,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("SamplingProfilerService:");
pw.println("Watching directory: " + SNAPSHOT_DIR);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index c68000a..d796098 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -102,6 +102,7 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
@@ -3911,7 +3912,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 531df81..7c1a609 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -60,6 +60,7 @@
import com.android.internal.telephony.PhoneConstantConversions;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.DumpUtils;
import com.android.server.am.BatteryStatsService;
/**
@@ -1391,12 +1392,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump telephony.registry from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mRecords) {
final int recordCount = mRecords.size();
pw.println("last known state:");
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index feda273..9068745 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -25,6 +25,7 @@
import com.android.internal.textservice.ISpellCheckerSessionListener;
import com.android.internal.textservice.ITextServicesManager;
import com.android.internal.textservice.ITextServicesSessionListener;
+import com.android.internal.util.DumpUtils;
import org.xmlpull.v1.XmlPullParserException;
@@ -757,14 +758,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump TextServicesManagerService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized(mSpellCheckerMap) {
pw.println("Current Text Services Manager state:");
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 227e2a2..04421cc 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -60,6 +60,7 @@
import com.android.internal.app.DisableCarModeActivity;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.util.DumpUtils;
import com.android.server.power.ShutdownThread;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
@@ -352,15 +353,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump uimode service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
dumpImpl(pw);
}
};
diff --git a/services/core/java/com/android/server/UpdateLockService.java b/services/core/java/com/android/server/UpdateLockService.java
index 7f33973..06f73e2 100644
--- a/services/core/java/com/android/server/UpdateLockService.java
+++ b/services/core/java/com/android/server/UpdateLockService.java
@@ -29,6 +29,8 @@
import android.os.UserHandle;
import android.util.Slog;
+import com.android.internal.util.DumpUtils;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -112,14 +114,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump update lock service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
mLocks.dump(pw);
}
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index c4676d1..678ae38 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -54,6 +54,7 @@
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.DumpUtils;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.FileDescriptor;
@@ -874,14 +875,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
- pw.println("Permission Denial: can't dump vibrator service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
pw.println("Previous vibrations:");
synchronized (mLock) {
for (VibrationInfo info : mPreviousVibrations) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index ad2ed93..d996ee2 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -92,6 +92,7 @@
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
@@ -4867,13 +4868,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- fout.println("Permission Denial: can't dump AccountsManager from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
final IndentingPrintWriter ipw = new IndentingPrintWriter(fout, " ");
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8b0665c..4cbfb27 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -398,7 +398,7 @@
r.delayedStop = false;
r.fgRequired = fgRequired;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- service, neededGrants));
+ service, neededGrants, callingUid));
final ServiceMap smap = getServiceMapLocked(r.userId);
boolean addToStarting = false;
@@ -1140,7 +1140,7 @@
// Service is already running, so we can immediately
// publish the connection.
try {
- c.conn.connected(s.name, b.intent.binder);
+ c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " to connection " + c.conn.asBinder()
@@ -1194,7 +1194,7 @@
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
try {
- c.conn.connected(r.name, service);
+ c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
@@ -1355,10 +1355,10 @@
if (r == null) {
try {
// TODO: come back and remove this assumption to triage all services
- ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
+ ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- userId);
+ userId, callingUid);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -1927,7 +1927,7 @@
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- null, null));
+ null, null, 0));
}
sendServiceArgsLocked(r, execInFg, true);
@@ -1979,7 +1979,8 @@
mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
si.getUriPermissionsLocked());
}
- // TODO b/34123112; Insert ephemeral grant here
+ mAm.grantEphemeralAccessLocked(r.userId, si.intent,
+ r.appInfo.uid, UserHandle.getAppId(si.callingId));
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
@@ -2080,7 +2081,7 @@
// being brought down. Mark it as dead.
cr.serviceDead = true;
try {
- cr.conn.connected(r.name, null);
+ cr.conn.connected(r.name, null, true);
} catch (Exception e) {
Slog.w(TAG, "Failure disconnecting service " + r.name +
" to connection " + c.get(i).conn.asBinder() +
@@ -2591,7 +2592,7 @@
stopServiceLocked(sr);
} else {
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
- sr.makeNextStartId(), baseIntent, null));
+ sr.makeNextStartId(), baseIntent, null, 0));
if (sr.app != null && sr.app.thread != null) {
// We always run in the foreground, since this is called as
// part of the "remove task" UI operation.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 81d0a7c..b4ea49b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -350,6 +350,7 @@
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
@@ -2656,14 +2657,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump meminfo from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+ "meminfo", pw)) return;
mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null);
}
}
@@ -2676,14 +2671,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump gfxinfo from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+ "gfxinfo", pw)) return;
mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
}
}
@@ -2696,14 +2685,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump dbinfo from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+ "dbinfo", pw)) return;
mActivityManagerService.dumpDbInfo(fd, pw, args);
}
}
@@ -2716,14 +2699,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump cpuinfo from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+ "cpuinfo", pw)) return;
synchronized (mActivityManagerService.mProcessCpuTracker) {
pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad());
pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState(
@@ -11539,6 +11516,9 @@
}
}
checkTime(startTime, "getContentProviderImpl: done!");
+
+ grantEphemeralAccessLocked(userId, null /*intent*/,
+ cpi.applicationInfo.uid, UserHandle.getAppId(Binder.getCallingUid()));
}
// Wait for the provider to be published...
@@ -12314,13 +12294,17 @@
mRecentTasks.notifyTaskPersisterLocked(task, flush);
}
- /** Notifies all listeners when the pinned stack animation starts. */
+ /**
+ * Notifies all listeners when the pinned stack animation starts.
+ */
@Override
public void notifyPinnedStackAnimationStarted() {
mTaskChangeNotificationController.notifyPinnedStackAnimationStarted();
}
- /** Notifies all listeners when the pinned stack animation ends. */
+ /**
+ * Notifies all listeners when the pinned stack animation ends.
+ */
@Override
public void notifyPinnedStackAnimationEnded() {
mTaskChangeNotificationController.notifyPinnedStackAnimationEnded();
@@ -14758,15 +14742,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ActivityManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " without permission "
- + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
boolean dumpAll = false;
boolean dumpClient = false;
@@ -17667,7 +17643,6 @@
*/
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
- Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid);
if (index >= 0) {
removeLruProcessLocked(app);
ProcessList.remove(app.pid);
@@ -19815,6 +19790,10 @@
}
}
+ /**
+ * NOTE: For the pinned stack, this method is only called after the bounds animation has
+ * animated the stack to the fullscreen.
+ */
@Override
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 8f1aa0d..cbb51e1 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -25,8 +25,20 @@
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
+import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
+import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.CATEGORY_LAUNCHER;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
@@ -43,15 +55,19 @@
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
+import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
+import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
@@ -68,8 +84,30 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityManagerService.IS_USER_BUILD;
import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.am.ActivityStack.LAUNCH_TICK;
+import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
+import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
+import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME;
+import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.am.TaskPersister.DEBUG;
+import static com.android.server.am.TaskPersister.IMAGE_EXTENSION;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.annotation.NonNull;
import android.app.ActivityManager.TaskDescription;
@@ -109,6 +147,7 @@
import com.android.internal.content.ReferrerIntent;
import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
+import com.android.server.AttributeCache.Entry;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.AppWindowContainerController;
@@ -199,6 +238,8 @@
long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
long pauseTime; // last time we started pausing the activity
long launchTickTime; // base time for launch tick messages
+ // TODO: Refactor mLastReportedConfiguration and mLastReportedOverrideConfiguration to use a
+ // MergedConfiguration object for clarity.
private Configuration mLastReportedConfiguration; // configuration activity was last running in
// Overridden configuration by the activity task
// WARNING: Reference points to {@link TaskRecord#getMergedOverrideConfig}, so its internal
@@ -243,6 +284,10 @@
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
boolean immersive; // immersive mode (don't interrupt if possible)
boolean forceNewConfig; // force re-create with new config next time
+ private boolean mInMultiWindowMode; // whether or not this activity is currently in multi-window
+ // mode (default false)
+ private boolean mInPictureInPictureMode; // whether or not this activity is currently in
+ // picture-in-picture mode (default false)
boolean supportsPictureInPictureWhilePausing; // This flag is set by the system to indicate
// that the activity can enter picture in picture while pausing (ie. only when another
// task is brought to front or started)
@@ -299,6 +344,7 @@
*/
private final Configuration mTmpConfig1 = new Configuration();
private final Configuration mTmpConfig2 = new Configuration();
+ private final Configuration mTmpConfig3 = new Configuration();
private final Point mTmpPoint = new Point();
private final Rect mTmpBounds = new Rect();
@@ -573,25 +619,51 @@
}
}
- void scheduleMultiWindowModeChanged() {
+ void updateMultiWindowMode() {
if (task == null || task.getStack() == null || app == null || app.thread == null) {
return;
}
+
+ // An activity is considered to be in multi-window mode if its task isn't fullscreen.
+ final boolean inMultiWindowMode = !task.mFullscreen;
+ if (inMultiWindowMode != mInMultiWindowMode) {
+ mInMultiWindowMode = inMultiWindowMode;
+ scheduleMultiWindowModeChanged(getConfiguration());
+ }
+ }
+
+ private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
try {
- // An activity is considered to be in multi-window mode if its task isn't fullscreen.
- app.thread.scheduleMultiWindowModeChanged(appToken, !task.mFullscreen);
+ app.thread.scheduleMultiWindowModeChanged(appToken, mInMultiWindowMode,
+ overrideConfig);
} catch (Exception e) {
// If process died, I don't care.
}
}
- void schedulePictureInPictureModeChanged() {
+ void updatePictureInPictureMode(Rect targetStackBounds) {
if (task == null || task.getStack() == null || app == null || app.thread == null) {
return;
}
+
+ final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) &&
+ (targetStackBounds != null);
+ if (inPictureInPictureMode != mInPictureInPictureMode) {
+ // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
+ // update that here in order
+ mInPictureInPictureMode = inPictureInPictureMode;
+ mInMultiWindowMode = inPictureInPictureMode;
+ final Configuration newConfig = task.computeNewOverrideConfigurationForBounds(
+ targetStackBounds, null);
+ schedulePictureInPictureModeChanged(newConfig);
+ scheduleMultiWindowModeChanged(newConfig);
+ }
+ }
+
+ private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
try {
- app.thread.schedulePictureInPictureModeChanged(
- appToken, task.getStackId() == PINNED_STACK_ID);
+ app.thread.schedulePictureInPictureModeChanged(appToken, mInPictureInPictureMode,
+ overrideConfig);
} catch (Exception e) {
// If process died, no one cares.
}
@@ -684,7 +756,7 @@
resultTo = _resultTo;
resultWho = _resultWho;
requestCode = _reqCode;
- state = ActivityState.INITIALIZING;
+ state = INITIALIZING;
frontOfTask = false;
launchFailed = false;
stopped = false;
@@ -768,7 +840,7 @@
packageName = aInfo.applicationInfo.packageName;
launchMode = aInfo.launchMode;
- AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+ Entry ent = AttributeCache.instance().get(packageName,
realTheme, com.android.internal.R.styleable.Window, userId);
final boolean translucent = ent != null && (ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowIsTranslucent, false)
@@ -860,16 +932,16 @@
}
private boolean isHomeIntent(Intent intent) {
- return Intent.ACTION_MAIN.equals(intent.getAction())
- && intent.hasCategory(Intent.CATEGORY_HOME)
+ return ACTION_MAIN.equals(intent.getAction())
+ && intent.hasCategory(CATEGORY_HOME)
&& intent.getCategories().size() == 1
&& intent.getData() == null
&& intent.getType() == null;
}
static boolean isMainIntent(Intent intent) {
- return Intent.ACTION_MAIN.equals(intent.getAction())
- && intent.hasCategory(Intent.CATEGORY_LAUNCHER)
+ return ACTION_MAIN.equals(intent.getAction())
+ && intent.hasCategory(CATEGORY_LAUNCHER)
&& intent.getCategories().size() == 1
&& intent.getData() == null
&& intent.getType() == null;
@@ -986,8 +1058,8 @@
}
boolean isPersistable() {
- return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
- info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
+ return (info.persistableMode == PERSIST_ROOT_ONLY ||
+ info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
(intent == null ||
(intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
}
@@ -1203,13 +1275,13 @@
// - It is currently resumed or paused. i.e. it is currently visible to the user and we want
// the user to see the visual effects caused by the intent delivery now.
// - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
- if ((state == ActivityState.RESUMED || state == ActivityState.PAUSED
+ if ((state == RESUMED || state == PAUSED
|| isTopActivityWhileSleeping) && app != null && app.thread != null) {
try {
ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
ar.add(rintent);
app.thread.scheduleNewIntent(
- ar, appToken, state == ActivityState.PAUSED /* andPause */);
+ ar, appToken, state == PAUSED /* andPause */);
unsent = false;
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
@@ -1233,17 +1305,17 @@
void applyOptionsLocked() {
if (pendingOptions != null
- && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
+ && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
final int animationType = pendingOptions.getAnimationType();
switch (animationType) {
- case ActivityOptions.ANIM_CUSTOM:
+ case ANIM_CUSTOM:
service.mWindowManager.overridePendingAppTransition(
pendingOptions.getPackageName(),
pendingOptions.getCustomEnterResId(),
pendingOptions.getCustomExitResId(),
pendingOptions.getOnAnimationStartListener());
break;
- case ActivityOptions.ANIM_CLIP_REVEAL:
+ case ANIM_CLIP_REVEAL:
service.mWindowManager.overridePendingAppTransitionClipReveal(
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getWidth(), pendingOptions.getHeight());
@@ -1254,7 +1326,7 @@
pendingOptions.getStartY()+pendingOptions.getHeight()));
}
break;
- case ActivityOptions.ANIM_SCALE_UP:
+ case ANIM_SCALE_UP:
service.mWindowManager.overridePendingAppTransitionScaleUp(
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getWidth(), pendingOptions.getHeight());
@@ -1265,9 +1337,9 @@
pendingOptions.getStartY()+pendingOptions.getHeight()));
}
break;
- case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
- case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
- boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
+ case ANIM_THUMBNAIL_SCALE_UP:
+ case ANIM_THUMBNAIL_SCALE_DOWN:
+ boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
service.mWindowManager.overridePendingAppTransitionThumb(
pendingOptions.getThumbnail(),
pendingOptions.getStartX(), pendingOptions.getStartY(),
@@ -1282,10 +1354,10 @@
+ pendingOptions.getThumbnail().getHeight()));
}
break;
- case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
- case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
- if (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
+ if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
&& specs != null) {
service.mWindowManager.overridePendingAppTransitionMultiThumb(
specs, pendingOptions.getOnAnimationStartListener(),
@@ -1296,7 +1368,7 @@
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getWidth(), pendingOptions.getHeight(),
pendingOptions.getOnAnimationStartListener(),
- (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
+ (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
if (intent.getSourceBounds() == null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
@@ -1478,7 +1550,7 @@
void makeVisibleIfNeeded(ActivityRecord starting) {
// This activity is not currently visible, but is running. Tell it to become visible.
- if (state == ActivityState.RESUMED || this == starting) {
+ if (state == RESUMED || this == starting) {
if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
"Not making visible, r=" + this + " state=" + state + " starting=" + starting);
return;
@@ -1515,7 +1587,7 @@
}
} catch(RemoteException e) {
}
- return state == ActivityState.RESUMED;
+ return state == RESUMED;
}
static void activityResumedLocked(IBinder token) {
@@ -1586,9 +1658,9 @@
final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
CharSequence description) {
final ActivityStack stack = getStack();
- if (state != ActivityState.STOPPING) {
+ if (state != STOPPING) {
Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
- stack.mHandler.removeMessages(ActivityStack.STOP_TIMEOUT_MSG, this);
+ stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
return;
}
if (newPersistentState != null) {
@@ -1607,9 +1679,9 @@
}
if (!stopped) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
- stack.mHandler.removeMessages(ActivityStack.STOP_TIMEOUT_MSG, this);
+ stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
stopped = true;
- state = ActivityState.STOPPED;
+ state = STOPPED;
mWindowContainerController.notifyAppStopped();
@@ -1630,7 +1702,7 @@
}
void startLaunchTickingLocked() {
- if (ActivityManagerService.IS_USER_BUILD) {
+ if (IS_USER_BUILD) {
return;
}
if (launchTickTime == 0) {
@@ -1649,9 +1721,9 @@
return false;
}
- Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
- stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
- stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
+ Message msg = stack.mHandler.obtainMessage(LAUNCH_TICK_MSG, this);
+ stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
+ stack.mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
return true;
}
@@ -1659,7 +1731,7 @@
launchTickTime = 0;
final ActivityStack stack = getStack();
if (stack != null) {
- stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+ stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
}
}
@@ -1697,8 +1769,8 @@
final long totalTime = stack.mFullyDrawnStartTime != 0
? (curTime - stack.mFullyDrawnStartTime) : thisTime;
if (SHOW_ACTIVITY_START_TIME) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
- EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
+ Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
+ EventLog.writeEvent(AM_ACTIVITY_FULLY_DRAWN_TIME,
userId, System.identityHashCode(this), shortComponentName,
thisTime, totalTime);
StringBuilder sb = service.mStringBuilder;
@@ -1731,8 +1803,8 @@
final long totalTime = stack.mLaunchStartTime != 0
? (curTime - stack.mLaunchStartTime) : thisTime;
if (SHOW_ACTIVITY_START_TIME) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
- EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
+ Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
+ EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
userId, System.identityHashCode(this), shortComponentName,
thisTime, totalTime);
StringBuilder sb = service.mStringBuilder;
@@ -1869,8 +1941,8 @@
* currently pausing, or is resumed.
*/
public boolean isInterestingToUserLocked() {
- return visible || nowVisible || state == ActivityState.PAUSING ||
- state == ActivityState.RESUMED;
+ return visible || nowVisible || state == PAUSING ||
+ state == RESUMED;
}
void setSleeping(boolean _sleeping) {
@@ -1932,8 +2004,8 @@
}
final boolean isDestroyable() {
- if (finishing || app == null || state == ActivityState.DESTROYING
- || state == ActivityState.DESTROYED) {
+ if (finishing || app == null || state == DESTROYING
+ || state == DESTROYED) {
// This would be redundant.
return false;
}
@@ -1952,7 +2024,7 @@
private static String createImageFilename(long createTime, int taskId) {
return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
- TaskPersister.IMAGE_EXTENSION;
+ IMAGE_EXTENSION;
}
void setTaskDescription(TaskDescription _taskDescription) {
@@ -1994,7 +2066,7 @@
}
void removeOrphanedStartingWindow(boolean behindFullscreenActivity) {
- if (state == ActivityState.INITIALIZING
+ if (state == INITIALIZING
&& mStartingWindowState == STARTING_WINDOW_SHOWN
&& behindFullscreenActivity) {
if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
@@ -2080,23 +2152,31 @@
return true;
}
- /** Computes the override configuration for this activity */
+ /**
+ * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}.
+ */
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void computeBounds(Rect outBounds) {
outBounds.setEmpty();
final float maxAspectRatio = info.maxAspectRatio;
final ActivityStack stack = getStack();
- if ((task != null && !task.mFullscreen) || maxAspectRatio == 0 || stack == null) {
+ if (task == null || stack == null || !task.mFullscreen || maxAspectRatio == 0) {
// We don't set override configuration if that activity task isn't fullscreen. I.e. the
// activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
- // the activity.
+ // the activity. This is indicated by an empty {@link outBounds}.
return;
}
- stack.getDisplaySize(mTmpPoint);
- int maxActivityWidth = mTmpPoint.x;
- int maxActivityHeight = mTmpPoint.y;
- if (mTmpPoint.x < mTmpPoint.y) {
+ // We must base this on the parent configuration, because we set our override
+ // configuration's appBounds based on the result of this method. If we used our own
+ // configuration, it would be influenced by past invocations.
+ final Configuration configuration = getParent().getConfiguration();
+ final int containingAppWidth = configuration.appBounds.width();
+ final int containingAppHeight = configuration.appBounds.height();
+ int maxActivityWidth = containingAppWidth;
+ int maxActivityHeight = containingAppHeight;
+
+ if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use that to figure-out what the max. height should
// be given the aspect ratio.
maxActivityHeight = (int) ((maxActivityWidth * maxAspectRatio) + 0.5f);
@@ -2106,8 +2186,14 @@
maxActivityWidth = (int) ((maxActivityHeight * maxAspectRatio) + 0.5f);
}
- if (mTmpPoint.x <= maxActivityWidth && mTmpPoint.y <= maxActivityHeight) {
+ if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
// The display matches or is less than the activity aspect ratio, so nothing else to do.
+ // Return the existing bounds. If this method is running for the first time,
+ // {@link mBounds} will be empty (representing no override). If the method has run
+ // before, then effect of {@link mBounds} will already have been applied to the
+ // value returned from {@link getConfiguration}. Refer to
+ // {@link TaskRecord#computeOverrideConfiguration}.
+ outBounds.set(mBounds);
return;
}
@@ -2167,6 +2253,9 @@
// to decide whether to relaunch an activity or just report a configuration change.
final int changes = getConfigurationChanges(mTmpConfig1);
+ // Preserve configuration used to generate this set of configuration changes.
+ mTmpConfig3.setTo(mTmpConfig1);
+
// Update last reported values.
final Configuration newGlobalConfig = service.getGlobalConfiguration();
final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
@@ -2210,8 +2299,7 @@
+ ", newGlobalConfig=" + newGlobalConfig
+ ", newMergedOverrideConfig=" + newMergedOverrideConfig);
- if (shouldRelaunchLocked(changes, newGlobalConfig, newMergedOverrideConfig)
- || forceNewConfig) {
+ if (shouldRelaunchLocked(changes, mTmpConfig3) || forceNewConfig) {
// Aha, the activity isn't handling the change, so DIE DIE DIE.
configChangeFlags |= changes;
startFreezingScreenLocked(app, globalChanges);
@@ -2221,7 +2309,7 @@
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Config is destroying non-running " + this);
stack.destroyActivityLocked(this, true, "config");
- } else if (state == ActivityState.PAUSING) {
+ } else if (state == PAUSING) {
// A little annoying: we are waiting for this activity to finish pausing. Let's not
// do anything now, but just flag that it needs to be restarted when done pausing.
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -2229,7 +2317,7 @@
deferRelaunchUntilPaused = true;
preserveWindowOnDeferredRelaunch = preserveWindow;
return true;
- } else if (state == ActivityState.RESUMED) {
+ } else if (state == RESUMED) {
// Try to optimize this case: the configuration is changing and we need to restart
// the top, resumed activity. Instead of doing the normal handshaking, just say
// "restart!".
@@ -2269,10 +2357,14 @@
/**
* When assessing a configuration change, decide if the changes flags and the new configurations
* should cause the Activity to relaunch.
+ *
+ * @param changes the changes due to the given configuration.
+ * @param changesConfig the configuration that was used to calculate the given changes via a
+ * call to getConfigurationChanges.
*/
- private boolean shouldRelaunchLocked(int changes, Configuration newGlobalConfig,
- Configuration newTaskMergedOverrideConfig) {
+ private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
int configChanged = info.getRealConfigChanged();
+ boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
// Override for apps targeting pre-O sdks
// If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
@@ -2280,13 +2372,23 @@
// For O and later, apps will be required to add configChanges="uimode" to their manifest.
if (appInfo.targetSdkVersion < O
&& requestedVrComponent != null
- && (isInVrUiMode(newGlobalConfig) || isInVrUiMode(newTaskMergedOverrideConfig))) {
+ && onlyVrUiModeChanged) {
configChanged |= CONFIG_UI_MODE;
}
return (changes&(~configChanged)) != 0;
}
+ /**
+ * Returns true if the configuration change is solely due to the UI mode switching into or out
+ * of UI_MODE_TYPE_VR_HEADSET.
+ */
+ private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
+ final Configuration currentConfig = getConfiguration();
+ return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
+ != isInVrUiMode(lastReportedConfig));
+ }
+
private int getConfigurationChanges(Configuration lastReportedConfig) {
// Determine what has changed. May be nothing, if this is a config that has come back from
// the app after going idle. In that case we just want to leave the official config object
@@ -2335,8 +2437,8 @@
"Relaunching: " + this + " with results=" + pendingResults
+ " newIntents=" + pendingNewIntents + " andResume=" + andResume
+ " preserveWindow=" + preserveWindow);
- EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
- : EventLogTags.AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
+ EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
+ : AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
task.taskId, shortComponentName);
startFreezingScreenLocked(app, 0);
@@ -2369,8 +2471,8 @@
service.showUnsupportedZoomDialogIfNeededLocked(this);
service.showAskCompatModeDialogLocked(this);
} else {
- service.mHandler.removeMessages(ActivityStack.PAUSE_TIMEOUT_MSG, this);
- state = ActivityState.PAUSED;
+ service.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
+ state = PAUSED;
// if the app is relaunched when it's stopped, and we're not resuming,
// put it back into stopped state.
if (stopped) {
@@ -2434,7 +2536,7 @@
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
final String attrName = in.getAttributeName(attrNdx);
final String attrValue = in.getAttributeValue(attrNdx);
- if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
+ if (DEBUG) Slog.d(TaskPersister.TAG,
"ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
if (ATTR_ID.equals(attrName)) {
createTime = Long.parseLong(attrValue);
@@ -2448,7 +2550,7 @@
componentSpecified = Boolean.parseBoolean(attrValue);
} else if (ATTR_USERID.equals(attrName)) {
userId = Integer.parseInt(attrValue);
- } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
+ } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
taskDescription.restoreFromXml(attrName, attrValue);
} else {
Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
@@ -2456,19 +2558,19 @@
}
int event;
- while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
- (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
- if (event == XmlPullParser.START_TAG) {
+ while (((event = in.next()) != END_DOCUMENT) &&
+ (event != END_TAG || in.getDepth() >= outerDepth)) {
+ if (event == START_TAG) {
final String name = in.getName();
- if (TaskPersister.DEBUG)
+ if (DEBUG)
Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
if (TAG_INTENT.equals(name)) {
intent = Intent.restoreFromXml(in);
- if (TaskPersister.DEBUG)
+ if (DEBUG)
Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
} else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
persistentState = PersistableBundle.restoreFromXml(in);
- if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
+ if (DEBUG) Slog.d(TaskPersister.TAG,
"ActivityRecord: persistentState=" + persistentState);
} else {
Slog.w(TAG, "restoreActivity: unexpected name=" + name);
@@ -2512,7 +2614,7 @@
}
private static boolean isInVrUiMode(Configuration config) {
- return (config.uiMode & Configuration.UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
+ return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
}
int getUid() {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 498de63..3d50b7c 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -342,7 +342,7 @@
private final Rect mTmpRect2 = new Rect();
/** Run all ActivityStacks through this */
- private final ActivityStackSupervisor mStackSupervisor;
+ protected final ActivityStackSupervisor mStackSupervisor;
private final LaunchingTaskPositioner mTaskPositioner;
@@ -2795,7 +2795,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;
@@ -4403,7 +4404,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;
}
@@ -5074,7 +5075,7 @@
}
void addTask(final TaskRecord task, final boolean toTop, String reason) {
- addTask(task, toTop ? MAX_VALUE : 0, reason);
+ addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
if (toTop) {
// TODO: figure-out a way to remove this call.
mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
@@ -5084,7 +5085,8 @@
// TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
// with the fall-out...
- void addTask(final TaskRecord task, int position, String reason) {
+ void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
+ String reason) {
// TODO: Is this remove really needed? Need to look into the call path for the other addTask
mTaskHistory.remove(task);
position = getAdjustedPositionForTask(task, position, null /* starting */);
@@ -5100,7 +5102,7 @@
updateTaskMovement(task, toTop);
- postAddTask(task, prevStack);
+ postAddTask(task, prevStack, schedulePictureInPictureModeChange);
}
void positionChildAt(TaskRecord task, int index) {
@@ -5116,7 +5118,7 @@
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
insertTaskAtPosition(task, index);
task.setStack(this);
- postAddTask(task, null /* prevStack */);
+ postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
if (wasResumed) {
if (mResumedActivity != null) {
@@ -5142,9 +5144,15 @@
return prevStack;
}
- private void postAddTask(TaskRecord task, ActivityStack prevStack) {
- if (prevStack != null) {
- mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
+ /**
+ * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
+ * change. Callers may set this to false if they are explicitly scheduling PiP mode
+ * changes themselves, like during the PiP animation
+ */
+ private void postAddTask(TaskRecord task, ActivityStack prevStack,
+ boolean schedulePictureInPictureModeChange) {
+ if (schedulePictureInPictureModeChange && prevStack != null) {
+ mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
} else if (task.voiceSession != null) {
try {
task.voiceSession.taskStarted(task.intent, task.taskId);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c65ca79..f16849d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -371,6 +371,10 @@
* application */
final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();
+ /** The target stack bounds for the picture-in-picture mode changed that we need to report to
+ * the application */
+ Rect mPipModeChangedTargetStackBounds;
+
/** Used on user changes */
final ArrayList<UserState> mStartingUsers = new ArrayList<>();
@@ -2334,6 +2338,9 @@
ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
final boolean isFullscreenStackVisible = fullscreenStack != null &&
fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
+ // If we are moving from the pinned stack, then the animation takes care of updating
+ // the picture-in-picture mode.
+ final boolean schedulePictureInPictureModeChange = (fromStackId != PINNED_STACK_ID);
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
final int size = tasks.size();
if (onTop) {
@@ -2352,6 +2359,7 @@
// Defer resume until all the tasks have been moved to the fullscreen stack
task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, isTopTask /* animate */, DEFER_RESUME,
+ schedulePictureInPictureModeChange,
"moveTasksToFullscreenStack - onTop");
}
} else {
@@ -2361,8 +2369,9 @@
? Math.max(fullscreenStack.getAllTasks().size() - 1, 0) : 0;
// Defer resume until all the tasks have been moved to the fullscreen stack
task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, position,
- REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
- DEFER_RESUME, "moveTasksToFullscreenStack - NOT_onTop");
+ REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME,
+ schedulePictureInPictureModeChange,
+ "moveTasksToFullscreenStack - NOT_onTop");
}
}
@@ -2506,9 +2515,8 @@
fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
for (int i = 0; i < tasks.size(); i++) {
// Insert the task either at the top of the fullscreen stack if it is hidden,
- // or just under the top task if it is currently visible
- final int insertPosition = isFullscreenStackVisible
- ? Math.max(0, fullscreenStack.getChildCount() - 1)
+ // or to the bottom if it is currently visible
+ final int insertPosition = isFullscreenStackVisible ? 0
: fullscreenStack.getChildCount();
final TaskRecord task = tasks.get(i);
// Defer resume until we remove all the tasks
@@ -2856,9 +2864,9 @@
// was launched from home so home should be visible behind it.
moveHomeStackToFront(reason);
}
- // Defer resume until below
+ // Defer resume until below, and do not schedule PiP changes until we animate below
task.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, reason);
+ DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
} else {
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
@@ -2873,9 +2881,9 @@
r.mActivityType);
r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
- // Defer resume until below
+ // Defer resume until below, and do not schedule PiP changes until we animate below
newTask.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, reason);
+ DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
}
// Reset the state that indicates it can enter PiP while pausing after we've moved it
@@ -4109,7 +4117,7 @@
mActivityMetricsLogger.logWindowState();
}
- void scheduleReportMultiWindowModeChanged(TaskRecord task) {
+ void scheduleUpdateMultiWindowMode(TaskRecord task) {
for (int i = task.mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = task.mActivities.get(i);
if (r.app != null && r.app.thread != null) {
@@ -4122,22 +4130,39 @@
}
}
- void scheduleReportPictureInPictureModeChangedIfNeeded(TaskRecord task, ActivityStack prevStack) {
+ void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, ActivityStack prevStack) {
final ActivityStack stack = task.getStack();
if (prevStack == null || prevStack == stack
|| (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
return;
}
- for (int i = task.mActivities.size() - 1; i >= 0; i--) {
- final ActivityRecord r = task.mActivities.get(i);
- if (r.app != null && r.app.thread != null) {
- mPipModeChangedActivities.add(r);
- }
- }
+ scheduleUpdatePictureInPictureModeIfNeeded(task, stack.mBounds, false /* immediate */);
+ }
- if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
- mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
+ void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds,
+ boolean immediate) {
+
+ if (immediate) {
+ mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG);
+ for (int i = task.mActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord r = task.mActivities.get(i);
+ if (r.app != null && r.app.thread != null) {
+ r.updatePictureInPictureMode(targetStackBounds);
+ }
+ }
+ } else {
+ for (int i = task.mActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord r = task.mActivities.get(i);
+ if (r.app != null && r.app.thread != null) {
+ mPipModeChangedActivities.add(r);
+ }
+ }
+ mPipModeChangedTargetStackBounds = targetStackBounds;
+
+ if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
+ mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
+ }
}
}
@@ -4165,7 +4190,7 @@
synchronized (mService) {
for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i);
- r.scheduleMultiWindowModeChanged();
+ r.updateMultiWindowMode();
}
}
} break;
@@ -4173,7 +4198,7 @@
synchronized (mService) {
for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mPipModeChangedActivities.remove(i);
- r.schedulePictureInPictureModeChanged();
+ r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds);
}
}
} break;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d3935d1..e5b2eca 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -59,6 +59,7 @@
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.PowerProfile;
+import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.power.BatterySaverPolicy.ServiceType;
@@ -1188,13 +1189,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump BatteryStats from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
int flags = 0;
boolean useCheckinFormat = false;
diff --git a/services/core/java/com/android/server/am/PersistentConnection.java b/services/core/java/com/android/server/am/PersistentConnection.java
new file mode 100644
index 0000000..c34c097
--- /dev/null
+++ b/services/core/java/com/android/server/am/PersistentConnection.java
@@ -0,0 +1,168 @@
+/*
+ * 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 android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+
+/**
+ * Connects to a given service component on a given user.
+ *
+ * - Call {@link #connect()} to create a connection.
+ * - Call {@link #disconnect()} to disconnect. Make sure to disconnect when the user stops.
+ *
+ * Add onConnected/onDisconnected callbacks as needed.
+ */
+public abstract class PersistentConnection<T> {
+ private final Object mLock = new Object();
+
+ private final String mTag;
+ private final Context mContext;
+ private final Handler mHandler;
+ private final int mUserId;
+ private final ComponentName mComponentName;
+
+ @GuardedBy("mLock")
+ private boolean mStarted;
+
+ @GuardedBy("mLock")
+ private boolean mIsConnected;
+
+ @GuardedBy("mLock")
+ private T mService;
+
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mLock) {
+ Slog.i(mTag, "Connected: " + mComponentName.flattenToShortString()
+ + " u" + mUserId);
+
+ mIsConnected = true;
+ mService = asInterface(service);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ synchronized (mLock) {
+ Slog.i(mTag, "Disconnected: " + mComponentName.flattenToShortString()
+ + " u" + mUserId);
+
+ cleanUpConnectionLocked();
+ }
+ }
+ };
+
+ public PersistentConnection(@NonNull String tag, @NonNull Context context,
+ @NonNull Handler handler, int userId, @NonNull ComponentName componentName) {
+ mTag = tag;
+ mContext = context;
+ mHandler = handler;
+ mUserId = userId;
+ mComponentName = componentName;
+ }
+
+ public final ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ /**
+ * @return whether connected.
+ */
+ public final boolean isConnected() {
+ synchronized (mLock) {
+ return mIsConnected;
+ }
+ }
+
+ /**
+ * @return the service binder interface.
+ */
+ public final T getServiceBinder() {
+ synchronized (mLock) {
+ return mService;
+ }
+ }
+
+ /**
+ * Connects to the service.
+ */
+ public final void connect() {
+ synchronized (mLock) {
+ if (mStarted) {
+ return;
+ }
+ mStarted = true;
+
+ final Intent service = new Intent().setComponent(mComponentName);
+
+ final boolean success = mContext.bindServiceAsUser(service, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ mHandler, UserHandle.of(mUserId));
+
+ if (!success) {
+ Slog.e(mTag, "Binding: " + service.getComponent() + " u" + mUserId
+ + " failed.");
+ }
+ }
+ }
+
+ private void cleanUpConnectionLocked() {
+ mIsConnected = false;
+ mService = null;
+ }
+
+ /**
+ * Disconnect from the service.
+ */
+ public final void disconnect() {
+ synchronized (mLock) {
+ if (!mStarted) {
+ return;
+ }
+ Slog.i(mTag, "Stopping: " + mComponentName.flattenToShortString() + " u" + mUserId);
+ mStarted = false;
+ mContext.unbindService(mServiceConnection);
+
+ cleanUpConnectionLocked();
+ }
+ }
+
+ /** Must be implemented by a subclass to convert an {@link IBinder} to a stub. */
+ protected abstract T asInterface(IBinder binder);
+
+ public void dump(String prefix, PrintWriter pw) {
+ synchronized (mLock) {
+ pw.print(prefix);
+ pw.print(mComponentName.flattenToShortString());
+ pw.print(mStarted ? " [started]" : " [not started]");
+ pw.print(mIsConnected ? " [connected]" : " [not connected]");
+ pw.println();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 32d3082..394e902 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -23,6 +23,7 @@
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.StackWindowController;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -57,4 +58,18 @@
boolean isBoundsAnimatingToFullscreen() {
return getWindowContainerController().isBoundsAnimatingToFullscreen();
}
+
+ @Override
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ // It is guaranteed that the activities requiring the update will be in the pinned stack at
+ // this point (either reparented before the animation into PiP, or before reparenting after
+ // the animation out of PiP)
+ synchronized(this) {
+ ArrayList<TaskRecord> tasks = getAllTasks();
+ for (int i = 0; i < tasks.size(); i++ ) {
+ mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(tasks.get(i),
+ targetStackBounds, true /* immediate */);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 40effff..0dc6788 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -350,58 +350,58 @@
String procState;
switch (curProcState) {
case ActivityManager.PROCESS_STATE_PERSISTENT:
- procState = "P ";
+ procState = "PER ";
break;
case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
- procState = "PU";
+ procState = "PERU";
break;
case ActivityManager.PROCESS_STATE_TOP:
- procState = "T ";
+ procState = "TOP";
break;
case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
- procState = "SB";
+ procState = "BFGS";
break;
case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
- procState = "SF";
+ procState = "FGS ";
break;
case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
- procState = "TS";
+ procState = "TPSL";
break;
case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
- procState = "IF";
+ procState = "IMPF";
break;
case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
- procState = "IB";
+ procState = "IMPB";
break;
case ActivityManager.PROCESS_STATE_BACKUP:
- procState = "BU";
+ procState = "BKUP";
break;
case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
- procState = "HW";
+ procState = "HVY ";
break;
case ActivityManager.PROCESS_STATE_SERVICE:
- procState = "S ";
+ procState = "SVC ";
break;
case ActivityManager.PROCESS_STATE_RECEIVER:
- procState = "R ";
+ procState = "RCVR";
break;
case ActivityManager.PROCESS_STATE_HOME:
- procState = "HO";
+ procState = "HOME";
break;
case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
- procState = "LA";
+ procState = "LAST";
break;
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
- procState = "CA";
+ procState = "CAC ";
break;
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
- procState = "Ca";
+ procState = "CACC";
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
- procState = "CE";
+ procState = "CEM ";
break;
case ActivityManager.PROCESS_STATE_NONEXISTENT:
- procState = "N ";
+ procState = "NONE";
break;
default:
procState = "??";
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 2d27204..3c5c5fd 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -287,7 +287,9 @@
pw.print(" setSchedGroup="); pw.print(setSchedGroup);
pw.print(" systemNoUi="); pw.print(systemNoUi);
pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
- pw.print(prefix); pw.print("vrThreadTid="); pw.print(vrThreadTid);
+ if (vrThreadTid != 0) {
+ pw.print(prefix); pw.print("vrThreadTid="); pw.println(vrThreadTid);
+ }
pw.print(prefix); pw.print("curProcState="); pw.print(curProcState);
pw.print(" repProcState="); pw.print(repProcState);
pw.print(" pssProcState="); pw.print(pssProcState);
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index d210ed7..deb3b28 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -616,13 +616,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mAm.checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump procstats from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
+ if (!com.android.internal.util.DumpUtils.checkDumpAndUsageStatsPermission(mAm.mContext,
+ TAG, pw)) return;
long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 44ebf50..b57f6c3 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -124,6 +124,7 @@
final ServiceRecord sr;
final boolean taskRemoved;
final int id;
+ final int callingId;
final Intent intent;
final ActivityManagerService.NeededUriGrants neededGrants;
long deliveredTime;
@@ -134,12 +135,13 @@
String stringName; // caching of toString
StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent,
- ActivityManagerService.NeededUriGrants _neededGrants) {
+ ActivityManagerService.NeededUriGrants _neededGrants, int _callingId) {
sr = _sr;
taskRemoved = _taskRemoved;
id = _id;
intent = _intent;
neededGrants = _neededGrants;
+ callingId = _callingId;
}
UriPermissionOwner getUriPermissionsLocked() {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ce32f84..27a2461 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -568,7 +568,27 @@
boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
boolean animate, boolean deferResume, String reason) {
return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
- deferResume, reason);
+ deferResume, true /* schedulePictureInPictureModeChange */, reason);
+ }
+
+ /**
+ * Convenience method to reparent a task to the top or bottom position of the stack, with
+ * an option to skip scheduling the picture-in-picture mode change.
+ */
+ boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
+ boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
+ String reason) {
+ return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
+ deferResume, schedulePictureInPictureModeChange, reason);
+ }
+
+ /**
+ * Convenience method to reparent a task to a specific position of the stack.
+ */
+ boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
+ boolean animate, boolean deferResume, String reason) {
+ return reparent(preferredStackId, position, moveStackMode, animate, deferResume,
+ true /* schedulePictureInPictureModeChange */, reason);
}
/**
@@ -577,16 +597,20 @@
* @param preferredStackId the stack id of the target stack to move this task
* @param position the position to place this task in the new stack
* @param animate whether or not we should wait for the new window created as a part of the
- * reparenting to be drawn and animated in
+ * reparenting to be drawn and animated in
* @param moveStackMode whether or not to move the stack to the front always, only if it was
- * previously focused & in front, or never
+ * previously focused & in front, or never
* @param deferResume whether or not to update the visibility of other tasks and stacks that may
- * have changed as a result of this reparenting
+ * have changed as a result of this reparenting
+ * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
+ * change. Callers may set this to false if they are explicitly scheduling PiP mode
+ * changes themselves, like during the PiP animation
* @param reason the caller of this reparenting
- * @return
+ * @return whether the task was reparented
*/
boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
- boolean animate, boolean deferResume, String reason) {
+ boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
+ String reason) {
final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
final WindowManagerService windowManager = mService.mWindowManager;
final ActivityStack sourceStack = getStack();
@@ -649,11 +673,12 @@
// Move the task
sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
- toStack.addTask(this, position, reason);
+ toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
- // TODO: Ensure that this is actually necessary here
- // Notify of picture-in-picture mode changes
- supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, sourceStack);
+ if (schedulePictureInPictureModeChange) {
+ // Notify of picture-in-picture mode changes
+ supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
+ }
// TODO: Ensure that this is actually necessary here
// Notify the voice session if required
@@ -1979,6 +2004,25 @@
}
/**
+ * @return a new Configuration for this Task, given the provided {@param bounds} and
+ * {@param insetBounds}.
+ */
+ Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
+ // Compute a new override configuration for the given bounds, if fullscreen bounds
+ // (bounds == null), then leave the override config unset
+ final Configuration newOverrideConfig = new Configuration();
+ if (bounds != null) {
+ newOverrideConfig.setTo(getOverrideConfiguration());
+ mTmpRect.set(bounds);
+ adjustForMinimalTaskDimensions(mTmpRect);
+ computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
+ mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
+ }
+
+ return newOverrideConfig;
+ }
+
+ /**
* Update task's override configuration based on the bounds.
* @param bounds The bounds of the task.
* @return True if the override configuration was updated.
@@ -2027,7 +2071,7 @@
onOverrideConfigurationChanged(newConfig);
if (mFullscreen != oldFullscreen) {
- mService.mStackSupervisor.scheduleReportMultiWindowModeChanged(this);
+ mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
}
return !mTmpConfig.equals(newConfig);
@@ -2044,6 +2088,7 @@
config.unset();
final Configuration parentConfig = getParent().getConfiguration();
+
final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
if (mStack != null) {
@@ -2052,11 +2097,7 @@
mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
config, parentConfig);
} else {
- // No stack, give some default values
- config.smallestScreenWidthDp =
- mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
- config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
- Slog.wtf(TAG, "Expected stack when calculating override config");
+ throw new IllegalArgumentException("Expected stack when calculating override config");
}
config.orientation = (config.screenWidthDp <= config.screenHeightDp)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 9a38f4d..c11f531 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -115,6 +115,7 @@
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityManager;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.XmlUtils;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
@@ -6119,7 +6120,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
mMediaFocusControl.dump(pw);
dumpStreamStates(pw);
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 83751a9..4315aaa 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -31,7 +31,7 @@
import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -40,11 +40,12 @@
public class NetworkNotificationManager {
+
public static enum NotificationType {
- LOST_INTERNET(MetricsEvent.NOTIFICATION_NETWORK_LOST_INTERNET),
- NETWORK_SWITCH(MetricsEvent.NOTIFICATION_NETWORK_SWITCH),
- NO_INTERNET(MetricsEvent.NOTIFICATION_NETWORK_NO_INTERNET),
- SIGN_IN(MetricsEvent.NOTIFICATION_NETWORK_SIGN_IN);
+ LOST_INTERNET(SystemMessage.NOTE_NETWORK_LOST_INTERNET),
+ NETWORK_SWITCH(SystemMessage.NOTE_NETWORK_SWITCH),
+ NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET),
+ SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN);
public final int eventId;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 07ab067..0e593bd 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -70,6 +70,7 @@
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.Protocol;
@@ -1585,13 +1586,7 @@
// Binder.java closes the resource for us.
@SuppressWarnings("resource")
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
- "from from pid=" + Binder.getCallingPid() + ", uid=" +
- Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("Tethering:");
pw.increaseIndent();
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index f47a9079..13054a6 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -60,6 +60,7 @@
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -162,9 +163,7 @@
@Override
protected synchronized void dump(FileDescriptor fd, PrintWriter pw_, String[] args) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
- "caller doesn't have the DUMP permission");
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw_)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, " ");
// This makes it so that future permission checks will be in the context of this
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index fd89b97..ddd918f 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -23,6 +23,7 @@
import static android.hardware.display.DisplayManager
.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import android.Manifest;
@@ -338,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) {
@@ -1538,13 +1551,7 @@
@Override // Binder call
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (mContext == null
- || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump DisplayManager from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
final long token = Binder.clearCallingIdentity();
try {
@@ -1668,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/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 1991c00..313abab 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -479,14 +479,7 @@
private final class BinderService extends IDreamManager.Stub {
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump DreamManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
final long ident = Binder.clearCallingIdentity();
try {
dumpInternal(pw);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7d97ce4..2b85570 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -56,6 +56,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.DumpUtils;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
@@ -1071,13 +1072,7 @@
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump Fingerprint from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
final long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 6864e1e..807b1b1 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -68,6 +68,7 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -1677,7 +1678,7 @@
@Override
protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
- getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 65a4604..aafc9a8 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -27,6 +27,7 @@
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.SomeArgs;
import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.DisplayThread;
@@ -1747,13 +1748,7 @@
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump InputManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("INPUT MANAGER (dumpsys input)\n");
String dumpStr = nativeDump(mPtr);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 2de9aae..7c231ff 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -72,6 +72,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.job.JobStore.JobStatusFunctor;
@@ -1790,7 +1791,7 @@
*/
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
long identityToken = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 0a15db6..5e9f355 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -31,6 +31,8 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.util.DumpUtils;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
@@ -242,11 +244,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump contexthub service");
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("Dumping ContextHub Service");
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index f91ea8c..7b0e51e 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -16,6 +16,7 @@
package com.android.server.media;
+import com.android.internal.util.DumpUtils;
import com.android.server.Watchdog;
import android.Manifest;
@@ -258,13 +259,7 @@
// Binder call
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump MediaRouterService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)");
pw.println();
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 4bf9d8f..64ab848 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -71,6 +71,7 @@
import android.view.KeyEvent;
import android.view.ViewConfiguration;
+import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
@@ -1283,13 +1284,7 @@
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump MediaSessionService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
pw.println();
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 3ea4f2c..9d92cbc 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -39,6 +39,7 @@
import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
import java.io.FileDescriptor;
@@ -314,14 +315,7 @@
@Override // Binder call
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (mContext == null
- || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump MediaProjectionManager from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
final long token = Binder.clearCallingIdentity();
try {
MediaProjectionManagerService.this.dump(pw);
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 f180c50..02e106e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -178,9 +178,11 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.DeviceIdleController;
@@ -212,6 +214,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Calendar;
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -245,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;
@@ -268,11 +271,11 @@
ActivityManager.isLowRamDeviceStatic() ? 50 : 200;
@VisibleForTesting
- public static final int TYPE_WARNING = 0x1;
+ public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING;
@VisibleForTesting
- public static final int TYPE_LIMIT = 0x2;
+ public static final int TYPE_LIMIT = SystemMessage.NOTE_NET_LIMIT;
@VisibleForTesting
- public static final int TYPE_LIMIT_SNOOZED = 0x3;
+ public static final int TYPE_LIMIT_SNOOZED = SystemMessage.NOTE_NET_LIMIT_SNOOZED;
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
@@ -419,15 +422,12 @@
/** Set of currently active {@link Notification} tags. */
@GuardedBy("mNetworkPoliciesSecondLock")
- private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
+ private final ArraySet<NotificationId> mActiveNotifs = new ArraySet<>();
/** Foreground at UID granularity. */
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidState = new SparseIntArray();
- /** Higher priority listener before general event dispatch */
- private INetworkPolicyListener mConnectivityListener;
-
private final RemoteCallbackList<INetworkPolicyListener>
mListeners = new RemoteCallbackList<>();
@@ -1054,7 +1054,7 @@
if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
// keep track of previously active notifications
- final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
+ final ArraySet<NotificationId> beforeNotifs = new ArraySet<NotificationId>(mActiveNotifs);
mActiveNotifs.clear();
// TODO: when switching to kernel notifications, compute next future
@@ -1091,9 +1091,9 @@
// cancel stale notifications that we didn't renew above
for (int i = beforeNotifs.size()-1; i >= 0; i--) {
- final String tag = beforeNotifs.valueAt(i);
- if (!mActiveNotifs.contains(tag)) {
- cancelNotification(tag);
+ final NotificationId notificationId = beforeNotifs.valueAt(i);
+ if (!mActiveNotifs.contains(notificationId)) {
+ cancelNotification(notificationId);
}
}
}
@@ -1141,19 +1141,11 @@
}
/**
- * Build unique tag that identifies an active {@link NetworkPolicy}
- * notification of a specific type, like {@link #TYPE_LIMIT}.
- */
- private String buildNotificationTag(NetworkPolicy policy, int type) {
- return TAG + ":" + policy.template.hashCode() + ":" + type;
- }
-
- /**
* Show notification for combined {@link NetworkPolicy} and specific type,
* like {@link #TYPE_LIMIT}. Okay to call multiple times.
*/
private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
- final String tag = buildNotificationTag(policy, type);
+ final NotificationId notificationId = new NotificationId(policy, type);
final Notification.Builder builder =
new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
builder.setOnlyAlertOnce(true);
@@ -1261,25 +1253,26 @@
try {
final String packageName = mContext.getPackageName();
final int[] idReceived = new int[1];
- if(!TextUtils.isEmpty(body)) {
+ if (!TextUtils.isEmpty(body)) {
builder.setStyle(new Notification.BigTextStyle()
.bigText(body));
}
mNotifManager.enqueueNotificationWithTag(
- packageName, packageName, tag, 0x0, builder.build(), idReceived,
- UserHandle.USER_ALL);
- mActiveNotifs.add(tag);
+ packageName, packageName, notificationId.getTag(), notificationId.getId(),
+ builder.build(), idReceived, UserHandle.USER_ALL);
+ mActiveNotifs.add(notificationId);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
}
- private void cancelNotification(String tag) {
+ private void cancelNotification(NotificationId notificationId) {
// TODO: move to NotificationManager once we can mock it
try {
final String packageName = mContext.getPackageName();
mNotifManager.cancelNotificationWithTag(
- packageName, tag, 0x0, UserHandle.USER_ALL);
+ packageName, notificationId.getTag(), notificationId.getId(),
+ UserHandle.USER_ALL);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -2241,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);
@@ -2585,7 +2569,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
final IndentingPrintWriter fout = new IndentingPrintWriter(writer, " ");
@@ -3560,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);
@@ -3571,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);
@@ -3602,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);
@@ -3620,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);
@@ -4053,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));
}
/**
@@ -4124,4 +4172,43 @@
return next;
}
}
+
+ private class NotificationId {
+ private final String mTag;
+ private final int mId;
+
+ NotificationId(NetworkPolicy policy, int type) {
+ mTag = buildNotificationTag(policy, type);
+ mId = type;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NotificationId)) return false;
+ NotificationId that = (NotificationId) o;
+ return Objects.equals(mTag, that.mTag);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mTag);
+ }
+
+ /**
+ * Build unique tag that identifies an active {@link NetworkPolicy}
+ * notification of a specific type, like {@link #TYPE_LIMIT}.
+ */
+ private String buildNotificationTag(NetworkPolicy policy, int type) {
+ return TAG + ":" + policy.template.hashCode() + ":" + type;
+ }
+
+ public String getTag() {
+ return mTag;
+ }
+
+ public int getId() {
+ return mId;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 6d666e8..e746355 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -122,6 +122,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.EventLogTags;
@@ -1234,7 +1235,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
- mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
long duration = DateUtils.DAY_IN_MILLIS;
final HashSet<String> argSet = new HashSet<String>();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ede5a5e..44c715b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -144,6 +144,7 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.server.DeviceIdleController;
@@ -2451,14 +2452,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump NotificationManager from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
final DumpFilter filter = DumpFilter.parseFromArguments(args);
if (filter != null && filter.stats) {
dumpJson(pw, filter);
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 73afaa0..65aaee0 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -282,7 +282,7 @@
for (int i = 0; i < size; i++) {
final NotificationChannel notificationChannel = r.channels.valueAt(i);
if (notificationChannel != null &&
- notificationChannel.getId() != NotificationChannel.DEFAULT_CHANNEL_ID) {
+ !notificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
hasCreatedAChannel = true;
break;
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index e1426fd..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;
}
@@ -445,8 +435,8 @@
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
- String packageName, List shortcutIds, ComponentName componentName, Intent intent,
- int flags, UserHandle targetUser) {
+ String packageName, List shortcutIds, ComponentName componentName, int flags,
+ UserHandle targetUser) {
ensureShortcutPermission(callingPackage);
if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
|| !isUserEnabled(targetUser)) {
@@ -457,17 +447,11 @@
"To query by shortcut ID, package name must also be set");
}
- if ((flags & ShortcutQuery.FLAG_MATCH_CHOOSER) == 0
- && intent != null) {
- throw new IllegalArgumentException("Supplied an intent in the query, but did "
- + "not request chooser targets");
- }
-
// TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
return new ParceledListSlice<>((List<ShortcutInfo>)
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
callingPackage, changedSince, packageName, shortcutIds,
- componentName, intent, flags, targetUser.getIdentifier()));
+ componentName, flags, targetUser.getIdentifier()));
}
@Override
@@ -915,7 +899,6 @@
cookie.packageName,
/* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
/* component= */ null,
- /* intent= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
| ShortcutQuery.FLAG_GET_ALL_KINDS
, userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2115f31..d89b12e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -254,6 +254,7 @@
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
@@ -568,7 +569,7 @@
Manifest.permission.RECEIVE_MMS,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.READ_PHONE_NUMBER,
+ Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.ANSWER_PHONE_CALLS);
@@ -1181,7 +1182,6 @@
// Stores a list of users whose package restrictions file needs to be updated
private ArraySet<Integer> mDirtyUsers = new ArraySet<Integer>();
- static final long DEFAULT_CONTAINER_WHITELIST_DURATION = 10 * 60 * 1000;
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
class DefaultContainerConnection implements ServiceConnection {
@@ -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 =
@@ -3036,13 +3040,14 @@
return null;
}
+ final int callingUid = Binder.getCallingUid();
final int resolveFlags =
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,
- resolveFlags, UserHandle.USER_SYSTEM);
+ resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
final int N = resolvers.size();
if (N == 0) {
@@ -4021,12 +4026,12 @@
* action and a {@code android.intent.category.BROWSABLE} category</li>
* </ul>
*/
- int updateFlagsForResolve(int flags, int userId, Intent intent, boolean includeInstantApp) {
+ int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
+ boolean includeInstantApps) {
// Safe mode means we shouldn't match any third-party components
if (mSafeMode) {
flags |= PackageManager.MATCH_SYSTEM_ONLY;
}
- final int callingUid = Binder.getCallingUid();
if (getInstantAppPackageName(callingUid) != null) {
// But, ephemeral apps see both ephemeral and exposed, non-ephemeral components
flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
@@ -4038,7 +4043,7 @@
|| callingUid == Process.SHELL_UID
|| callingUid == 0;
final boolean allowMatchInstant =
- (includeInstantApp
+ (includeInstantApps
&& Intent.ACTION_VIEW.equals(intent.getAction())
&& intent.hasCategory(Intent.CATEGORY_BROWSABLE)
&& hasWebURI(intent))
@@ -5588,22 +5593,23 @@
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
return resolveIntentInternal(
- intent, resolvedType, flags, userId, false /*includeInstantApp*/);
+ intent, resolvedType, flags, userId, false /*includeInstantApps*/);
}
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
- int flags, int userId, boolean includeInstantApp) {
+ int flags, int userId, boolean includeInstantApps) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+ enforceCrossUserPermission(callingUid, userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
- flags, userId, includeInstantApp);
+ flags, userId, includeInstantApps);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
@@ -5623,9 +5629,11 @@
if (!sUserManager.exists(userId)) {
return null;
}
+ final int callingUid = Binder.getCallingUid();
intent = updateIntentForResolve(intent);
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
- final int flags = updateFlagsForResolve(0, userId, intent, false);
+ final int flags = updateFlagsForResolve(
+ 0, userId, intent, callingUid, false /*includeInstantApps*/);
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
userId);
synchronized (mPackages) {
@@ -5914,7 +5922,9 @@
List<ResolveInfo> query, int priority, boolean always,
boolean removeMatches, boolean debug, int userId) {
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(
+ flags, userId, intent, callingUid, false /*includeInstantApps*/);
intent = updateIntentForResolve(intent);
// writer
synchronized (mPackages) {
@@ -6080,9 +6090,11 @@
}
if (hasWebURI(intent)) {
// cross-profile app linking works only towards the parent.
+ final int callingUid = Binder.getCallingUid();
final UserInfo parent = getProfileParent(sourceUserId);
synchronized(mPackages) {
- int flags = updateFlagsForResolve(0, parent.id, intent, false);
+ int flags = updateFlagsForResolve(0, parent.id, intent, callingUid,
+ false /*includeInstantApps*/);
CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
intent, resolvedType, flags, sourceUserId, parent.id);
return xpDomainInfo != null;
@@ -6149,11 +6161,12 @@
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int userId, boolean includeInstantApp) {
+ String resolvedType, int flags, int userId, boolean includeInstantApps) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
- flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ final String instantAppPkgName = getInstantAppPackageName(callingUid);
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+ enforceCrossUserPermission(callingUid, userId,
false /* requireFullPermission */, false /* checkShell */,
"query intent activities");
ComponentName comp = intent.getComponent();
@@ -6783,9 +6796,11 @@
Intent[] specifics, String[] specificTypes, Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
- false /* requireFullPermission */, false /* checkShell */,
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid,
+ false /*includeInstantApps*/);
+ enforceCrossUserPermission(callingUid, userId,
+ false /*requireFullPermission*/, false /*checkShell*/,
"query intent activity options");
final String resultsAction = intent.getAction();
@@ -6963,7 +6978,9 @@
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid,
+ false /*includeInstantApps*/);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -6999,9 +7016,17 @@
@Override
public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ return resolveServiceInternal(
+ intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
+ }
+
+ private ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags,
+ int userId, int callingUid, boolean includeInstantApps) {
if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent, false);
- List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+ List<ResolveInfo> query = queryIntentServicesInternal(
+ intent, resolvedType, flags, userId, callingUid, includeInstantApps);
if (query != null) {
if (query.size() >= 1) {
// If there is more than one service with the same priority,
@@ -7015,14 +7040,17 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent,
String resolvedType, int flags, int userId) {
- return new ParceledListSlice<>(
- queryIntentServicesInternal(intent, resolvedType, flags, userId));
+ final int callingUid = Binder.getCallingUid();
+ return new ParceledListSlice<>(queryIntentServicesInternal(
+ intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/));
}
private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
- String resolvedType, int flags, int userId) {
+ String resolvedType, int flags, int userId, int callingUid,
+ boolean includeInstantApps) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final String instantAppPkgName = getInstantAppPackageName(callingUid);
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -7034,9 +7062,27 @@
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ServiceInfo si = getServiceInfo(comp, flags, userId);
if (si != null) {
- final ResolveInfo ri = new ResolveInfo();
- ri.serviceInfo = si;
- list.add(ri);
+ // When specifying an explicit component, we prevent the service from being
+ // used when either 1) the service is in an instant application and the
+ // caller is not the same instant application or 2) the calling package is
+ // ephemeral and the activity is not visible to ephemeral applications.
+ final boolean matchVisibleToInstantAppOnly =
+ (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+ final boolean isCallerInstantApp =
+ instantAppPkgName != null;
+ final boolean isTargetSameInstantApp =
+ comp.getPackageName().equals(instantAppPkgName);
+ final boolean isTargetHiddenFromInstantApp =
+ (si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+ final boolean blockResolution =
+ !isTargetSameInstantApp
+ && ((matchVisibleToInstantAppOnly && isCallerInstantApp
+ && isTargetHiddenFromInstantApp));
+ if (!blockResolution) {
+ final ResolveInfo ri = new ResolveInfo();
+ ri.serviceInfo = si;
+ list.add(ri);
+ }
}
return list;
}
@@ -7045,17 +7091,67 @@
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mServices.queryIntent(intent, resolvedType, flags, userId);
+ return applyPostServiceResolutionFilter(
+ mServices.queryIntent(intent, resolvedType, flags, userId),
+ instantAppPkgName);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
- userId);
+ return applyPostServiceResolutionFilter(
+ mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+ userId),
+ instantAppPkgName);
}
return Collections.emptyList();
}
}
+ private List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
+ String instantAppPkgName) {
+ // TODO: When adding on-demand split support for non-instant apps, remove this check
+ // and always apply post filtering
+ if (instantAppPkgName == null) {
+ return resolveInfos;
+ }
+ for (int i = resolveInfos.size() - 1; i >= 0; i--) {
+ final ResolveInfo info = resolveInfos.get(i);
+ final boolean isEphemeralApp = info.serviceInfo.applicationInfo.isInstantApp();
+ // allow services that are defined in the provided package
+ if (isEphemeralApp && instantAppPkgName.equals(info.serviceInfo.packageName)) {
+ if (info.serviceInfo.splitName != null
+ && !ArrayUtils.contains(info.serviceInfo.applicationInfo.splitNames,
+ info.serviceInfo.splitName)) {
+ // requested service is defined in a split that hasn't been installed yet.
+ // add the installer to the resolve list
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+ }
+ final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+ installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
+ info.serviceInfo.packageName, info.serviceInfo.splitName,
+ info.serviceInfo.applicationInfo.versionCode);
+ // make sure this resolver is the default
+ installerInfo.isDefault = true;
+ installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+ // add a non-generic filter
+ installerInfo.filter = new IntentFilter();
+ // load resources from the correct package
+ installerInfo.resolvePackageName = info.getComponentInfo().packageName;
+ resolveInfos.set(i, installerInfo);
+ }
+ continue;
+ }
+ // allow services that have been explicitly exposed to ephemeral apps
+ if (!isEphemeralApp
+ && ((info.serviceInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+ continue;
+ }
+ resolveInfos.remove(i);
+ }
+ return resolveInfos;
+ }
+
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
String resolvedType, int flags, int userId) {
@@ -7066,7 +7162,9 @@
private @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
- flags = updateFlagsForResolve(flags, userId, intent, false);
+ final int callingUid = Binder.getCallingUid();
+ flags = updateFlagsForResolve(flags, userId, intent, callingUid,
+ false /*includeInstantApps*/);
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -12401,11 +12499,29 @@
if (ps == null) {
return null;
}
+ final PackageUserState userState = ps.readUserState(userId);
ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
- ps.readUserState(userId), userId);
+ userState, userId);
if (si == null) {
return null;
}
+ final boolean matchVisibleToInstantApp =
+ (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+ final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+ // throw out filters that aren't visible to ephemeral apps
+ if (matchVisibleToInstantApp
+ && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+ return null;
+ }
+ // throw out ephemeral filters if we're not explicitly requesting them
+ if (!isInstantApp && userState.instantApp) {
+ return null;
+ }
+ // throw out instant app filters if updates are available; will trigger
+ // instant app resolution
+ if (userState.instantApp && ps.isUpdateAvailable()) {
+ return null;
+ }
final ResolveInfo res = new ResolveInfo();
res.serviceInfo = si;
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -12915,9 +13031,6 @@
IActivityManager am = ActivityManager.getService();
if (am != null) {
try {
- getDeviceIdleController().addPowerSaveTempWhitelistApp(Process.SYSTEM_UID,
- DEFAULT_CONTAINER_PACKAGE, DEFAULT_CONTAINER_WHITELIST_DURATION,
- UserHandle.USER_SYSTEM, false, "cleaning packages");
am.startService(null, intent, null, -1, null, false, mContext.getOpPackageName(),
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
@@ -20230,15 +20343,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump ActivityManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " without permission "
- + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
DumpState dumpState = new DumpState();
boolean fullPreferred = false;
@@ -22238,7 +22343,7 @@
if (DEBUG_INSTALL) Slog.d(TAG, "Measured code size " + stats.codeSize + ", data size "
+ stats.dataSize);
- final long startFreeBytes = measurePath.getFreeSpace();
+ final long startFreeBytes = measurePath.getUsableSpace();
final long sizeBytes;
if (moveCompleteApp) {
sizeBytes = stats.codeSize + stats.dataSize;
@@ -22302,7 +22407,7 @@
} catch (InterruptedException ignored) {
}
- final long deltaFreeBytes = startFreeBytes - measurePath.getFreeSpace();
+ final long deltaFreeBytes = startFreeBytes - measurePath.getUsableSpace();
final int progress = 10 + (int) MathUtils.constrain(
((deltaFreeBytes * 80) / sizeBytes), 0, 80);
mMoveCallbacks.notifyStatusChanged(moveId, progress);
@@ -23146,10 +23251,18 @@
}
}
+ @Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
return resolveIntentInternal(
- intent, resolvedType, flags, userId, true /*includeInstantApp*/);
+ intent, resolvedType, flags, userId, true /*includeInstantApps*/);
+ }
+
+ @Override
+ public ResolveInfo resolveService(Intent intent, String resolvedType,
+ int flags, int userId, int callingUid) {
+ return resolveServiceInternal(
+ intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8739089..6fb056a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3375,7 +3375,7 @@
private void applyDefaultPreferredActivityLPw(PackageManagerService service,
Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
- flags = service.updateFlagsForResolve(flags, userId, intent, false);
+ flags = service.updateFlagsForResolve(flags, userId, intent, Binder.getCallingUid(), false);
List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
intent.getType(), flags, 0);
if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 21fe5ba..5035e68 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,7 +20,6 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
@@ -32,7 +31,6 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.ShortcutService.ShortcutOperation;
@@ -70,9 +68,6 @@
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_CATEGORIES = "categories";
- private static final String TAG_CHOOSER_EXTRAS = "chooser-extras";
- private static final String TAG_CHOOSER_INTENT_FILTERS = "chooser-intent-filters";
- private static final String TAG_CHOOSER_COMPONENT_NAMES = "chooser-component-names";
private static final String ATTR_NAME = "name";
private static final String ATTR_CALL_COUNT = "call-count";
@@ -96,7 +91,6 @@
private static final String ATTR_ICON_RES_ID = "icon-res";
private static final String ATTR_ICON_RES_NAME = "icon-resname";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
- private static final String ATTR_COMPONENT_NAMES = "component-names";
private static final String NAME_CATEGORIES = "categories";
@@ -206,7 +200,7 @@
if (shortcut != null) {
mShortcutUser.mService.removeIcon(getPackageUserId(), shortcut);
shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
- | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CHOOSER);
+ | ShortcutInfo.FLAG_MANIFEST);
}
return shortcut;
}
@@ -232,7 +226,7 @@
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
- addCorrectDynamicFlags(newShortcut);
+ newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
@@ -256,17 +250,6 @@
addShortcutInner(newShortcut);
}
- // TODO: Sample code & JavaDoc for ShortcutManager needs updating to reflect the fact that
- // Chooser shortcuts are not always dynamic.
- public void addCorrectDynamicFlags(@NonNull ShortcutInfo shortcut) {
- if (shortcut.getIntent() != null) {
- shortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
- }
- if (!ArrayUtils.isEmpty(shortcut.getChooserIntentFilters())) {
- shortcut.addFlags(ShortcutInfo.FLAG_CHOOSER);
- }
- }
-
/**
* Remove all shortcuts that aren't pinned nor dynamic.
*/
@@ -299,11 +282,11 @@
boolean changed = false;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isDynamic() || si.isChooser()) {
+ if (si.isDynamic()) {
changed = true;
si.setTimestamp(now);
- si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER);
+ si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
si.setRank(0); // It may still be pinned, so clear the rank.
}
}
@@ -372,8 +355,7 @@
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
- oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST
- | ShortcutInfo.FLAG_CHOOSER);
+ oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
}
@@ -708,8 +690,6 @@
getPackageInfo().updateVersionInfo(pi);
- boolean changed = false;
-
// For existing shortcuts, update timestamps if they have any resources.
// Also check if shortcuts' activities are still main activities. Otherwise, disable them.
if (!isNewApp) {
@@ -733,7 +713,6 @@
}
// Still pinned, so fall-through and possibly update the resources.
}
- changed = true;
}
if (si.hasAnyResources()) {
@@ -750,29 +729,23 @@
// non-manifest at the moment, but icons can still be resources.)
si.lookupAndFillInResourceIds(publisherRes);
}
- changed = true;
si.setTimestamp(s.injectCurrentTimeMillis());
}
}
}
// (Re-)publish manifest shortcut.
- changed |= publishManifestShortcuts(newManifestShortcutList);
+ publishManifestShortcuts(newManifestShortcutList);
if (newManifestShortcutList != null) {
- changed |= pushOutExcessShortcuts();
+ pushOutExcessShortcuts();
}
s.verifyStates();
- if (changed) {
- // This will send a notification to the launcher, and also save .
- s.packageShortcutsChanged(getPackageName(), getPackageUserId());
- } else {
- // Still save the version code.
- s.scheduleSaveUser(getPackageUserId());
- }
- return changed;
+ // This will send a notification to the launcher, and also save .
+ s.packageShortcutsChanged(getPackageName(), getPackageUserId());
+ return true; // true means changed.
}
private boolean publishManifestShortcuts(List<ShortcutInfo> newManifestShortcutList) {
@@ -1142,8 +1115,8 @@
// Don't adjust ranks for manifest shortcuts.
continue;
}
- // At this point, it must be dynamic or a chooser.
- if (!si.isDynamicOrChooser()) {
+ // At this point, it must be dynamic.
+ if (!si.isDynamic()) {
s.wtf("Non-dynamic shortcut found.");
continue;
}
@@ -1320,7 +1293,7 @@
ShortcutService.writeAttr(out, ATTR_FLAGS,
si.getFlags() &
~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
- | ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER));
+ | ShortcutInfo.FLAG_DYNAMIC));
} else {
// When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
// as dynamic.
@@ -1343,37 +1316,16 @@
}
final Intent[] intentsNoExtras = si.getIntentsNoExtras();
final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
- if (intentsNoExtras != null) {
- final int numIntents = intentsNoExtras.length;
- for (int i = 0; i < numIntents; i++) {
- out.startTag(null, TAG_INTENT);
- ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
- out.endTag(null, TAG_INTENT);
- }
+ final int numIntents = intentsNoExtras.length;
+ for (int i = 0; i < numIntents; i++) {
+ out.startTag(null, TAG_INTENT);
+ ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+ out.endTag(null, TAG_INTENT);
}
+
ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
- ShortcutService.writeTagExtra(out, TAG_CHOOSER_EXTRAS, si.getChooserExtras());
-
- final IntentFilter[] intentFilters = si.getChooserIntentFilters();
- if (intentFilters != null) {
- for (int i = 0; i < intentFilters.length; i++) {
- out.startTag(null, TAG_CHOOSER_INTENT_FILTERS);
- intentFilters[i].writeToXml(out);
- out.endTag(null, TAG_CHOOSER_INTENT_FILTERS);
- }
- }
-
- final ComponentName[] componentNames = si.getChooserComponentNames();
- if (componentNames != null) {
- for (int i = 0; i < componentNames.length; i++) {
- out.startTag(null, TAG_CHOOSER_COMPONENT_NAMES);
- ShortcutService.writeAttr(out, ATTR_COMPONENT_NAMES, componentNames[i]);
- out.endTag(null, TAG_CHOOSER_COMPONENT_NAMES);
- }
- }
-
out.endTag(null, TAG_SHORTCUT);
}
@@ -1445,9 +1397,6 @@
String iconResName;
String bitmapPath;
ArraySet<String> categories = null;
- PersistableBundle chooserExtras;
- List<IntentFilter> chooserIntentFilters = new ArrayList<>();
- List<ComponentName> chooserComponentNames = new ArrayList<>();
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1508,18 +1457,6 @@
}
}
continue;
- case TAG_CHOOSER_EXTRAS:
- chooserExtras = PersistableBundle.restoreFromXml(parser);
- continue;
- case TAG_CHOOSER_COMPONENT_NAMES:
- chooserComponentNames.add(ShortcutService.parseComponentNameAttribute(parser,
- ATTR_ACTIVITY));
- continue;
- case TAG_CHOOSER_INTENT_FILTERS:
- IntentFilter toAdd = new IntentFilter();
- toAdd.readFromXml(parser);
- chooserIntentFilters.add(toAdd);
- continue;
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
@@ -1613,10 +1550,10 @@
// Verify each shortcut's status.
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (!(si.isDeclaredInManifest() || si.isDynamicOrChooser() || si.isPinned())) {
+ if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " is not manifest, dynamic, chooser or pinned.");
+ + " is not manifest, dynamic or pinned.");
}
if (si.isDeclaredInManifest() && si.isDynamic()) {
failed = true;
@@ -1658,11 +1595,6 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has a dummy target activity");
}
- if (si.getIntent() == null && !si.isChooser()) {
- failed = true;
- Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " has a null intent, but is not a chooser");
- }
}
if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ef46bae..7c89e1c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -27,7 +27,6 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -65,7 +64,6 @@
import android.os.Handler;
import android.os.LocaleList;
import android.os.Looper;
-import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
@@ -96,6 +94,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
@@ -1575,15 +1574,15 @@
* - Write to file
*/
void packageShortcutsChanged(@NonNull String packageName, @UserIdInt int userId) {
- if (DEBUG) {
- Slog.d(TAG, String.format(
- "Shortcut changes: package=%s, user=%d", packageName, userId));
- }
notifyListeners(packageName, userId);
scheduleSaveUser(userId);
}
private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, String.format(
+ "Shortcut changes: package=%s, user=%d", packageName, userId));
+ }
injectPostToHandler(() -> {
try {
final ArrayList<ShortcutChangeListener> copy;
@@ -1753,7 +1752,6 @@
ps.clearAllImplicitRanks();
assignImplicitRanks(newShortcuts);
- // TODO: Consider removing Chooser fields. If so, the FLAG_CHOOSER should be removed
for (int i = 0; i < size; i++) {
final ShortcutInfo source = newShortcuts.get(i);
fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
@@ -1793,13 +1791,6 @@
if (replacingIcon || source.hasStringResources()) {
fixUpShortcutResourceNamesAndValues(target);
}
-
- // While updating, we keep the dynamic flag as it previously was, but refresh the
- // chooser flag.
- // TODO: If we support clearing Chooser fields, we should also remove the flag.
- if (target.getChooserIntentFilters() != null) {
- target.addFlags(ShortcutInfo.FLAG_CHOOSER);
- }
}
// Lastly, adjust the ranks.
@@ -1863,7 +1854,6 @@
return true;
}
- // TODO: Ensure non-launchable shortcuts can not be pinned
@Override
public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) {
@@ -2019,7 +2009,7 @@
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isDynamicOrChooser);
+ ShortcutInfo::isDynamic);
}
}
@@ -2212,14 +2202,6 @@
synchronized (mLock) {
throwIfUserLockedL(userId);
- // For the chooser, we just check is the system is calling.
- // STOPSHIP: We need to implement a new permission here rather than this terrible check.
- // The packageName check is to try to distinguish between when an actual
- // launcher is making the call, and when it's the system.
- if (isCallerSystem() && packageName.equals("android")) {
- return true;
- }
-
final ShortcutUser user = getUserShortcutsLocked(userId);
// Always trust the cached component.
@@ -2392,7 +2374,7 @@
public List<ShortcutInfo> getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName, @Nullable Intent intent,
+ @Nullable ComponentName componentName,
int queryFlags, int userId) {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
@@ -2414,13 +2396,13 @@
if (packageName != null) {
getShortcutsInnerLocked(launcherUserId,
callingPackage, packageName, shortcutIds, changedSince,
- componentName, intent, queryFlags, userId, ret, cloneFlag);
+ componentName, queryFlags, userId, ret, cloneFlag);
} else {
final List<String> shortcutIdsF = shortcutIds;
getUserShortcutsLocked(userId).forAllPackages(p -> {
getShortcutsInnerLocked(launcherUserId,
callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
- componentName, intent, queryFlags, userId, ret, cloneFlag);
+ componentName, queryFlags, userId, ret, cloneFlag);
});
}
}
@@ -2429,7 +2411,7 @@
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
@Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
- @Nullable ComponentName componentName, Intent intent, int queryFlags,
+ @Nullable ComponentName componentName, int queryFlags,
int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
final ArraySet<String> ids = shortcutIds == null ? null
: new ArraySet<>(shortcutIds);
@@ -2454,15 +2436,6 @@
return false;
}
}
- if (intent != null
- && !si.hasMatchingFilter(mContext.getContentResolver(), intent)) {
- return false;
- }
-
- if (((queryFlags & ShortcutQuery.FLAG_MATCH_CHOOSER) != 0)
- && si.isChooser()) {
- return true;
- }
if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
&& si.isDynamic()) {
return true;
@@ -2896,6 +2869,11 @@
}
private void handlePackageChanged(String packageName, int packageUserId) {
+ if (!isPackageInstalled(packageName, packageUserId)) {
+ // Probably disabled, which is the same thing as uninstalled.
+ handlePackageRemoved(packageName, packageUserId);
+ return;
+ }
if (DEBUG) {
Slog.d(TAG, String.format("handlePackageChanged: %s user=%d", packageName,
packageUserId));
@@ -3111,7 +3089,7 @@
}
private static boolean isInstalled(@Nullable ApplicationInfo ai) {
- return (ai != null) && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
+ return (ai != null) && ai.enabled && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
}
private static boolean isEphemeralApp(@Nullable ApplicationInfo ai) {
@@ -3442,8 +3420,12 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
- "can't dump by this caller");
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
+ dumpNoCheck(fd, pw, args);
+ }
+
+ @VisibleForTesting
+ void dumpNoCheck(FileDescriptor fd, PrintWriter pw, String[] args) {
boolean checkin = false;
boolean clear = false;
if (args != null) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8ecf6f7..63e2d47 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -89,6 +89,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -3358,15 +3359,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump UserManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " without permission "
- + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
long now = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 4f67e8c..9c4e700 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -75,6 +75,7 @@
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.server.EventLogTags;
import com.android.server.LockGuard;
import com.android.server.RescueParty;
@@ -4503,13 +4504,7 @@
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump PowerManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index edeb774..8c31731 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -47,6 +47,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -371,7 +372,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
synchronized (mSearchables) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 83ea075..212bd61 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -39,6 +39,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationDelegate;
import com.android.server.power.ShutdownThread;
@@ -981,13 +982,7 @@
// ================================================================================
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump StatusBar from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
pw.println(" mDisabled1=0x" + Integer.toHexString(mDisabled1));
diff --git a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
index 963a572..40bb496 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
@@ -17,6 +17,8 @@
import android.content.ComponentName;
import android.os.RemoteException;
import android.os.ShellCommand;
+import android.service.quicksettings.TileService;
+
import com.android.internal.statusbar.IStatusBarService;
import java.io.PrintWriter;
@@ -48,6 +50,10 @@
return runRemoveTile();
case "click-tile":
return runClickTile();
+ case "check-support":
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println(String.valueOf(TileService.isQuickSettingsSupported()));
+ return 0;
default:
return handleDefaultCommands(cmd);
}
@@ -113,5 +119,8 @@
pw.println(" click-tile COMPONENT");
pw.println(" Click on a TileService of the specified component");
pw.println("");
+ pw.println(" check-support");
+ pw.println(" Check if this device supports QS + APIs");
+ pw.println("");
}
}
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index a847a3c..275b612 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -20,6 +20,7 @@
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.util.DumpUtils;
import com.android.server.EventLogTags;
import com.android.server.SystemService;
import com.android.server.pm.InstructionSets;
@@ -467,15 +468,7 @@
private final Binder mRemoteService = new Binder() {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
dumpImpl(fd, pw, args);
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 4570b0d..f4f7e24 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -59,6 +59,7 @@
import android.view.WindowManagerGlobal;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.SystemService;
import java.io.FileDescriptor;
@@ -849,8 +850,7 @@
@Override
protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
- mContext.enforceCallingPermission(Manifest.permission.DUMP,
- "dumping TrustManagerService");
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
if (isSafeMode()) {
fout.println("disabled because the system is in safe mode.");
return;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 08eca73..6117da7 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -59,6 +59,7 @@
import android.view.KeyEvent;
import android.view.Surface;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
@@ -549,12 +550,7 @@
public void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump TvInputHardwareManager from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
pw.println("TvInputHardwareManager Info:");
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 52763a1..be91f48 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -77,6 +77,7 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
import com.android.server.SystemService;
@@ -1912,12 +1913,7 @@
@SuppressWarnings("resource")
protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump TvInputManager from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
pw.println("User Ids (Current user: " + mCurrentUserId + "):");
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 324faff..cc08918 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -55,6 +55,7 @@
import android.util.SparseArray;
import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
@@ -444,12 +445,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump VrManagerService from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+
pw.println("********* Dump of VrManagerService *********");
pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
pw.println("Persistent VR mode is currently: " +
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index c6b032b..6a18beb 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -87,6 +87,7 @@
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.server.EventLogTags;
@@ -2297,14 +2298,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump wallpaper service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
pw.println("System wallpaper state:");
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 4a105e1..3b400b4 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -33,6 +33,7 @@
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;
+import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
import java.io.FileDescriptor;
@@ -293,14 +294,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump webviewupdate service from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
WebViewUpdateService.this.mImpl.dumpState(pw);
}
}
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 62414e5..9f0ed21 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -32,7 +31,6 @@
import android.util.Slog;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
import android.view.WindowManagerInternal;
/**
@@ -111,10 +109,15 @@
private final boolean mMoveToFullScreen;
// True if this this animation was cancelled and will be replaced the another animation from
// the same {@link #AnimateBoundsUser} target.
- private boolean mWillReplace;
- // True to true if this animation replaced a previous animation of the same
+ private boolean mSkipAnimationEnd;
+ // True if this animation replaced a previous animation of the same
// {@link #AnimateBoundsUser} target.
- private final boolean mReplacement;
+ private final boolean mSkipAnimationStart;
+ // True if this animation is not replacing a previous animation, or if the previous
+ // animation is animating to a different fullscreen state than the current animation.
+ // We use this to ensure that we always provide a consistent set/order of callbacks when we
+ // transition to/from PiP.
+ private final boolean mAnimatingToNewFullscreenState;
// Depending on whether we are animating from
// a smaller to a larger size
@@ -122,13 +125,14 @@
private final int mFrozenTaskHeight;
BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen,
- boolean replacement) {
+ boolean replacingExistingAnimation, boolean animatingToNewFullscreenState) {
super();
mTarget = target;
mFrom.set(from);
mTo.set(to);
mMoveToFullScreen = moveToFullScreen;
- mReplacement = replacement;
+ mSkipAnimationStart = replacingExistingAnimation;
+ mAnimatingToNewFullscreenState = animatingToNewFullscreenState;
addUpdateListener(this);
addListener(this);
@@ -145,11 +149,32 @@
}
}
- boolean animatingToLargerSize() {
- if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
- return false;
+ @Override
+ public void onAnimationStart(Animator animation) {
+ if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ + " mSkipAnimationStart=" + mSkipAnimationStart);
+ mFinishAnimationAfterTransition = false;
+ mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
+ mFrom.top + mFrozenTaskHeight);
+
+ // Ensure that we have prepared the target for animation before
+ // we trigger any size changes, so it can swap surfaces
+ // in to appropriate modes, or do as it wishes otherwise.
+ if (!mSkipAnimationStart) {
+ mTarget.onAnimationStart(mMoveToFullScreen);
}
- return true;
+
+ // If we are animating to a new fullscreen state (either to/from fullscreen), then
+ // notify the target of the change with the new frozen task bounds
+ if (mAnimatingToNewFullscreenState) {
+ mTarget.updatePictureInPictureMode(mMoveToFullScreen ? null : mTo);
+ }
+
+ // Immediately update the task bounds if they have to become larger, but preserve
+ // the starting position so we don't jump at the beginning of the animation.
+ if (animatingToLargerSize()) {
+ mTarget.setPinnedStackSize(mFrom, mTmpRect);
+ }
}
@Override
@@ -174,32 +199,11 @@
}
}
-
- @Override
- public void onAnimationStart(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
- + " mReplacement=" + mReplacement);
- mFinishAnimationAfterTransition = false;
- // Ensure that we have prepared the target for animation before
- // we trigger any size changes, so it can swap surfaces
- // in to appropriate modes, or do as it wishes otherwise.
- if (!mReplacement) {
- mTarget.onAnimationStart(mMoveToFullScreen);
- }
-
- // Immediately update the task bounds if they have to become larger, but preserve
- // the starting position so we don't jump at the beginning of the animation.
- if (animatingToLargerSize()) {
- mTmpRect.set(mFrom.left, mFrom.top,
- mFrom.left + mFrozenTaskWidth, mFrom.top + mFrozenTaskHeight);
- mTarget.setPinnedStackSize(mFrom, mTmpRect);
- }
- }
-
@Override
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
- + " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
+ + " mMoveToFullScreen=" + mMoveToFullScreen
+ + " mSkipAnimationEnd=" + mSkipAnimationEnd);
// There could be another animation running. For example in the
// move to fullscreen case, recents will also be closing while the
@@ -214,7 +218,7 @@
finishAnimation();
mTarget.setPinnedStackSize(mTo, null);
- if (mMoveToFullScreen && !mWillReplace) {
+ if (mMoveToFullScreen && !mSkipAnimationEnd) {
mTarget.moveToFullscreen();
}
}
@@ -226,20 +230,27 @@
@Override
public void cancel() {
- mWillReplace = true;
+ mSkipAnimationEnd = true;
if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget);
super.cancel();
}
/** Returns true if the animation target is the same as the input bounds. */
- public boolean isAnimatingTo(Rect bounds) {
+ boolean isAnimatingTo(Rect bounds) {
return mTo.equals(bounds);
}
+ private boolean animatingToLargerSize() {
+ if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
+ return false;
+ }
+ return true;
+ }
+
private void finishAnimation() {
if (DEBUG) Slog.d(TAG, "finishAnimation: mTarget=" + mTarget
+ " callers" + Debug.getCallers(2));
- if (!mWillReplace) {
+ if (!mSkipAnimationEnd) {
mTarget.onAnimationEnd();
}
removeListener(this);
@@ -249,7 +260,7 @@
@Override
public void onAnimationRepeat(Animator animation) {
-
+ // Do nothing
}
}
@@ -266,14 +277,27 @@
boolean setSize(Rect bounds);
/**
* Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
- * to allow for more flexibility during resizing. Only
- * works for the pinned stack at the moment.
+ * to allow for more flexibility during resizing. Only works for the pinned stack at the
+ * moment.
*/
boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
+ /**
+ * Callback for the target to inform it that the animation has started, so it can do some
+ * necessary preparation.
+ */
void onAnimationStart(boolean toFullscreen);
/**
+ * Callback for the target to inform it that the animation is going to a new fullscreen
+ * state and should update the picture-in-picture mode accordingly.
+ *
+ * @param targetStackBounds the target stack bounds we are animating to, can be null if
+ * we are animating to fullscreen
+ */
+ void updatePictureInPictureMode(Rect targetStackBounds);
+
+ /**
* Callback for the target to inform it that the animation has ended, so it can do some
* necessary cleanup.
*/
@@ -286,9 +310,12 @@
boolean moveToFullscreen) {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
+ final boolean animatingToNewFullscreenState = (existing == null) ||
+ (existing.mMoveToFullScreen != moveToFullscreen);
if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to
- + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing);
+ + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing
+ + " animatingToNewFullscreenState=" + animatingToNewFullscreenState);
if (replacing) {
if (existing.isAnimatingTo(to)) {
@@ -300,8 +327,8 @@
}
existing.cancel();
}
- final BoundsAnimator animator =
- new BoundsAnimator(target, from, to, moveToFullscreen, replacing);
+ final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen,
+ replacing, animatingToNewFullscreenState);
mRunningAnimations.put(target, animator);
animator.setFloatValues(0f, 1f);
animator.setDuration((animationDuration != -1 ? animationDuration
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ae413e5..da524c7 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();
@@ -1134,6 +1146,13 @@
config.screenHeightDp =
(int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
config.uiMode, mDisplayId) / mDisplayMetrics.density);
+
+ mService.mPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, mTmpRect);
+ final int leftInset = mTmpRect.left;
+ final int topInset = mTmpRect.top;
+ // appBounds at the root level should mirror the app screen size.
+ config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + displayInfo.appWidth /*right*/,
+ topInset + displayInfo.appHeight /*bottom*/);
final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
|| displayInfo.rotation == Surface.ROTATION_270);
@@ -1490,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);
}
@@ -1507,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) {
@@ -1540,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) {
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 85eae02..e300256 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -225,14 +225,25 @@
mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
config.unset();
config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
+
+ final int displayId = mDisplayContent.getDisplayId();
+ final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation,
+ baseConfig.uiMode, displayId);
+ final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
+ baseConfig.uiMode, displayId);
+ mService.mPolicy.getNonDecorInsetsLw(rotation, dw, dh, mTmpRect);
+ final int leftInset = mTmpRect.left;
+ final int topInset = mTmpRect.top;
+
+ config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + appWidth /*right*/,
+ topInset + appHeight /*bottom*/);
+
config.screenWidthDp = (int)
(mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode,
- mDisplayContent.getDisplayId()) /
- mDisplayContent.getDisplayMetrics().density);
+ displayId) / mDisplayContent.getDisplayMetrics().density);
config.screenHeightDp = (int)
(mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode,
- mDisplayContent.getDisplayId()) /
- mDisplayContent.getDisplayMetrics().density);
+ displayId) / mDisplayContent.getDisplayMetrics().density);
final Context rotationContext = mService.mContext.createConfigurationContext(config);
mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
rotationContext.getResources(), dw, dh, getContentWidth(),
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 8186d30..635527e 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -270,6 +270,12 @@
int width;
int height;
+
+ final Rect parentAppBounds = parentConfig.appBounds;
+
+ config.setAppBounds(!bounds.isEmpty() ? bounds : null);
+ boolean intersectParentBounds = false;
+
if (StackId.tasksAreFloating(mStackId)) {
// Floating tasks should not be resized to the screen's bounds.
@@ -280,6 +286,7 @@
// the fullscreen stack, without intersecting it with the display bounds
stableBounds.inset(mTmpStableInsets);
nonDecorBounds.inset(mTmpNonDecorInsets);
+ intersectParentBounds = true;
}
width = (int) (stableBounds.width() / density);
height = (int) (stableBounds.height() / density);
@@ -299,6 +306,11 @@
parentConfig.screenWidthDp);
height = Math.min((int) (stableBounds.height() / density),
parentConfig.screenHeightDp);
+ intersectParentBounds = true;
+ }
+
+ if (intersectParentBounds && config.appBounds != null) {
+ config.appBounds.intersect(parentAppBounds);
}
config.screenWidthDp = width;
@@ -350,6 +362,13 @@
}
}
+ /** Calls directly into activity manager so window manager lock shouldn't held. */
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ if (mListener != null) {
+ mListener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+ }
+ }
+
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
index c763c17..a55f9df 100644
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ b/services/core/java/com/android/server/wm/StackWindowListener.java
@@ -26,4 +26,10 @@
/** Called when the stack container would like its controller to resize. */
void requestResize(Rect bounds);
+
+ /**
+ * Called when the stack container pinned stack animation will change the picture-in-picture
+ * mode. This is a direct call into ActivityManager.
+ */
+ default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 8b5f5ac..1a67ac7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1483,6 +1483,14 @@
}
@Override // AnimatesBounds
+ public void updatePictureInPictureMode(Rect targetStackBounds) {
+ final StackWindowController controller = getController();
+ if (controller != null) {
+ controller.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+ }
+ }
+
+ @Override // AnimatesBounds
public void onAnimationEnd() {
synchronized (mService.mWindowMap) {
mBoundsAnimating = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6c7da50..1691d14 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -204,6 +204,7 @@
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -5311,8 +5312,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) {
}
@@ -5337,8 +5338,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);
}
@@ -6517,13 +6517,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump WindowManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
boolean dumpAll = false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
new file mode 100644
index 0000000..97fa9d5
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
@@ -0,0 +1,211 @@
+/*
+ * 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.devicepolicy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.IDeviceAdminService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.am.PersistentConnection;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Manages connections to persistent services in owner packages.
+ */
+public class DeviceAdminServiceController {
+ static final String TAG = DevicePolicyManagerService.LOG_TAG;
+
+ static final boolean DEBUG = false; // DO NOT MERGE WITH TRUE.
+
+ final Object mLock = new Object();
+ final Context mContext;
+
+ private final DevicePolicyManagerService mService;
+ private final DevicePolicyManagerService.Injector mInjector;
+
+ private final Handler mHandler; // needed?
+
+ static void debug(String format, Object... args) {
+ if (!DEBUG) {
+ return;
+ }
+ Slog.d(TAG, String.format(format, args));
+ }
+
+ private class DevicePolicyServiceConnection
+ extends PersistentConnection<IDeviceAdminService> {
+ public DevicePolicyServiceConnection(int userId, @NonNull ComponentName componentName) {
+ super(TAG, mContext, mHandler, userId, componentName);
+ }
+
+ @Override
+ protected IDeviceAdminService asInterface(IBinder binder) {
+ return IDeviceAdminService.Stub.asInterface(binder);
+ }
+ }
+
+ /**
+ * User-ID -> {@link PersistentConnection}.
+ */
+ @GuardedBy("mLock")
+ private final SparseArray<DevicePolicyServiceConnection> mConnections = new SparseArray<>();
+
+ public DeviceAdminServiceController(DevicePolicyManagerService service) {
+ mService = service;
+ mInjector = service.mInjector;
+ mContext = mInjector.mContext;
+ mHandler = new Handler(BackgroundThread.get().getLooper());
+ }
+
+ /**
+ * Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
+ * in a given package.
+ */
+ @Nullable
+ private ServiceInfo findService(@NonNull String packageName, int userId) {
+ final Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE);
+ intent.setPackage(packageName);
+
+ try {
+ final ParceledListSlice<ResolveInfo> pls = mInjector.getIPackageManager()
+ .queryIntentServices(intent, null, /* flags=*/ 0, userId);
+ if (pls == null) {
+ return null;
+ }
+ final List<ResolveInfo> list = pls.getList();
+ if (list.size() == 0) {
+ return null;
+ }
+ // Note if multiple services are found, that's an error, even if only one of them
+ // is exported.
+ if (list.size() > 1) {
+ Log.e(TAG, "More than one DeviceAdminService's found in package "
+ + packageName
+ + ". They'll all be ignored.");
+ return null;
+ }
+ final ServiceInfo si = list.get(0).serviceInfo;
+ if (si.exported) {
+ Log.e(TAG, "DeviceAdminService must not be exported: '"
+ + si.getComponentName().flattenToShortString()
+ + "' will be ignored.");
+ return null;
+ }
+ return si;
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
+ * in an owner package and connect to it.
+ */
+ public void startServiceForOwner(@NonNull String packageName, int userId,
+ @NonNull String actionForLog) {
+ final long token = mInjector.binderClearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ final ServiceInfo service = findService(packageName, userId);
+ if (service == null) {
+ debug("Owner package %s on u%d has no service.",
+ packageName, userId);
+ disconnectServiceOnUserLocked(userId, actionForLog);
+ return;
+ }
+ // See if it's already running.
+ final PersistentConnection<IDeviceAdminService> existing =
+ mConnections.get(userId);
+ if (existing != null) {
+ if (existing.getComponentName().equals(service.getComponentName())) {
+ return;
+ }
+ disconnectServiceOnUserLocked(userId, actionForLog);
+ }
+
+ debug("Owner package %s on u%d has service %s for %s",
+ packageName, userId,
+ service.getComponentName().flattenToShortString(), actionForLog);
+
+ final DevicePolicyServiceConnection conn =
+ new DevicePolicyServiceConnection(
+ userId, service.getComponentName());
+ mConnections.put(userId, conn);
+ conn.connect();
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Stop an owner service on a given user.
+ */
+ public void stopServiceForOwner(int userId, @NonNull String actionForLog) {
+ final long token = mInjector.binderClearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ disconnectServiceOnUserLocked(userId, actionForLog);
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(token);
+ }
+ }
+
+ private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) {
+ final DevicePolicyServiceConnection conn = mConnections.get(userId);
+ if (conn != null) {
+ debug("Stopping service for u%d if already running for %s.",
+ userId, actionForLog);
+ conn.disconnect();
+ mConnections.remove(userId);
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ synchronized (mLock) {
+ if (mConnections.size() == 0) {
+ return;
+ }
+ pw.println();
+ pw.print(prefix); pw.println("Owner Services:");
+ for (int i = 0; i < mConnections.size(); i++) {
+ final int userId = mConnections.keyAt(i);
+ pw.print(prefix); pw.print(" "); pw.print("User: "); pw.println(userId);
+
+ final DevicePolicyServiceConnection con = mConnections.valueAt(i);
+ con.dump(prefix + " ", pw);
+ }
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index db7c99e..bfa1b99 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -140,7 +140,6 @@
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsInternal;
import android.provider.Settings;
-import android.security.Credentials;
import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
@@ -169,6 +168,7 @@
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
@@ -193,7 +193,6 @@
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
-import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -364,6 +363,7 @@
final UserManagerInternal mUserManagerInternal;
final TelephonyManager mTelephonyManager;
private final LockPatternUtils mLockPatternUtils;
+ private final DeviceAdminServiceController mDeviceAdminServiceController;
/**
* Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
@@ -458,7 +458,17 @@
@Override
public void onStartUser(int userHandle) {
- mService.onStartUser(userHandle);
+ mService.handleStartUser(userHandle);
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mService.handleUnlockUser(userHandle);
+ }
+
+ @Override
+ public void onStopUser(int userHandle) {
+ mService.handleStopUser(userHandle);
}
}
@@ -1419,7 +1429,7 @@
}
}
- private void handlePackagesChanged(String packageName, int userHandle) {
+ private void handlePackagesChanged(@Nullable String packageName, int userHandle) {
boolean removedAdmin = false;
if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
@@ -1433,9 +1443,9 @@
if (packageName == null || packageName.equals(adminPackage)) {
if (mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) == null
|| mIPackageManager.getReceiverInfo(aa.info.getComponent(),
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userHandle) == null) {
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userHandle) == null) {
removedAdmin = true;
policy.mAdminList.remove(i);
policy.mAdminMap.remove(aa.info.getComponent());
@@ -1460,6 +1470,13 @@
}
}
+ // If it's an owner package, we may need to refresh the bound connection.
+ final ComponentName owner = getOwnerComponent(userHandle);
+ if ((packageName != null) && (owner != null)
+ && (owner.getPackageName().equals(packageName))) {
+ startOwnerService(userHandle, "package-broadcast");
+ }
+
// Persist updates if the removed package was an admin or delegate.
if (removedAdmin || removedDelegate) {
saveSettingsLocked(policy.mUserHandle);
@@ -1790,6 +1807,8 @@
// Needed when mHasFeature == false, because it controls the certificate warning text.
mCertificateMonitor = new CertificateMonitor(this, mInjector, mBackgroundHandler);
+ mDeviceAdminServiceController = new DeviceAdminServiceController(this);
+
if (!mHasFeature) {
// Skip the rest of the initialization
return;
@@ -2942,7 +2961,7 @@
loadOwners();
cleanUpOldUsers();
ensureUnknownSourcesRestrictionForProfileOwners();
- onStartUser(UserHandle.USER_SYSTEM);
+ handleStartUser(UserHandle.USER_SYSTEM);
// Register an observer for watching for user setup complete and settings changes.
mSetupContentObserver.register();
@@ -2989,10 +3008,32 @@
}
}
- private void onStartUser(int userId) {
+ void handleStartUser(int userId) {
updateScreenCaptureDisabledInWindowManager(userId,
getScreenCaptureDisabled(null, userId));
pushUserRestrictions(userId);
+
+ startOwnerService(userId, "start-user");
+ }
+
+ void handleUnlockUser(int userId) {
+ startOwnerService(userId, "unlock-user");
+ }
+
+ void handleStopUser(int userId) {
+ stopOwnerService(userId, "stop-user");
+ }
+
+ private void startOwnerService(int userId, String actionForLog) {
+ final ComponentName owner = getOwnerComponent(userId);
+ if (owner != null) {
+ mDeviceAdminServiceController.startServiceForOwner(
+ owner.getPackageName(), userId, actionForLog);
+ }
+ }
+
+ private void stopOwnerService(int userId, String actionForLog) {
+ mDeviceAdminServiceController.stopServiceForOwner(userId, actionForLog);
}
private void cleanUpOldUsers() {
@@ -5077,7 +5118,7 @@
* @param callerPackage the name of the calling package. Required if {@code who} is
* {@code null}.
* @param reqPolicy the policy used in the API whose access permission is being checked.
- * @param scoppe the delegation scope corresponding to the API being checked.
+ * @param scope the delegation scope corresponding to the API being checked.
* @throws SecurityException if {@code who} is given and is not an owner for {@code reqPolicy};
* or when {@code who} is {@code null} and {@code callerPackage} is not a delegate
* of {@code scope}.
@@ -6459,6 +6500,9 @@
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
+ mDeviceAdminServiceController.startServiceForOwner(
+ admin.getPackageName(), userId, "set-device-owner");
+
Slog.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId);
return true;
}
@@ -6614,6 +6658,8 @@
}
private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) {
+ mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-device-owner");
+
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
@@ -6691,6 +6737,8 @@
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
+ mDeviceAdminServiceController.startServiceForOwner(
+ who.getPackageName(), userHandle, "set-profile-owner");
return true;
}
}
@@ -6722,6 +6770,8 @@
}
public void clearProfileOwnerLocked(ActiveAdmin admin, int userId) {
+ mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-profile-owner");
+
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
@@ -7269,18 +7319,12 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
- + mInjector.binderGetCallingPid()
- + ", uid=" + mInjector.binderGetCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
synchronized (this) {
pw.println("Current Device Policy Manager state:");
mOwners.dump(" ", pw);
+ mDeviceAdminServiceController.dump(" ", pw);
int userCount = mUserData.size();
for (int u = 0; u < userCount; u++) {
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
@@ -9630,6 +9674,21 @@
return null;
}
+ /**
+ * Return device owner or profile owner set on a given user.
+ */
+ private @Nullable ComponentName getOwnerComponent(int userId) {
+ synchronized (this) {
+ if (mOwners.getDeviceOwnerUserId() == userId) {
+ return mOwners.getDeviceOwnerComponent();
+ }
+ if (mOwners.hasProfileOwner(userId)) {
+ return mOwners.getProfileOwnerComponent(userId);
+ }
+ }
+ return null;
+ }
+
private int checkManagedUserProvisioningPreCondition(int callingUserId) {
if (!hasFeatureManagedUsers()) {
return CODE_MANAGED_USERS_NOT_SUPPORTED;
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 1c18c9b..100e459 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -45,6 +45,7 @@
import android.util.Log;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.server.SystemService;
@@ -1011,7 +1012,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("MIDI Manager State:");
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index d7666d9..3ec8380 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -19,7 +19,6 @@
import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
-import android.Manifest;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.ComponentName;
@@ -40,22 +39,23 @@
import android.print.IPrintDocumentAdapter;
import android.print.IPrintJobStateChangeListener;
import android.print.IPrintManager;
-import android.printservice.recommendation.IRecommendationsChangeListener;
import android.print.IPrintServicesChangeListener;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
-import android.printservice.recommendation.RecommendationInfo;
import android.print.PrinterId;
import android.printservice.PrintServiceInfo;
+import android.printservice.recommendation.IRecommendationsChangeListener;
+import android.printservice.recommendation.RecommendationInfo;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
@@ -628,13 +628,7 @@
fd = Preconditions.checkNotNull(fd);
pw = Preconditions.checkNotNull(pw);
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump PrintManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
synchronized (mLock) {
final long identity = Binder.clearCallingIdentity();
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 7c37027..d281e5a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -36,7 +36,6 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -569,6 +568,7 @@
protected Map<String, PackageInfo> mInjectedPackages;
protected Set<PackageWithUser> mUninstalledPackages;
+ protected Set<PackageWithUser> mDisabledPackages;
protected Set<PackageWithUser> mEphemeralPackages;
protected Set<String> mSystemPackages;
@@ -740,6 +740,7 @@
pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
mUninstalledPackages = new HashSet<>();
+ mDisabledPackages = new HashSet<>();
mSystemPackages = new HashSet<>();
mEphemeralPackages = new HashSet<>();
@@ -1026,7 +1027,7 @@
protected void uninstallPackage(int userId, String packageName) {
if (ENABLE_DUMP) {
- Log.v(TAG, "Unnstall package " + packageName + " / " + userId);
+ Log.v(TAG, "Uninstall package " + packageName + " / " + userId);
}
mUninstalledPackages.add(PackageWithUser.of(userId, packageName));
}
@@ -1038,6 +1039,20 @@
mUninstalledPackages.remove(PackageWithUser.of(userId, packageName));
}
+ protected void disablePackage(int userId, String packageName) {
+ if (ENABLE_DUMP) {
+ Log.v(TAG, "Disable package " + packageName + " / " + userId);
+ }
+ mDisabledPackages.add(PackageWithUser.of(userId, packageName));
+ }
+
+ protected void enablePackage(int userId, String packageName) {
+ if (ENABLE_DUMP) {
+ Log.v(TAG, "Enable package " + packageName + " / " + userId);
+ }
+ mDisabledPackages.remove(PackageWithUser.of(userId, packageName));
+ }
+
PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId,
boolean getSignatures) {
final PackageInfo pi = mInjectedPackages.get(packageName);
@@ -1061,6 +1076,8 @@
if (mSystemPackages.contains(packageName)) {
ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
}
+ ret.applicationInfo.enabled =
+ !mDisabledPackages.contains(PackageWithUser.of(userId, packageName));
if (getSignatures) {
ret.signatures = pi.signatures;
@@ -1258,7 +1275,7 @@
try {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintWriter pw = new PrintWriter(out);
- mService.dump(/* fd */ null, pw, args);
+ mService.dumpNoCheck(/* fd */ null, pw, args);
pw.close();
return out.toString();
@@ -1327,23 +1344,20 @@
protected ShortcutInfo makeShortcut(String id) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
@Deprecated // Title was renamed to short label.
protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
return makeShortcut(
id, title, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
return makeShortcut(
id, shortLabel, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
/**
@@ -1352,8 +1366,7 @@
protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
s.setTimestamp(timestamp);
return s;
}
@@ -1365,8 +1378,7 @@
ComponentName activity) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
s.setTimestamp(timestamp);
return s;
}
@@ -1377,27 +1389,7 @@
protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, icon,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
- }
-
- protected ShortcutInfo makeChooserShortcut(String id, int i, boolean includeIntent) {
- List<IntentFilter> filters = new ArrayList<>();
- List<ComponentName> componentNames = new ArrayList<>();
- for(int j = 0; j < i; j++) {
- final IntentFilter filter = new IntentFilter();
- filter.addAction("view");
- filters.add(filter);
-
- componentNames.add(new ComponentName("xxxx", "yy" + i));
- }
- Intent intent = null;
- if (includeIntent) {
- intent = makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class);
- }
- return makeShortcut(
- id, "Title-" + id, /* activity =*/ null, /* icon */ null,
- intent, /* rank =*/ 0, filters, componentNames);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makePackageShortcut(String packageName, String id) {
@@ -1406,8 +1398,7 @@
setCaller(packageName);
ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
setCaller(origCaller); // restore the caller
return s;
@@ -1431,52 +1422,39 @@
protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- intent, /* rank =*/ 0, /* chooserFilters =*/ null,
- /* chooserComponentNames =*/ null);
-
+ intent, /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
String title) {
return makeShortcut(
id, title, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
- /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
int rank) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank,
- /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
}
/**
* Make a shortcut with details.
*/
protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
- Icon icon, Intent intent, int rank, @Nullable List<IntentFilter> chooserFilters,
- @Nullable List<ComponentName> chooserComponentNames) {
+ Icon icon, Intent intent, int rank) {
final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
.setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
.setShortLabel(title)
- .setRank(rank);
- if (intent != null) {
- b.setIntent(intent);
- }
- if (chooserFilters != null) {
- for (int i = 0; i < chooserFilters.size(); i++) {
- b.addChooserIntentFilter(chooserFilters.get(i), chooserComponentNames.get(i));
- }
- }
+ .setRank(rank)
+ .setIntent(intent);
if (icon != null) {
b.setIcon(icon);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 796cc16..9861aa1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -17,7 +17,6 @@
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.anyOrNull;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.anyStringOrNull;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllChooser;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
@@ -58,7 +57,6 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -102,6 +100,8 @@
import java.io.IOException;
import java.util.List;
import java.util.Locale;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
/**
* Tests for ShortcutService and ShortcutManager.
@@ -259,9 +259,7 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"shortcut2",
@@ -269,18 +267,14 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
final ShortcutInfo si3 = makeShortcut(
"shortcut3",
"Title 3",
/* activity */ null,
icon3,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 13,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 13);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -991,10 +985,8 @@
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5"),
- makeChooserShortcut("s6", 2, true),
- makeChooserShortcut("s7", 2, true),
- makeChooserShortcut("s8", 1, true))));
+ makeShortcut("s5")
+ )));
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -1002,13 +994,11 @@
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5"),
- makeChooserShortcut("s6", 2, true),
- makeChooserShortcut("s7", 2, true),
- makeChooserShortcut("s8", 1, true))));
+ makeShortcut("s5")
+ )));
});
runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3", "s6"),
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
getCallingUser());
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
getCallingUser());
@@ -1021,20 +1011,19 @@
mManager.removeDynamicShortcuts(list("s1"));
mManager.removeDynamicShortcuts(list("s3"));
mManager.removeDynamicShortcuts(list("s5"));
- mManager.removeDynamicShortcuts(list("s7"));
});
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5", "s6", "s7", "s8");
+ "s3", "s4", "s5");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3", "s6");
+ "s2", "s3");
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4", "s6", "s8");
+ "s2", "s4");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1071,10 +1060,10 @@
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5", "s6", "s7", "s8");
+ "s3", "s4", "s5");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3", "s6");
+ "s2", "s3");
ShortcutInfo s = getCallerShortcut("s2");
assertTrue(s.hasIconResource());
@@ -1090,7 +1079,7 @@
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4", "s6", "s8");
+ "s2", "s4");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1187,46 +1176,7 @@
});
}
- public void testUpdateShortcuts_chooser() {
- runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"),
- makeChooserShortcut("s2", 2, false),
- makeChooserShortcut("s3", 2, false)
- )));
-
- assertFalse(getCallerShortcut("s1").isChooser());
- assertTrue(getCallerShortcut("s2").isChooser());
- assertTrue(getCallerShortcut("s3").isChooser());
-
- ShortcutInfo s = getCallerShortcut("s1");
- assertNull(s.getChooserIntentFilters());
- assertNull(s.getChooserComponentNames());
-
- assertTrue(getCallerShortcut("s1").isDynamic());
- assertFalse(getCallerShortcut("s2").isDynamic());
- assertFalse(getCallerShortcut("s3").isDynamic());
-
-
- // Replace 2 with a chooser shortcut
- mManager.updateShortcuts(list(makeChooserShortcut("s1", 2, true)));
-
- s = getCallerShortcut("s1");
- assertEquals(2, s.getChooserIntentFilters().length);
- assertEquals(2, s.getChooserComponentNames().length);
-
- assertShortcutIds(assertAllChooser(
- mManager.getDynamicShortcuts()),
- "s1", "s2", "s3");
-
- assertTrue(getCallerShortcut("s1").isDynamic());
- assertFalse(getCallerShortcut("s2").isDynamic());
- assertFalse(getCallerShortcut("s3").isDynamic());
- });
- }
-
-
- // === Test for launcher side APIs ===
+ // === Test for launcher side APIs ===
public void testGetShortcuts() {
@@ -1537,17 +1487,15 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo s1_2 = makeShortcut(
- "s2", "Title 2",
+ "s2",
+ "Title 2",
/* activity */ null,
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
dumpsysOnLogcat();
@@ -1560,9 +1508,7 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
dumpsysOnLogcat();
@@ -2731,12 +2677,10 @@
final ShortcutInfo s1_2 = makeShortcut(
"s2",
"Title 2",
- /* activity */ null,
- /* icon =*/ null,
+ /* activity */ null,
+ /* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* rank */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* rank */ 12);
final ShortcutInfo s1_3 = makeShortcut("s3");
@@ -2751,9 +2695,7 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
});
@@ -3173,9 +3115,7 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3183,9 +3123,7 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12,
- /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3203,8 +3141,8 @@
makeComponent(ShortcutActivity.class),
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
- "key1", "val1", "nest", makeBundle("key", 123)), /* weight */ 10,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3212,8 +3150,7 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3235,8 +3172,7 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 10);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3244,8 +3180,7 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null);
+ /* weight */ 12);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3967,6 +3902,22 @@
}
public void testHandlePackageDelete() {
+ checkHandlePackageDeleteInner((userId, packageName) -> {
+ uninstallPackage(userId, packageName);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageDeleteIntent(packageName, userId));
+ });
+ }
+
+ public void testHandlePackageDisable() {
+ checkHandlePackageDeleteInner((userId, packageName) -> {
+ disablePackage(userId, packageName);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageChangedIntent(packageName, userId));
+ });
+ }
+
+ private void checkHandlePackageDeleteInner(BiConsumer<Integer, String> remover) {
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
setCaller(CALLING_PACKAGE_1, USER_0);
@@ -4019,9 +3970,7 @@
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
- uninstallPackage(USER_0, CALLING_PACKAGE_1);
- mService.mPackageMonitor.onReceive(getTestContext(),
- genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
+ remover.accept(USER_0, CALLING_PACKAGE_1);
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4039,9 +3988,7 @@
mRunningUsers.put(USER_10, true);
- uninstallPackage(USER_10, CALLING_PACKAGE_2);
- mService.mPackageMonitor.onReceive(getTestContext(),
- genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
+ remover.accept(USER_10, CALLING_PACKAGE_2);
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -6870,12 +6817,10 @@
mManager.setDynamicShortcuts(list(
makeShortcut("ms1", "title1",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0,
- /* chooserFilter=*/ null, /* chooserComponentNames=*/ null),
+ /* icon */ null, new Intent("action1"), /* rank */ 0),
makeShortcut("ms2", "title2",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0, /* chooserFilter=*/ null,
- /* chooserComponentNames=*/ null)));
+ /* icon */ null, new Intent("action1"), /* rank */ 0)));
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 7c5eb07..9880caa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -34,7 +34,6 @@
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
@@ -93,6 +92,11 @@
assertExpectException(
RuntimeException.class,
+ "intents cannot contain null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
+
+ assertExpectException(
+ RuntimeException.class,
"action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -137,19 +141,6 @@
"disabledMessage cannot be empty",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
-
- assertExpectException(
- RuntimeException.class,
- "component name cannot be null",
- () -> new ShortcutInfo.Builder(getTestContext(), "id")
- .addChooserIntentFilter(new IntentFilter(Intent.ACTION_SEND), null));
-
- assertExpectException(
- RuntimeException.class,
- "intent filter cannot be null",
- () -> new ShortcutInfo.Builder(getTestContext(), "id")
- .addChooserIntentFilter(null, new ComponentName("xxx", "s")));
-
assertExpectException(NullPointerException.class, "action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -248,10 +239,6 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -264,8 +251,6 @@
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -296,12 +281,6 @@
assertEquals(null, si.getTextResName());
assertEquals(0, si.getDisabledMessageResourceId());
assertEquals(null, si.getDisabledMessageResName());
-
- assertEquals(1, si.getChooserIntentFilters().length);
- assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
- assertEquals(1, si.getChooserComponentNames().length);
- assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
- assertEquals(1, si.getChooserExtras().getInt("l"));
}
public void testShortcutInfoParcel_resId() {
@@ -310,10 +289,6 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -326,8 +301,6 @@
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -364,11 +337,6 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
-
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -380,8 +348,6 @@
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -411,12 +377,6 @@
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
- assertEquals(1, si.getChooserIntentFilters().length);
- assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
- assertEquals(1, si.getChooserComponentNames().length);
- assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
- assertEquals(1, si.getChooserExtras().getInt("l"));
-
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -484,10 +444,6 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -499,8 +455,6 @@
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
- .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
- .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -533,12 +487,6 @@
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
- assertEquals(1, si.getChooserIntentFilters().length);
- assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
- assertEquals(1, si.getChooserComponentNames().length);
- assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
- assertEquals(1, si.getChooserExtras().getInt("l"));
-
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -654,10 +602,6 @@
public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- IntentFilter chooserFilter = new IntentFilter();
- chooserFilter.addAction(Intent.ACTION_VIEW);
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -769,12 +713,12 @@
assertEquals(999, si.getRank());
- PersistableBundle pb3 = new PersistableBundle();
- pb3.putInt("x", 99);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("x", 99);
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
- .setExtras(pb3).build());
+ .setExtras(pb2).build());
assertEquals("text", si.getText());
assertEquals(99, si.getExtras().getInt("x"));
}
@@ -2096,16 +2040,6 @@
assertEquals(expected, dumpCheckin());
}
- public void testDumpsysNoPermission() {
- assertExpectException(SecurityException.class, "android.permission.DUMP",
- () -> mService.dump(null, new PrintWriter(new StringWriter()), null));
-
- // System can call it without the permission.
- runWithSystemUid(() -> {
- mService.dump(null, new PrintWriter(new StringWriter()), null);
- });
- }
-
/**
* Make sure the legacy file format that only supported a single intent per shortcut
* can still be read.
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java b/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java
new file mode 100644
index 0000000..f68e06a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java
@@ -0,0 +1,144 @@
+/*
+ * 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.res.Configuration;
+import android.graphics.Rect;
+import android.os.Debug;
+import android.view.DisplayInfo;
+import org.junit.Test;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class to exercise logic related to {@link android.content.res.Configuration#appBounds}.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.AppBoundsTests
+ */
+@SmallTest
+@Presubmit
+@org.junit.runner.RunWith(AndroidJUnit4.class)
+public class AppBoundsTests extends WindowTestsBase {
+ private Rect mParentBounds;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
+ }
+
+ /**
+ * Ensures the configuration app bounds at the root level match the app dimensions.
+ */
+ @Test
+ public void testRootConfigurationBounds() throws Exception {
+ final DisplayInfo info = sDisplayContent.getDisplayInfo();
+ info.appWidth = 1024;
+ info.appHeight = 768;
+
+ final Configuration config = sWm.computeNewConfiguration(sDisplayContent.getDisplayId());
+ // The bounds should always be positioned in the top left.
+ assertEquals(config.appBounds.left, 0);
+ assertEquals(config.appBounds.top, 0);
+
+ // The bounds should equal the defined app width and height
+ assertEquals(config.appBounds.width(), info.appWidth);
+ assertEquals(config.appBounds.height(), info.appHeight);
+ }
+
+ /**
+ * Ensures that bounds are clipped to their parent.
+ */
+ @Test
+ public void testBoundsClipping() throws Exception {
+ final Rect shiftedBounds = new Rect(mParentBounds);
+ shiftedBounds.offset(10, 10);
+ final Rect expectedBounds = new Rect(mParentBounds);
+ expectedBounds.intersect(shiftedBounds);
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, shiftedBounds,
+ expectedBounds);
+ }
+
+ /**
+ * Ensures that empty bounds are not propagated to the configuration.
+ */
+ @Test
+ public void testEmptyBounds() throws Exception {
+ final Rect emptyBounds = new Rect();
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds,
+ null /*ExpectedBounds*/);
+ }
+
+ /**
+ * Ensures that bounds on freeform stacks are not clipped.
+ */
+ @Test
+ public void testFreeFormBounds() throws Exception {
+ final Rect freeFormBounds = new Rect(mParentBounds);
+ freeFormBounds.offset(10, 10);
+ testStackBoundsConfiguration(ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID,
+ mParentBounds, freeFormBounds, freeFormBounds);
+ }
+
+ /**
+ * Ensures that fully contained bounds are not clipped.
+ */
+ @Test
+ public void testContainedBounds() throws Exception {
+ final Rect insetBounds = new Rect(mParentBounds);
+ insetBounds.inset(5, 5, 5, 5);
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds);
+ }
+
+ /**
+ * Ensures that full screen free form bounds are clipped
+ */
+ @Test
+ public void testFullScreenFreeFormBounds() throws Exception {
+ final Rect fullScreenBounds = new Rect(0, 0, sDisplayInfo.logicalWidth,
+ sDisplayInfo.logicalHeight);
+ testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds,
+ mParentBounds);
+ }
+
+
+ private void testStackBoundsConfiguration(Integer stackId, Rect parentBounds, Rect bounds,
+ Rect expectedConfigBounds) {
+ final StackWindowController stackController = stackId != null ?
+ createStackControllerOnStackOnDisplay(stackId, sDisplayContent)
+ : createStackControllerOnDisplay(sDisplayContent);
+
+ final Configuration parentConfig = sDisplayContent.getConfiguration();
+ parentConfig.setAppBounds(parentBounds);
+
+ final Configuration config = new Configuration();
+ stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/,
+ new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/,
+ false /*overrideHeight*/, sDisplayInfo.logicalDensityDpi, config, parentConfig);
+ // Assert that both expected and actual are null or are equal to each other
+
+ assertTrue((expectedConfigBounds == null && config.appBounds == null)
+ || expectedConfigBounds.equals(config.appBounds));
+ }
+}
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 1729cee..e3ccd6e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -213,10 +213,10 @@
*/
@Test
public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
- final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration();
+ final Configuration currentConfig = sDisplayContent.getConfiguration();
// Create new, slightly changed override configuration and apply it to the display.
- final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
+ final Configuration newOverrideConfig = new Configuration(currentConfig);
newOverrideConfig.densityDpi += 120;
newOverrideConfig.fontScale += 0.3;
@@ -228,10 +228,10 @@
assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
// Return back to original values.
- sWm.setNewDisplayOverrideConfiguration(currentOverrideConfig, DEFAULT_DISPLAY);
+ sWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
globalConfig = sWm.mRoot.getConfiguration();
- assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
- assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
+ assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
+ assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 0b72a21..fbeda0a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import android.content.pm.ActivityInfo;
import android.os.PowerSaveState;
import org.mockito.invocation.InvocationOnMock;
@@ -449,9 +450,8 @@
}
@Override
- public boolean rotationHasCompatibleMetricsLw(int orientation,
- int rotation) {
- return false;
+ public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
+ return true;
}
@Override
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 1b1984d..2e6eac0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -250,37 +250,57 @@
@Test
public void testLayoutNonfullscreenTask() {
- final Rect taskBounds = new Rect(300, 300, 700, 700);
+ final DisplayInfo displayInfo = sWm.getDefaultDisplayContentLocked().getDisplayInfo();
+ final int logicalWidth = displayInfo.logicalWidth;
+ final int logicalHeight = displayInfo.logicalHeight;
+
+ final int taskLeft = logicalWidth / 4;
+ final int taskTop = logicalHeight / 4;
+ final int taskRight = logicalWidth / 4 * 3;
+ final int taskBottom = logicalHeight / 4 * 3;
+ final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
TaskWithBounds task = new TaskWithBounds(taskBounds);
task.mFullscreenForTest = false;
WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- final Rect pf = new Rect(0, 0, 1000, 1000);
+ final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null);
// For non fullscreen tasks the containing frame is based off the
// task bounds not the parent frame.
- assertRect(w.mFrame, 300, 300, 700, 700);
- assertRect(w.getContentFrameLw(), 300, 300, 700, 700);
+ assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+ assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
assertRect(w.mContentInsets, 0, 0, 0, 0);
- pf.set(0, 0, 1000, 1000);
+ pf.set(0, 0, logicalWidth, logicalHeight);
// We still produce insets against the containing frame the same way.
- final Rect cf = new Rect(0, 0, 500, 500);
+ final int cfRight = logicalWidth / 2;
+ final int cfBottom = logicalHeight / 2;
+ final Rect cf = new Rect(0, 0, cfRight, cfBottom);
w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
- assertRect(w.mFrame, 300, 300, 700, 700);
- assertRect(w.getContentFrameLw(), 300, 300, 500, 500);
- assertRect(w.mContentInsets, 0, 0, 200, 200);
+ assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+ int contentInsetRight = taskRight - cfRight;
+ int contentInsetBottom = taskBottom - cfBottom;
+ assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
+ assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
+ taskBottom - contentInsetBottom);
- pf.set(0, 0, 1000, 1000);
+ pf.set(0, 0, logicalWidth, logicalHeight);
// However if we set temp inset bounds, the insets will be computed
// as if our window was laid out there, but it will be laid out according to
// the task bounds.
- task.mInsetBounds.set(200, 200, 600, 600);
+ final int insetLeft = logicalWidth / 5;
+ final int insetTop = logicalHeight / 5;
+ final int insetRight = insetLeft + (taskRight - taskLeft);
+ final int insetBottom = insetTop + (taskBottom - taskTop);
+ task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
- assertRect(w.mFrame, 300, 300, 700, 700);
- assertRect(w.getContentFrameLw(), 300, 300, 600, 600);
- assertRect(w.mContentInsets, 0, 0, 100, 100);
+ assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+ contentInsetRight = insetRight - cfRight;
+ contentInsetBottom = insetBottom - cfBottom;
+ assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
+ assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
+ taskBottom - contentInsetBottom);
}
@Test
@@ -289,13 +309,16 @@
new TaskWithBounds(null), FILL_PARENT, FILL_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- final Rect pf = new Rect(0, 0, 1000, 1000);
+ final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
+ final int logicalWidth = displayInfo.logicalWidth;
+ final int logicalHeight = displayInfo.logicalHeight;
+ final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
final Rect df = pf;
final Rect of = df;
final Rect cf = new Rect(pf);
// Produce some insets
- cf.top += 50;
- cf.bottom -= 100;
+ cf.top += displayInfo.logicalWidth / 10;
+ cf.bottom -= displayInfo.logicalWidth / 5;
final Rect vf = cf;
final Rect sf = vf;
// We use a decor content frame with insets to produce cropping.
@@ -308,35 +331,34 @@
// If we were above system decor we wouldnt' get any cropping though
w.mLayer = sWm.mSystemDecorLayer + 1;
w.calculatePolicyCrop(policyCrop);
- assertRect(policyCrop, 0, 0, 1000, 1000);
+ assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
w.mLayer = 1;
dcf.setEmpty();
// Likewise with no decor frame we would get no crop
w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
w.calculatePolicyCrop(policyCrop);
- assertRect(policyCrop, 0, 0, 1000, 1000);
+ assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
// Now we set up a window which doesn't fill the entire decor frame.
// Normally it would be cropped to it's frame but in the case of docked resizing
// we need to account for the fact the windows surface will be made
// fullscreen and thus also make the crop fullscreen.
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- w.mAttrs.width = 500;
- w.mAttrs.height = 500;
- w.mRequestedWidth = 500;
- w.mRequestedHeight = 500;
+ w.mAttrs.width = logicalWidth / 2;
+ w.mAttrs.height = logicalHeight / 2;
+ w.mRequestedWidth = logicalWidth / 2;
+ w.mRequestedHeight = logicalHeight / 2;
w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
w.calculatePolicyCrop(policyCrop);
// Normally the crop is shrunk from the decor frame
// to the computed window frame.
- assertRect(policyCrop, 0, 0, 500, 500);
+ assertRect(policyCrop, 0, 0, logicalWidth / 2, logicalHeight / 2);
w.mDockedResizingForTest = true;
w.calculatePolicyCrop(policyCrop);
// But if we are docked resizing it won't be, however we will still be
// shrunk to the decor frame and the display.
- final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
assertRect(policyCrop, 0, 0,
Math.min(pf.width(), displayInfo.logicalWidth),
Math.min(pf.height(), displayInfo.logicalHeight));
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 132ed98..922f08d 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -26,6 +26,7 @@
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -511,13 +512,6 @@
return actualShortcuts;
}
- public static List<ShortcutInfo> assertAllChooser(List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.isChooser());
- }
- return actualShortcuts;
- }
-
public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId(), s.isPinned());
@@ -1096,7 +1090,7 @@
public ShortcutListAsserter assertCallbackCalledForPackageAndUser(
String publisherPackageName, UserHandle publisherUserHandle) {
final ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
- verify(mCallback, times(1)).onShortcutsChanged(
+ verify(mCallback, atLeastOnce()).onShortcutsChanged(
eq(publisherPackageName),
shortcuts.capture(),
eq(publisherUserHandle));
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 68c4c56..3f39e4f 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -398,7 +398,7 @@
super(looper);
// TODO: Handle all private volumes.
mStats = new StatFs(Environment.getDataDirectory().getAbsolutePath());
- mPreviousBytes = mStats.getFreeBytes();
+ mPreviousBytes = mStats.getAvailableBytes();
mMinimumThresholdBytes = mStats.getTotalBytes() * MINIMUM_CHANGE_DELTA;
}
@@ -413,9 +413,9 @@
switch (msg.what) {
case MSG_CHECK_STORAGE_DELTA: {
- long bytesDelta = Math.abs(mPreviousBytes - mStats.getFreeBytes());
+ long bytesDelta = Math.abs(mPreviousBytes - mStats.getAvailableBytes());
if (bytesDelta > mMinimumThresholdBytes) {
- mPreviousBytes = mStats.getFreeBytes();
+ mPreviousBytes = mStats.getAvailableBytes();
recalculateQuotas(getInitializedStrategy());
}
sendEmptyMessageDelayed(MSG_CHECK_STORAGE_DELTA, DELAY_IN_MILLIS);
@@ -434,7 +434,7 @@
// If errors occurred getting the quotas from disk, let's re-calc them.
if (mPreviousBytes < 0) {
- mPreviousBytes = mStats.getFreeBytes();
+ mPreviousBytes = mStats.getAvailableBytes();
recalculateQuotas(strategy);
}
sendEmptyMessageDelayed(MSG_CHECK_STORAGE_DELTA, DELAY_IN_MILLIS);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7be2b0f..4ba457d 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -78,6 +78,7 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
@@ -1465,13 +1466,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump UsageStats from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
UsageStatsService.this.dump(args, pw);
}
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/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index a87ac9e..61e1e8f 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -40,6 +40,7 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
@@ -480,7 +481,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
final long ident = Binder.clearCallingIdentity();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 03a7db7..dc4b41c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -62,6 +62,7 @@
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
@@ -1117,13 +1118,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump voiceinteraction from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (this) {
pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)");
pw.println(" mEnableService: " + mEnableService);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 201f3ad..81f6600 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1178,6 +1178,7 @@
public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(Intent.EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
//FIXME this is using phoneId and slotIndex interchangeably
//Eventually, this should be removed as it is not the slot id
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 26c9430..8357a2b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -877,19 +877,16 @@
/**
* USSD return code success.
- * @hide
*/
public static final int USSD_RETURN_SUCCESS = 100;
/**
* USSD return code for failure case.
- * @hide
*/
public static final int USSD_RETURN_FAILURE = -1;
/**
* USSD return code for failure case.
- * @hide
*/
public static final int USSD_ERROR_SERVICE_UNAVAIL = -2;
@@ -2395,7 +2392,7 @@
* OR
* {@link android.Manifest.permission#READ_SMS}
* OR
- * {@link android.Manifest.permission#READ_PHONE_NUMBER}
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS}
* <p>
* The default SMS app can also use this.
*/
@@ -2412,7 +2409,7 @@
* OR
* {@link android.Manifest.permission#READ_SMS}
* OR
- * {@link android.Manifest.permission#READ_PHONE_NUMBER}
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS}
* <p>
* The default SMS app can also use this.
*
@@ -5113,16 +5110,32 @@
return new int[0];
}
- public static abstract class OnReceiveUssdResponseCallback {
+ /* The caller of {@link #sendUssdRequest(String, UssdResponseCallback, Handler} provides
+ * once the network returns a USSD message or if there is failure.
+ * Either {@link #onReceiveUssdResponse(TelephonyManager, String, CharSequence} or
+ * {@link #onReceiveUssdResponseFailed(TelephonyManager, String, int} will be called.
+ */
+ public static abstract class UssdResponseCallback {
/**
- ** Called when USSD has succeeded.
+ * Called when USSD has succeeded. The calling app can choose to either display the message
+ * or interpret the message.
+ * @param telephonyManager the TelephonyManager the callback is registered to.
+ * @param request the ussd code sent to the network.
+ * @param response the response from the network.
**/
- public void onReceiveUssdResponse(String request, CharSequence response) {};
+ public void onReceiveUssdResponse(final TelephonyManager telephonyManager,
+ String request, CharSequence response) {};
/**
- ** Called when USSD has failed.
+ * Called when USSD has failed.
+ * @param telephonyManager the TelephonyManager the callback is registered to
+ * @param request the ussd code.
+ * @param failureCode failure code, should be either of
+ * {@link TelephonyManager#USSD_RETURN_FAILURE} or
+ * {@link TelephonyManager#USSD_ERROR_SERVICE_UNAVAIL}.
**/
- public void onReceiveUssdResponseFailed(String request, int failureCode) {};
+ public void onReceiveUssdResponseFailed(final TelephonyManager telephonyManager,
+ String request, int failureCode) {};
}
/**
@@ -5134,13 +5147,14 @@
* {@link android.Manifest.permission#CALL_PHONE}
* @param ussdRequest the USSD command to be executed.
* @param callback called by the framework to inform the caller of the result of executing the
- * USSD request (see {@link OnReceiveUssdResponseCallback}).
+ * USSD request (see {@link UssdResponseCallback}).
* @param handler the {@link Handler} to run the request on.
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void sendUssdRequest(String ussdRequest,
- final OnReceiveUssdResponseCallback callback, Handler handler) {
- checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
+ final UssdResponseCallback callback, Handler handler) {
+ checkNotNull(callback, "UssdResponseCallback cannot be null.");
+ final TelephonyManager telephonyManager = this;
ResultReceiver wrappedCallback = new ResultReceiver(handler) {
@Override
@@ -5150,10 +5164,11 @@
UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
if (resultCode == USSD_RETURN_SUCCESS) {
- callback.onReceiveUssdResponse(response.getUssdRequest(),
+ callback.onReceiveUssdResponse(telephonyManager, response.getUssdRequest(),
response.getReturnMessage());
} else {
- callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
+ callback.onReceiveUssdResponseFailed(telephonyManager,
+ response.getUssdRequest(), resultCode);
}
}
};
@@ -5172,11 +5187,13 @@
}
}
- /*
- * @return true, if the device is currently on a technology (e.g. UMTS or LTE) which can support
- * voice and data simultaneously. This can change based on location or network condition.
- */
- public boolean isConcurrentVoiceAndDataAllowed() {
+ /**
+ * Whether the device is currently on a technology (e.g. UMTS or LTE) which can support
+ * voice and data simultaneously. This can change based on location or network condition.
+ *
+ * @return {@code true} if simultaneous voice and data supported, and {@code false} otherwise.
+ */
+ public boolean isConcurrentVoiceAndDataSupported() {
try {
ITelephony telephony = getITelephony();
return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(mSubId));
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 73ee25a..b4c531e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -334,9 +334,11 @@
* <ul>
* <li><em>subscription</em> - A int, the current default subscription.</li>
* </ul>
+ * @deprecated Use {@link Intent#ACTION_DEFAULT_SUBSCRIPTION_CHANGED}
*/
+ @Deprecated
public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
+ = Intent.ACTION_DEFAULT_SUBSCRIPTION_CHANGED;
/**
* Broadcast Action: The default data subscription has changed. This has the following
@@ -364,9 +366,11 @@
* <ul>
* <li><em>subscription</em> - A int, the current sms default subscription.</li>
* </ul>
+ * @deprecated Use {@link Intent#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED}
*/
+ @Deprecated
public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
+ = Intent.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED;
/*
* Broadcast Action: An attempt to set phone radio type and access technology has changed.
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/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index e3bc34b..c20ee12 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -33,7 +33,6 @@
import com.android.layoutlib.bridge.util.NinePatchInputStream;
import com.android.ninepatch.NinePatch;
import com.android.resources.ResourceType;
-import com.android.resources.ResourceUrl;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import com.android.util.Pair;
@@ -60,8 +59,6 @@
import java.io.InputStream;
import java.util.Iterator;
-import static com.android.SdkConstants.ANDROID_NS_NAME;
-
@SuppressWarnings("deprecation")
public class Resources_Delegate {
@@ -140,8 +137,8 @@
if (value == null) {
// Unable to resolve the attribute, just leave the unresolved value
- value = new ResourceValue(ResourceUrl.create(resourceInfo.getFirst(), attributeName,
- platformResFlag_out[0]), attributeName);
+ value = new ResourceValue(resourceInfo.getFirst(), attributeName, attributeName,
+ platformResFlag_out[0]);
}
return Pair.of(attributeName, value);
}
@@ -681,7 +678,7 @@
String packageName;
if (resourceInfo != null) {
if (platformOut[0]) {
- packageName = ANDROID_NS_NAME;
+ packageName = SdkConstants.ANDROID_NS_NAME;
} else {
packageName = resources.mContext.getPackageName();
packageName = packageName == null ? SdkConstants.APP_PREFIX : packageName;
@@ -699,7 +696,7 @@
Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, platformOut);
if (resourceInfo != null) {
if (platformOut[0]) {
- return ANDROID_NS_NAME;
+ return SdkConstants.ANDROID_NS_NAME;
}
String packageName = resources.mContext.getPackageName();
return packageName == null ? SdkConstants.APP_PREFIX : packageName;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index cc5a0c3..328fc0a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -31,7 +31,6 @@
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.Stack;
import com.android.resources.ResourceType;
-import com.android.resources.ResourceUrl;
import com.android.util.Pair;
import com.android.util.PropertiesMap;
import com.android.util.PropertiesMap.Property;
@@ -87,6 +86,7 @@
import android.view.BridgeInflater;
import android.view.Display;
import android.view.DisplayAdjustments;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -107,7 +107,6 @@
import java.util.Map;
import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1;
-import static com.android.SdkConstants.ANDROID_NS_NAME;
import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
/**
@@ -122,23 +121,20 @@
static {
FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue(
- ResourceUrl.create(ANDROID_NS_NAME, ResourceType.BOOL, "animateFirstView"),
- "false"));
- FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", new ResourceValue(
- ResourceUrl.create(ANDROID_NS_NAME, ResourceType.BOOL, "animateLayoutChanges"),
- "false"));
+ ResourceType.BOOL, "animateFirstView", "false", false));
+ FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges",
+ new ResourceValue(ResourceType.BOOL, "animateLayoutChanges", "false", false));
- FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout", new ResourceValue(
- ResourceUrl.create(ANDROID_NS_NAME, ResourceType.LAYOUT,
- "textEditSuggestionItemLayout"), "text_edit_suggestion_item"));
- FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout", new ResourceValue(
- ResourceUrl.create(ANDROID_NS_NAME, ResourceType.LAYOUT,
- "textEditSuggestionContainerLayout"), "text_edit_suggestion_container"));
- FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle", new ResourceValue(
- ResourceUrl.create(ANDROID_NS_NAME, ResourceType.STYLE,
- "textEditSuggestionHighlightStyle"),
- "TextAppearance.Holo.SuggestionHighlight"));
+ FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout",
+ new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionItemLayout",
+ "text_edit_suggestion_item", true));
+ FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout",
+ new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionContainerLayout",
+ "text_edit_suggestion_container", true));
+ FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle",
+ new ResourceValue(ResourceType.STYLE, "textEditSuggestionHighlightStyle",
+ "TextAppearance.Holo.SuggestionHighlight", true));
}
@@ -974,9 +970,7 @@
// there is a value in the XML, but we need to resolve it in case it's
// referencing another resource or a theme value.
ta.bridgeSetValue(index, attrName, frameworkAttr,
- mRenderResources.resolveResValue(new ResourceValue(
- ResourceUrl.create(ResourceType.STRING, attrName,
- isPlatformFile), value)));
+ mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
}
}
}
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java
index 00dddee..8739b7f 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java
@@ -311,7 +311,6 @@
sFrameworkRepo = null;
sProjectResources = null;
sLogger = null;
- sBridge.dispose();
sBridge = null;
TestUtils.gc();
@@ -329,7 +328,6 @@
RenderSession session = sBridge.createSession(params);
try {
-
if (frameTimeNanos != -1) {
session.setElapsedFrameTimeNanos(frameTimeNanos);
}
@@ -338,11 +336,13 @@
getLogger().error(session.getResult().getException(),
session.getResult().getErrorMessage());
}
- // Render the session with a timeout of 50s.
- Result renderResult = session.render(50000);
- if (!renderResult.isSuccess()) {
- getLogger().error(session.getResult().getException(),
- session.getResult().getErrorMessage());
+ else {
+ // Render the session with a timeout of 50s.
+ Result renderResult = session.render(50000);
+ if (!renderResult.isSuccess()) {
+ getLogger().error(session.getResult().getException(),
+ session.getResult().getErrorMessage());
+ }
}
return RenderResult.getFromSession(session);