diff options
159 files changed, 2086 insertions, 1962 deletions
diff --git a/api/current.txt b/api/current.txt index f1647d04eaf6..2f57d9a942ca 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4126,13 +4126,12 @@ package android.app { field public java.lang.String serviceDetails; } - public class AutomaticZenRule implements android.os.Parcelable { + public final class AutomaticZenRule implements android.os.Parcelable { ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean); ctor public AutomaticZenRule(android.os.Parcel); method public int describeContents(); method public android.net.Uri getConditionId(); method public long getCreationTime(); - method public java.lang.String getId(); method public int getInterruptionFilter(); method public java.lang.String getName(); method public android.content.ComponentName getOwner(); @@ -5228,14 +5227,14 @@ package android.app { } public class NotificationManager { - method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule); + method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule); method public boolean areNotificationsEnabled(); method public void cancel(int); method public void cancel(java.lang.String, int); method public void cancelAll(); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); - method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules(); + method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); method public int getImportance(); method public android.app.NotificationManager.Policy getNotificationPolicy(); @@ -5245,7 +5244,7 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); - method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule); + method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED"; @@ -6591,7 +6590,7 @@ package android.auditing { field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 } - public static class SecurityLog.SecurityEvent implements android.os.Parcelable { + public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { method public int describeContents(); method public java.lang.Object getData(); method public int getTag(); @@ -7335,15 +7334,6 @@ package android.bluetooth { field public static final int TYPE_SCO = 2; // 0x2 } - public class OobData implements android.os.Parcelable { - ctor public OobData(); - method public int describeContents(); - method public byte[] getSecurityManagerTk(); - method public void setSecurityManagerTk(byte[]); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR; - } - } package android.bluetooth.le { @@ -19708,7 +19698,7 @@ package android.media { field public static final int TYPE_WIRED_HEADSET = 3; // 0x3 } - public class AudioFormat implements android.os.Parcelable { + public final class AudioFormat implements android.os.Parcelable { method public int describeContents(); method public int getChannelCount(); method public int getChannelIndexMask(); @@ -20008,7 +19998,7 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); } - public class AudioRecordConfiguration implements android.os.Parcelable { + public final class AudioRecordConfiguration implements android.os.Parcelable { method public int describeContents(); method public android.media.AudioDeviceInfo getAudioDevice(); method public int getClientAudioSessionId(); @@ -20660,6 +20650,7 @@ package android.media { field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000 field public static final int HEVCProfileMain = 1; // 0x1 field public static final int HEVCProfileMain10 = 2; // 0x2 + field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000 field public static final int MPEG2LevelH14 = 2; // 0x2 field public static final int MPEG2LevelHL = 3; // 0x3 field public static final int MPEG2LevelLL = 0; // 0x0 @@ -22976,7 +22967,7 @@ package android.media.tv { } public static final class TvInputInfo.Builder { - ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>); + ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName); method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean); method public android.media.tv.TvInputInfo.Builder setTunerCount(int); @@ -23044,7 +23035,7 @@ package android.media.tv { ctor public TvInputService.RecordingSession(android.content.Context); method public void notifyError(int); method public void notifyRecordingStopped(android.net.Uri); - method public void notifyTuned(); + method public void notifyTuned(android.net.Uri); method public abstract void onRelease(); method public abstract void onStartRecording(android.net.Uri); method public abstract void onStopRecording(); @@ -23103,7 +23094,7 @@ package android.media.tv { method public void onDisconnected(java.lang.String); method public void onError(int); method public void onRecordingStopped(android.net.Uri); - method public void onTuned(); + method public void onTuned(android.net.Uri); } public final class TvTrackInfo implements android.os.Parcelable { @@ -23523,17 +23514,6 @@ package android.net { method public abstract void onNetworkActive(); } - public class ConnectivityMetricsEvent implements android.os.Parcelable { - ctor public ConnectivityMetricsEvent(long, int, int, android.os.Parcelable); - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent> CREATOR; - field public final int componentTag; - field public final android.os.Parcelable data; - field public final int eventTag; - field public final long timestamp; - } - public class Credentials { ctor public Credentials(int, int, int); method public int getGid(); @@ -23541,7 +23521,7 @@ package android.net { method public int getUid(); } - public class DataUsageRequest implements android.os.Parcelable { + public final class DataUsageRequest implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR; @@ -29429,7 +29409,7 @@ package android.os.storage { method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); } - public class StorageVolume implements android.os.Parcelable { + public final class StorageVolume implements android.os.Parcelable { method public android.content.Intent createAccessIntent(java.lang.String); method public int describeContents(); method public java.lang.String getDescription(android.content.Context); @@ -30262,7 +30242,7 @@ package android.provider { field public static final java.lang.String COLUMN_ID = "_id"; field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number"; - field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers"; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number"; field public static final android.net.Uri CONTENT_URI; } @@ -34553,7 +34533,7 @@ package android.service.notification { method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap); method public final void requestInterruptionFilter(int); method public final void requestListenerHints(int); - method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException; + method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException; method public final void requestUnbind() throws android.os.RemoteException; method public final void setNotificationsShown(java.lang.String[]); field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications"; @@ -36433,7 +36413,7 @@ package android.telecom { method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle); method public boolean isInCall(); method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String); - method public void launchManageBlockedNumbersActivity(); + method public deprecated void launchManageBlockedNumbersActivity(); method public void placeCall(android.net.Uri, android.os.Bundle); method public void registerPhoneAccount(android.telecom.PhoneAccount); method public void showInCallScreen(boolean); @@ -50685,6 +50665,7 @@ package java.lang { } public abstract interface Iterable { + method public default void forEach(java.util.function.Consumer<? super T>); method public abstract java.util.Iterator<T> iterator(); } @@ -54160,6 +54141,7 @@ package java.security { public abstract class Provider extends java.util.Properties { ctor protected Provider(java.lang.String, double, java.lang.String); + method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>); method public java.lang.String getInfo(); method public java.lang.String getName(); method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String); @@ -57109,6 +57091,7 @@ package java.util { ctor public ArrayList(java.util.Collection<? extends E>); method public java.lang.Object clone(); method public void ensureCapacity(int); + method public void forEach(java.util.function.Consumer<? super E>); method public E get(int); method public int size(); method public void trimToSize(); @@ -57672,6 +57655,7 @@ package java.util { ctor public HashMap(java.util.Map<? extends K, ? extends V>); method public java.lang.Object clone(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set { @@ -57696,6 +57680,7 @@ package java.util { method public boolean containsValue(java.lang.Object); method public synchronized java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public synchronized V get(java.lang.Object); method public synchronized boolean isEmpty(); method public java.util.Set<K> keySet(); @@ -57714,6 +57699,7 @@ package java.util { ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>); method public java.lang.Object clone(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } public class IllegalFormatCodePointException extends java.util.IllegalFormatException { @@ -57953,6 +57939,7 @@ package java.util { method public abstract boolean containsValue(java.lang.Object); method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public abstract boolean equals(java.lang.Object); + method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public abstract V get(java.lang.Object); method public abstract int hashCode(); method public abstract boolean isEmpty(); @@ -58414,6 +58401,7 @@ package java.util { method public K firstKey(); method public java.util.Map.Entry<K, V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public java.util.NavigableMap<K, V> headMap(K, boolean); method public java.util.SortedMap<K, V> headMap(K); method public java.util.Map.Entry<K, V> higherEntry(K); @@ -58496,6 +58484,7 @@ package java.util { method public java.util.Enumeration<E> elements(); method public synchronized void ensureCapacity(int); method public synchronized E firstElement(); + method public synchronized void forEach(java.util.function.Consumer<? super E>); method public synchronized E get(int); method public synchronized int indexOf(java.lang.Object, int); method public synchronized void insertElementAt(E, int); @@ -58519,6 +58508,7 @@ package java.util { ctor public WeakHashMap(); ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } } diff --git a/api/removed.txt b/api/removed.txt index 50a24f6dfd93..115224ce49a6 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -37,7 +37,7 @@ package android.database { package android.media { - public class AudioFormat implements android.os.Parcelable { + public final class AudioFormat implements android.os.Parcelable { ctor public AudioFormat(); } diff --git a/api/system-current.txt b/api/system-current.txt index 61a8953516c8..03e261bdf76d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4252,13 +4252,12 @@ package android.app { field public java.lang.String serviceDetails; } - public class AutomaticZenRule implements android.os.Parcelable { + public final class AutomaticZenRule implements android.os.Parcelable { ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean); ctor public AutomaticZenRule(android.os.Parcel); method public int describeContents(); method public android.net.Uri getConditionId(); method public long getCreationTime(); - method public java.lang.String getId(); method public int getInterruptionFilter(); method public java.lang.String getName(); method public android.content.ComponentName getOwner(); @@ -5360,14 +5359,14 @@ package android.app { } public class NotificationManager { - method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule); + method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule); method public boolean areNotificationsEnabled(); method public void cancel(int); method public void cancel(java.lang.String, int); method public void cancelAll(); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); - method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules(); + method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); method public int getImportance(); method public android.app.NotificationManager.Policy getNotificationPolicy(); @@ -5377,7 +5376,7 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); - method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule); + method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED"; @@ -6858,7 +6857,7 @@ package android.auditing { field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 } - public static class SecurityLog.SecurityEvent implements android.os.Parcelable { + public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { method public int describeContents(); method public java.lang.Object getData(); method public int getTag(); @@ -7610,15 +7609,6 @@ package android.bluetooth { field public static final int TYPE_SCO = 2; // 0x2 } - public class OobData implements android.os.Parcelable { - ctor public OobData(); - method public int describeContents(); - method public byte[] getSecurityManagerTk(); - method public void setSecurityManagerTk(byte[]); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR; - } - } package android.bluetooth.le { @@ -9707,25 +9697,6 @@ package android.content.pm { field public int reqTouchScreen; } - public deprecated class ContainerEncryptionParams implements android.os.Parcelable { - ctor public ContainerEncryptionParams(java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey) throws java.security.InvalidAlgorithmParameterException; - ctor public ContainerEncryptionParams(java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey, java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey, byte[], long, long, long) throws java.security.InvalidAlgorithmParameterException; - method public int describeContents(); - method public long getAuthenticatedDataStart(); - method public long getDataEnd(); - method public long getEncryptedDataStart(); - method public java.lang.String getEncryptionAlgorithm(); - method public javax.crypto.SecretKey getEncryptionKey(); - method public java.security.spec.AlgorithmParameterSpec getEncryptionSpec(); - method public java.lang.String getMacAlgorithm(); - method public javax.crypto.SecretKey getMacKey(); - method public java.security.spec.AlgorithmParameterSpec getMacSpec(); - method public byte[] getMacTag(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.content.pm.ContainerEncryptionParams> CREATOR; - field protected static final java.lang.String TAG = "ContainerEncryptionParams"; - } - public final class EphemeralResolveInfo implements android.os.Parcelable { ctor public EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>); method public int describeContents(); @@ -21204,7 +21175,7 @@ package android.media { field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR; } - public class AudioFormat implements android.os.Parcelable { + public final class AudioFormat implements android.os.Parcelable { method public int describeContents(); method public int getChannelCount(); method public int getChannelIndexMask(); @@ -21516,7 +21487,7 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); } - public class AudioRecordConfiguration implements android.os.Parcelable { + public final class AudioRecordConfiguration implements android.os.Parcelable { method public int describeContents(); method public android.media.AudioDeviceInfo getAudioDevice(); method public int getClientAudioSessionId(); @@ -22168,6 +22139,7 @@ package android.media { field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000 field public static final int HEVCProfileMain = 1; // 0x1 field public static final int HEVCProfileMain10 = 2; // 0x2 + field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000 field public static final int MPEG2LevelH14 = 2; // 0x2 field public static final int MPEG2LevelHL = 3; // 0x3 field public static final int MPEG2LevelLL = 0; // 0x0 @@ -24663,7 +24635,7 @@ package android.media.tv { } public static final class TvInputInfo.Builder { - ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>); + ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName); method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean); method public android.media.tv.TvInputInfo.Builder setHdmiDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo); @@ -24808,7 +24780,7 @@ package android.media.tv { method public void notifyError(int); method public void notifyRecordingStopped(android.net.Uri); method public void notifySessionEvent(java.lang.String, android.os.Bundle); - method public void notifyTuned(); + method public void notifyTuned(android.net.Uri); method public void onAppPrivateCommand(java.lang.String, android.os.Bundle); method public abstract void onRelease(); method public abstract void onStartRecording(android.net.Uri); @@ -24876,7 +24848,7 @@ package android.media.tv { method public void onError(int); method public void onEvent(java.lang.String, java.lang.String, android.os.Bundle); method public void onRecordingStopped(android.net.Uri); - method public void onTuned(); + method public void onTuned(android.net.Uri); } public class TvStreamConfig implements android.os.Parcelable { @@ -25344,17 +25316,6 @@ package android.net { method public void onTetheringStarted(); } - public class ConnectivityMetricsEvent implements android.os.Parcelable { - ctor public ConnectivityMetricsEvent(long, int, int, android.os.Parcelable); - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent> CREATOR; - field public final int componentTag; - field public final android.os.Parcelable data; - field public final int eventTag; - field public final long timestamp; - } - public class Credentials { ctor public Credentials(int, int, int); method public int getGid(); @@ -25362,7 +25323,7 @@ package android.net { method public int getUid(); } - public class DataUsageRequest implements android.os.Parcelable { + public final class DataUsageRequest implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR; @@ -31800,7 +31761,7 @@ package android.os.storage { method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); } - public class StorageVolume implements android.os.Parcelable { + public final class StorageVolume implements android.os.Parcelable { method public android.content.Intent createAccessIntent(java.lang.String); method public int describeContents(); method public java.lang.String getDescription(android.content.Context); @@ -32634,7 +32595,7 @@ package android.provider { field public static final java.lang.String COLUMN_ID = "_id"; field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number"; - field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers"; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number"; field public static final android.net.Uri CONTENT_URI; } @@ -37042,6 +37003,7 @@ package android.service.notification { public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService { ctor public NotificationAssistantService(); method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment); + method public final android.os.IBinder onBind(android.content.Intent); method public void onNotificationActionClick(java.lang.String, long, int); method public void onNotificationClick(java.lang.String, long); method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean); @@ -37094,7 +37056,7 @@ package android.service.notification { method public void registerAsSystemService(android.content.Context, android.content.ComponentName, int) throws android.os.RemoteException; method public final void requestInterruptionFilter(int); method public final void requestListenerHints(int); - method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException; + method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException; method public final void requestUnbind() throws android.os.RemoteException; method public final void setNotificationsShown(java.lang.String[]); method public final void setOnNotificationPostedTrim(int); @@ -39145,7 +39107,7 @@ package android.telecom { method public boolean isRinging(); method public boolean isTtySupported(); method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String); - method public void launchManageBlockedNumbersActivity(); + method public deprecated void launchManageBlockedNumbersActivity(); method public void placeCall(android.net.Uri, android.os.Bundle); method public void registerPhoneAccount(android.telecom.PhoneAccount); method public void showInCallScreen(boolean); @@ -53805,6 +53767,7 @@ package java.lang { } public abstract interface Iterable { + method public default void forEach(java.util.function.Consumer<? super T>); method public abstract java.util.Iterator<T> iterator(); } @@ -57280,6 +57243,7 @@ package java.security { public abstract class Provider extends java.util.Properties { ctor protected Provider(java.lang.String, double, java.lang.String); + method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>); method public java.lang.String getInfo(); method public java.lang.String getName(); method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String); @@ -60229,6 +60193,7 @@ package java.util { ctor public ArrayList(java.util.Collection<? extends E>); method public java.lang.Object clone(); method public void ensureCapacity(int); + method public void forEach(java.util.function.Consumer<? super E>); method public E get(int); method public int size(); method public void trimToSize(); @@ -60792,6 +60757,7 @@ package java.util { ctor public HashMap(java.util.Map<? extends K, ? extends V>); method public java.lang.Object clone(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set { @@ -60816,6 +60782,7 @@ package java.util { method public boolean containsValue(java.lang.Object); method public synchronized java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public synchronized V get(java.lang.Object); method public synchronized boolean isEmpty(); method public java.util.Set<K> keySet(); @@ -60834,6 +60801,7 @@ package java.util { ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>); method public java.lang.Object clone(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } public class IllegalFormatCodePointException extends java.util.IllegalFormatException { @@ -61073,6 +61041,7 @@ package java.util { method public abstract boolean containsValue(java.lang.Object); method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public abstract boolean equals(java.lang.Object); + method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public abstract V get(java.lang.Object); method public abstract int hashCode(); method public abstract boolean isEmpty(); @@ -61534,6 +61503,7 @@ package java.util { method public K firstKey(); method public java.util.Map.Entry<K, V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public java.util.NavigableMap<K, V> headMap(K, boolean); method public java.util.SortedMap<K, V> headMap(K); method public java.util.Map.Entry<K, V> higherEntry(K); @@ -61616,6 +61586,7 @@ package java.util { method public java.util.Enumeration<E> elements(); method public synchronized void ensureCapacity(int); method public synchronized E firstElement(); + method public synchronized void forEach(java.util.function.Consumer<? super E>); method public synchronized E get(int); method public synchronized int indexOf(java.lang.Object, int); method public synchronized void insertElementAt(E, int); @@ -61639,6 +61610,7 @@ package java.util { ctor public WeakHashMap(); ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } } diff --git a/api/system-removed.txt b/api/system-removed.txt index 7347aa3f2110..9ebc484e6dd7 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -35,7 +35,7 @@ package android.database { package android.media { - public class AudioFormat implements android.os.Parcelable { + public final class AudioFormat implements android.os.Parcelable { ctor public AudioFormat(); } diff --git a/api/test-current.txt b/api/test-current.txt index d2d470bbd274..0bf42c3e82e8 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4126,13 +4126,12 @@ package android.app { field public java.lang.String serviceDetails; } - public class AutomaticZenRule implements android.os.Parcelable { + public final class AutomaticZenRule implements android.os.Parcelable { ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean); ctor public AutomaticZenRule(android.os.Parcel); method public int describeContents(); method public android.net.Uri getConditionId(); method public long getCreationTime(); - method public java.lang.String getId(); method public int getInterruptionFilter(); method public java.lang.String getName(); method public android.content.ComponentName getOwner(); @@ -5228,14 +5227,14 @@ package android.app { } public class NotificationManager { - method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule); + method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule); method public boolean areNotificationsEnabled(); method public void cancel(int); method public void cancel(java.lang.String, int); method public void cancelAll(); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); - method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules(); + method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); method public int getImportance(); method public android.app.NotificationManager.Policy getNotificationPolicy(); @@ -5245,7 +5244,7 @@ package android.app { method public boolean removeAutomaticZenRule(java.lang.String); method public final void setInterruptionFilter(int); method public void setNotificationPolicy(android.app.NotificationManager.Policy); - method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule); + method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule); field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED"; @@ -6593,7 +6592,7 @@ package android.auditing { field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 } - public static class SecurityLog.SecurityEvent implements android.os.Parcelable { + public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { method public int describeContents(); method public java.lang.Object getData(); method public int getTag(); @@ -7337,15 +7336,6 @@ package android.bluetooth { field public static final int TYPE_SCO = 2; // 0x2 } - public class OobData implements android.os.Parcelable { - ctor public OobData(); - method public int describeContents(); - method public byte[] getSecurityManagerTk(); - method public void setSecurityManagerTk(byte[]); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR; - } - } package android.bluetooth.le { @@ -19717,7 +19707,7 @@ package android.media { field public static final int TYPE_WIRED_HEADSET = 3; // 0x3 } - public class AudioFormat implements android.os.Parcelable { + public final class AudioFormat implements android.os.Parcelable { method public int describeContents(); method public int getChannelCount(); method public int getChannelIndexMask(); @@ -20017,7 +20007,7 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); } - public class AudioRecordConfiguration implements android.os.Parcelable { + public final class AudioRecordConfiguration implements android.os.Parcelable { method public int describeContents(); method public android.media.AudioDeviceInfo getAudioDevice(); method public int getClientAudioSessionId(); @@ -20669,6 +20659,7 @@ package android.media { field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000 field public static final int HEVCProfileMain = 1; // 0x1 field public static final int HEVCProfileMain10 = 2; // 0x2 + field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000 field public static final int MPEG2LevelH14 = 2; // 0x2 field public static final int MPEG2LevelHL = 3; // 0x3 field public static final int MPEG2LevelLL = 0; // 0x0 @@ -22985,7 +22976,7 @@ package android.media.tv { } public static final class TvInputInfo.Builder { - ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>); + ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName); method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean); method public android.media.tv.TvInputInfo.Builder setTunerCount(int); @@ -23053,7 +23044,7 @@ package android.media.tv { ctor public TvInputService.RecordingSession(android.content.Context); method public void notifyError(int); method public void notifyRecordingStopped(android.net.Uri); - method public void notifyTuned(); + method public void notifyTuned(android.net.Uri); method public abstract void onRelease(); method public abstract void onStartRecording(android.net.Uri); method public abstract void onStopRecording(); @@ -23112,7 +23103,7 @@ package android.media.tv { method public void onDisconnected(java.lang.String); method public void onError(int); method public void onRecordingStopped(android.net.Uri); - method public void onTuned(); + method public void onTuned(android.net.Uri); } public final class TvTrackInfo implements android.os.Parcelable { @@ -23532,17 +23523,6 @@ package android.net { method public abstract void onNetworkActive(); } - public class ConnectivityMetricsEvent implements android.os.Parcelable { - ctor public ConnectivityMetricsEvent(long, int, int, android.os.Parcelable); - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent> CREATOR; - field public final int componentTag; - field public final android.os.Parcelable data; - field public final int eventTag; - field public final long timestamp; - } - public class Credentials { ctor public Credentials(int, int, int); method public int getGid(); @@ -23550,7 +23530,7 @@ package android.net { method public int getUid(); } - public class DataUsageRequest implements android.os.Parcelable { + public final class DataUsageRequest implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR; @@ -29439,7 +29419,7 @@ package android.os.storage { method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); } - public class StorageVolume implements android.os.Parcelable { + public final class StorageVolume implements android.os.Parcelable { method public android.content.Intent createAccessIntent(java.lang.String); method public int describeContents(); method public java.lang.String getDescription(android.content.Context); @@ -30275,7 +30255,7 @@ package android.provider { field public static final java.lang.String COLUMN_ID = "_id"; field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number"; field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number"; - field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers"; + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number"; field public static final android.net.Uri CONTENT_URI; } @@ -34568,7 +34548,7 @@ package android.service.notification { method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap); method public final void requestInterruptionFilter(int); method public final void requestListenerHints(int); - method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException; + method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException; method public final void requestUnbind() throws android.os.RemoteException; method public final void setNotificationsShown(java.lang.String[]); field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications"; @@ -36448,7 +36428,7 @@ package android.telecom { method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle); method public boolean isInCall(); method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String); - method public void launchManageBlockedNumbersActivity(); + method public deprecated void launchManageBlockedNumbersActivity(); method public void placeCall(android.net.Uri, android.os.Bundle); method public void registerPhoneAccount(android.telecom.PhoneAccount); method public void showInCallScreen(boolean); @@ -50702,6 +50682,7 @@ package java.lang { } public abstract interface Iterable { + method public default void forEach(java.util.function.Consumer<? super T>); method public abstract java.util.Iterator<T> iterator(); } @@ -54177,6 +54158,7 @@ package java.security { public abstract class Provider extends java.util.Properties { ctor protected Provider(java.lang.String, double, java.lang.String); + method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>); method public java.lang.String getInfo(); method public java.lang.String getName(); method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String); @@ -57126,6 +57108,7 @@ package java.util { ctor public ArrayList(java.util.Collection<? extends E>); method public java.lang.Object clone(); method public void ensureCapacity(int); + method public void forEach(java.util.function.Consumer<? super E>); method public E get(int); method public int size(); method public void trimToSize(); @@ -57689,6 +57672,7 @@ package java.util { ctor public HashMap(java.util.Map<? extends K, ? extends V>); method public java.lang.Object clone(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set { @@ -57713,6 +57697,7 @@ package java.util { method public boolean containsValue(java.lang.Object); method public synchronized java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public synchronized V get(java.lang.Object); method public synchronized boolean isEmpty(); method public java.util.Set<K> keySet(); @@ -57731,6 +57716,7 @@ package java.util { ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>); method public java.lang.Object clone(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } public class IllegalFormatCodePointException extends java.util.IllegalFormatException { @@ -57970,6 +57956,7 @@ package java.util { method public abstract boolean containsValue(java.lang.Object); method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public abstract boolean equals(java.lang.Object); + method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public abstract V get(java.lang.Object); method public abstract int hashCode(); method public abstract boolean isEmpty(); @@ -58431,6 +58418,7 @@ package java.util { method public K firstKey(); method public java.util.Map.Entry<K, V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public java.util.NavigableMap<K, V> headMap(K, boolean); method public java.util.SortedMap<K, V> headMap(K); method public java.util.Map.Entry<K, V> higherEntry(K); @@ -58513,6 +58501,7 @@ package java.util { method public java.util.Enumeration<E> elements(); method public synchronized void ensureCapacity(int); method public synchronized E firstElement(); + method public synchronized void forEach(java.util.function.Consumer<? super E>); method public synchronized E get(int); method public synchronized int indexOf(java.lang.Object, int); method public synchronized void insertElementAt(E, int); @@ -58536,6 +58525,7 @@ package java.util { ctor public WeakHashMap(); ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); } } diff --git a/api/test-removed.txt b/api/test-removed.txt index 50a24f6dfd93..115224ce49a6 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -37,7 +37,7 @@ package android.database { package android.media { - public class AudioFormat implements android.os.Parcelable { + public final class AudioFormat implements android.os.Parcelable { ctor public AudioFormat(); } diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index eedb82bd5d0a..df0e5fc6f1bb 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -1216,6 +1216,7 @@ public class Am extends BaseCommand { class MyActivityController extends IActivityController.Stub { final String mGdbPort; + final boolean mMonkey; static final int STATE_NORMAL = 0; static final int STATE_CRASHED = 1; @@ -1242,8 +1243,9 @@ public class Am extends BaseCommand { Thread mGdbThread; boolean mGotGdbPrint; - MyActivityController(String gdbPort) { + MyActivityController(String gdbPort, boolean monkey) { mGdbPort = gdbPort; + mMonkey = monkey; } @Override @@ -1443,7 +1445,7 @@ public class Am extends BaseCommand { try { printMessageForState(); - mAm.setActivityController(this); + mAm.setActivityController(this, mMonkey); mState = STATE_NORMAL; InputStreamReader converter = new InputStreamReader(System.in); @@ -1498,7 +1500,7 @@ public class Am extends BaseCommand { } catch (IOException e) { e.printStackTrace(); } finally { - mAm.setActivityController(null); + mAm.setActivityController(null, mMonkey); } } } @@ -1506,16 +1508,19 @@ public class Am extends BaseCommand { private void runMonitor() throws Exception { String opt; String gdbPort = null; + boolean monkey = false; while ((opt=nextOption()) != null) { if (opt.equals("--gdb")) { gdbPort = nextArgRequired(); + } else if (opt.equals("-m")) { + monkey = true; } else { System.err.println("Error: Unknown option: " + opt); return; } } - MyActivityController controller = new MyActivityController(gdbPort); + MyActivityController controller = new MyActivityController(gdbPort, monkey); controller.run(); } diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java index 1fa9bacc10cb..ddeb8e786271 100644 --- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java +++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java @@ -50,9 +50,9 @@ public class UiAutomationShellWrapper { } try { if (isSet) { - am.setActivityController(new DummyActivityController()); + am.setActivityController(new DummyActivityController(), true); } else { - am.setActivityController(null); + am.setActivityController(null, true); } } catch (RemoteException e) { throw new RuntimeException(e); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 32751b2b47fe..be89b20c91c5 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -41,6 +41,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; @@ -68,6 +69,7 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.StrictMode; +import android.os.SystemProperties; import android.os.UserHandle; import android.text.Selection; import android.text.SpannableStringBuilder; @@ -110,6 +112,7 @@ import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.widget.AdapterView; +import android.widget.Toast; import android.widget.Toolbar; import com.android.internal.app.IVoiceInteractor; @@ -832,6 +835,8 @@ public class Activity extends ContextThemeWrapper private boolean mHasCurrentPermissionsRequest; private boolean mEatKeyUpEvent; + private static native String getDlWarning(); + /** Return the intent that started this activity. */ public Intent getIntent() { return mIntent; @@ -1119,34 +1124,6 @@ public class Activity extends ContextThemeWrapper } /** - * Attempts to extract the color from a given drawable. - * - * @return the extracted color or 0 if no color could be extracted. - */ - private int tryExtractColorFromDrawable(Drawable drawable) { - if (drawable instanceof ColorDrawable) { - return ((ColorDrawable) drawable).getColor(); - } else if (drawable instanceof InsetDrawable) { - return tryExtractColorFromDrawable(((InsetDrawable) drawable).getDrawable()); - } else if (drawable instanceof ShapeDrawable) { - Paint p = ((ShapeDrawable) drawable).getPaint(); - if (p != null) { - return p.getColor(); - } - } else if (drawable instanceof LayerDrawable) { - LayerDrawable ld = (LayerDrawable) drawable; - int numLayers = ld.getNumberOfLayers(); - for (int i = 0; i < numLayers; i++) { - int color = tryExtractColorFromDrawable(ld.getDrawable(i)); - if (color != 0) { - return color; - } - } - } - return 0; - } - - /** * Called when activity start-up is complete (after {@link #onStart} * and {@link #onRestoreInstanceState} have been called). Applications will * generally not implement this method; it is intended for system @@ -1168,35 +1145,6 @@ public class Activity extends ContextThemeWrapper onTitleChanged(getTitle(), getTitleColor()); } - Resources.Theme theme = getTheme(); - if (theme != null) { - // Get the primary color and update the TaskDescription for this activity - TypedArray a = theme.obtainStyledAttributes( - com.android.internal.R.styleable.ActivityTaskDescription); - if (mTaskDescription.getPrimaryColor() == 0) { - int colorPrimary = a.getColor( - com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0); - if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) { - mTaskDescription.setPrimaryColor(colorPrimary); - } - } - if (mTaskDescription.getBackgroundColor() == 0) { - int windowBgResourceId = a.getResourceId( - com.android.internal.R.styleable.ActivityTaskDescription_windowBackground, - 0); - int windowBgFallbackResourceId = a.getResourceId( - com.android.internal.R.styleable.ActivityTaskDescription_windowBackgroundFallback, - 0); - int colorBg = tryExtractColorFromDrawable(DecorView.getResizingBackgroundDrawable( - this, windowBgResourceId, windowBgFallbackResourceId)); - if (colorBg != 0 && Color.alpha(colorBg) == 0xFF) { - mTaskDescription.setBackgroundColor(colorBg); - } - } - a.recycle(); - setTaskDescription(mTaskDescription); - } - mCalled = true; } @@ -4036,6 +3984,27 @@ public class Activity extends ContextThemeWrapper } theme.applyStyle(resid, false); } + + // Get the primary color and update the TaskDescription for this activity + TypedArray a = theme.obtainStyledAttributes( + com.android.internal.R.styleable.ActivityTaskDescription); + if (mTaskDescription.getPrimaryColor() == 0) { + int colorPrimary = a.getColor( + com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0); + if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) { + mTaskDescription.setPrimaryColor(colorPrimary); + } + } + // For dev-preview only. + if (mTaskDescription.getBackgroundColor() == 0) { + int colorBackground = a.getColor( + com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0); + if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) { + mTaskDescription.setBackgroundColor(colorBackground); + } + } + a.recycle(); + setTaskDescription(mTaskDescription); } /** @@ -6621,6 +6590,31 @@ public class Activity extends ContextThemeWrapper } mFragments.dispatchStart(); mFragments.reportLoaderStart(); + + // This property is set for all builds except final release + boolean isDlwarningEnabled = SystemProperties.getInt("ro.bionic.ld.warning", 0) == 1; + boolean isAppDebuggable = + (mApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + + if (isAppDebuggable || isDlwarningEnabled) { + String dlwarning = getDlWarning(); + if (dlwarning != null) { + String appName = getString(mApplication.getApplicationInfo().labelRes); + String warning = "Detected problems with app native libraries\n" + + "(please consult log for detail):\n" + dlwarning; + if (isAppDebuggable) { + new AlertDialog.Builder(this). + setTitle(appName). + setMessage(warning). + setPositiveButton(android.R.string.ok, null). + setCancelable(false). + show(); + } else { + Toast.makeText(this, appName + "\n" + warning, Toast.LENGTH_LONG).show(); + } + } + } + mActivityTransitionState.enterReady(this); } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index a1f82dea9542..b264e8ec6993 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1527,7 +1527,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); IActivityController watcher = IActivityController.Stub.asInterface( data.readStrongBinder()); - setActivityController(watcher); + boolean imAMonkey = data.readInt() != 0; + setActivityController(watcher, imAMonkey); reply.writeNoException(); return true; } @@ -4860,12 +4861,14 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - public void setActivityController(IActivityController watcher) throws RemoteException + public void setActivityController(IActivityController watcher, boolean imAMonkey) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(watcher != null ? watcher.asBinder() : null); + data.writeInt(imAMonkey ? 1 : 0); mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f2a8ea5eb148..e41b7920a401 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -175,6 +175,7 @@ public final class ActivityThread { private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; private static final int LOG_AM_ON_PAUSE_CALLED = 30021; private static final int LOG_AM_ON_RESUME_CALLED = 30022; + private static final int LOG_AM_ON_STOP_CALLED = 30049; /** Type for IActivityManager.serviceDoneExecuting: anonymous operation */ public static final int SERVICE_DONE_EXECUTING_ANON = 0; @@ -1407,7 +1408,7 @@ public final class ActivityThread { r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); - handleLaunchActivity(r, null); + handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case RELAUNCH_ACTIVITY: { @@ -1458,7 +1459,7 @@ public final class ActivityThread { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume"); SomeArgs args = (SomeArgs) msg.obj; handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true, - args.argi3); + args.argi3, "RESUME_ACTIVITY"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case SEND_RESULT: @@ -2631,7 +2632,7 @@ public final class ActivityThread { return baseContext; } - private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { + private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -2658,7 +2659,7 @@ public final class ActivityThread { reportSizeConfigurations(r); Bundle oldState = r.state; handleResumeActivity(r.token, false, r.isForward, - !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq); + !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); if (!r.activity.mFinished && r.startsNotResumed) { // The activity manager actually wants this one to start out @@ -2673,6 +2674,8 @@ public final class ActivityThread { try { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); + EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(), + r.activity.getComponentName().getClassName(), reason); // We need to keep around the original state, in case // we need to be created again. But we only do this // for pre-Honeycomb apps, which always save their state @@ -3320,7 +3323,7 @@ public final class ActivityThread { } public final ActivityClientRecord performResumeActivity(IBinder token, - boolean clearHide) { + boolean clearHide, String reason) { ActivityClientRecord r = mActivities.get(token); if (localLOGV) Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished); @@ -3342,8 +3345,8 @@ public final class ActivityThread { } r.activity.performResume(); - EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, - UserHandle.myUserId(), r.activity.getComponentName().getClassName()); + EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(), + r.activity.getComponentName().getClassName(), reason); r.paused = false; r.stopped = false; @@ -3379,7 +3382,7 @@ public final class ActivityThread { } final void handleResumeActivity(IBinder token, - boolean clearHide, boolean isForward, boolean reallyResume, int seq) { + boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { ActivityClientRecord r = mActivities.get(token); if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) { return; @@ -3391,7 +3394,7 @@ public final class ActivityThread { mSomeActivitiesChanged = true; // TODO Push resumeArgs into the activity for consideration - r = performResumeActivity(token, clearHide); + r = performResumeActivity(token, clearHide, reason); if (r != null) { final Activity a = r.activity; @@ -3583,7 +3586,7 @@ public final class ActivityThread { } r.activity.mConfigChangeFlags |= configChanges; - performPauseActivity(token, finished, r.isPreHoneycomb()); + performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity"); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { @@ -3607,13 +3610,13 @@ public final class ActivityThread { } final Bundle performPauseActivity(IBinder token, boolean finished, - boolean saveState) { + boolean saveState, String reason) { ActivityClientRecord r = mActivities.get(token); - return r != null ? performPauseActivity(r, finished, saveState) : null; + return r != null ? performPauseActivity(r, finished, saveState, reason) : null; } final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, - boolean saveState) { + boolean saveState, String reason) { if (r.paused) { if (r.activity.mFinished) { // If we are finishing, we won't call onResume() in certain cases. @@ -3638,7 +3641,7 @@ public final class ActivityThread { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName()); + r.activity.getComponentName().getClassName(), reason); if (!r.activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + @@ -3671,9 +3674,9 @@ public final class ActivityThread { return !r.activity.mFinished && saveState ? r.state : null; } - final void performStopActivity(IBinder token, boolean saveState) { + final void performStopActivity(IBinder token, boolean saveState, String reason) { ActivityClientRecord r = mActivities.get(token); - performStopActivityInner(r, null, false, saveState); + performStopActivityInner(r, null, false, saveState, reason); } private static class StopInfo implements Runnable { @@ -3690,8 +3693,8 @@ public final class ActivityThread { activity.token, state, persistentState, description); } catch (RemoteException ex) { if (ex instanceof TransactionTooLargeException - && "com.google.android.gms".equals(activity.packageInfo.getPackageName())) { - Log.d(TAG, "STAHP SENDING SO MUCH DATA KTHX: " + ex); + && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) { + Log.e(TAG, "App tried sending too much data in instance state", ex); return; } @@ -3731,7 +3734,7 @@ public final class ActivityThread { * the activity's UI visibillity changes. */ private void performStopActivityInner(ActivityClientRecord r, - StopInfo info, boolean keepShown, boolean saveState) { + StopInfo info, boolean keepShown, boolean saveState, String reason) { if (localLOGV) Slog.v(TAG, "Performing stop of " + r); if (r != null) { if (!keepShown && r.stopped) { @@ -3783,6 +3786,8 @@ public final class ActivityThread { } } r.stopped = true; + EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), + r.activity.getComponentName().getClassName(), reason); } r.paused = true; @@ -3829,7 +3834,7 @@ public final class ActivityThread { r.activity.mConfigChangeFlags |= configChanges; StopInfo info = new StopInfo(); - performStopActivityInner(r, info, show, true); + performStopActivityInner(r, info, show, true, "handleStopActivity"); if (localLOGV) Slog.v( TAG, "Finishing stop of " + r + ": show=" + show @@ -3885,7 +3890,7 @@ public final class ActivityThread { } if (!show && !r.stopped) { - performStopActivityInner(r, null, show, false); + performStopActivityInner(r, null, show, false, "handleWindowVisibility"); } else if (show && r.stopped) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. @@ -3924,6 +3929,8 @@ public final class ActivityThread { } } r.stopped = true; + EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), + r.activity.getComponentName().getClassName(), "sleeping"); } // Make sure any pending writes are now committed. @@ -4065,7 +4072,7 @@ public final class ActivityThread { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(), - r.activity.getComponentName().getClassName()); + r.activity.getComponentName().getClassName(), "destroy"); if (!r.activity.mCalled) { throw new SuperNotCalledException( "Activity " + safeToComponentShortString(r.intent) @@ -4097,6 +4104,8 @@ public final class ActivityThread { } } r.stopped = true; + EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(), + r.activity.getComponentName().getClassName(), "destroy"); } if (getNonConfigInstance) { try { @@ -4396,7 +4405,7 @@ public final class ActivityThread { // Need to ensure state is saved. if (!r.paused) { - performPauseActivity(r.token, false, r.isPreHoneycomb()); + performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity"); } if (r.state == null && !r.stopped && !r.isPreHoneycomb()) { callCallActivityOnSaveInstanceState(r); @@ -4426,7 +4435,7 @@ public final class ActivityThread { r.startsNotResumed = tmp.startsNotResumed; r.overrideConfig = tmp.overrideConfig; - handleLaunchActivity(r, currentIntent); + handleLaunchActivity(r, currentIntent, "handleRelaunchActivity"); if (!tmp.onlyLocalRequest) { try { @@ -4804,8 +4813,9 @@ public final class ActivityThread { // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp). private static File getPrimaryProfileFile(String packageName) { - return new File("/data/misc/profiles/cur/" + UserHandle.myUserId() + - "/" + packageName + "/primary.prof"); + File profileDir = Environment.getDataProfilesDePackageDirectory( + UserHandle.myUserId(), packageName); + return new File(profileDir, "primary.prof"); } private static void setupJitProfileSupport(LoadedApk loadedApk, File cacheDir) { @@ -4848,8 +4858,17 @@ public final class ActivityThread { } } + final File foreignDexProfilesFile = + Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId()); + String foreignDexProfilesPath = null; + if (!foreignDexProfilesFile.exists()) { + Log.v(TAG, "ForeignDexProfilesPath does not exists:" + + foreignDexProfilesFile.getPath()); + } else { + foreignDexProfilesPath = foreignDexProfilesFile.getAbsolutePath(); + } VMRuntime.registerAppInfo(profileFile.getAbsolutePath(), appInfo.dataDir, - codePaths.toArray(new String[codePaths.size()])); + codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesPath); } private void updateDefaultDensity() { diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 9d1dfdd24a88..82c4c51b6a04 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -704,8 +704,8 @@ public class AppOpsManager { * (and system ui) to bypass the user restriction when active. */ private static boolean[] sOpAllowSystemRestrictionBypass = new boolean[] { - false, //COARSE_LOCATION - false, //FINE_LOCATION + true, //COARSE_LOCATION + true, //FINE_LOCATION false, //GPS false, //VIBRATE false, //READ_CONTACTS diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 4d466d34a79c..53cc9caf5a2f 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -30,7 +30,6 @@ import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; -import android.content.pm.ContainerEncryptionParams; import android.content.pm.EphemeralApplicationInfo; import android.content.pm.FeatureInfo; import android.content.pm.IOnPermissionsChangeListener; @@ -54,7 +53,6 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; -import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -1469,80 +1467,27 @@ public class ApplicationPackageManager extends PackageManager { @Override public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName) { - final VerificationParams verificationParams = new VerificationParams(null, null, - null, VerificationParams.NO_UID); installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags, - installerPackageName, verificationParams, null, mContext.getUserId()); - } - - @Override - public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, - int flags, String installerPackageName, Uri verificationURI, - ContainerEncryptionParams encryptionParams) { - final VerificationParams verificationParams = new VerificationParams(verificationURI, null, - null, VerificationParams.NO_UID); - installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags, - installerPackageName, verificationParams, encryptionParams, mContext.getUserId()); - } - - @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, - IPackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { - installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags, - installerPackageName, verificationParams, encryptionParams, mContext.getUserId()); + installerPackageName, mContext.getUserId()); } @Override public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags, String installerPackageName) { - installPackageAsUser(packageURI, observer, flags, installerPackageName, - mContext.getUserId()); - } - - @Override - public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer, int flags, - String installerPackageName, int userId) { - final VerificationParams verificationParams = new VerificationParams(null, null, - null, VerificationParams.NO_UID); - installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null, - userId); - } - - @Override - public void installPackageWithVerification(Uri packageURI, - PackageInstallObserver observer, int flags, String installerPackageName, - Uri verificationURI, - ContainerEncryptionParams encryptionParams) { - final VerificationParams verificationParams = new VerificationParams(verificationURI, null, - null, VerificationParams.NO_UID); - installCommon(packageURI, observer, flags, installerPackageName, verificationParams, - encryptionParams, mContext.getUserId()); - } - - @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, - PackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { - installCommon(packageURI, observer, flags, installerPackageName, verificationParams, - encryptionParams, mContext.getUserId()); + installCommon(packageURI, observer, flags, installerPackageName, mContext.getUserId()); } private void installCommon(Uri packageURI, PackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams, int userId) { if (!"file".equals(packageURI.getScheme())) { throw new UnsupportedOperationException("Only file:// URIs are supported"); } - if (encryptionParams != null) { - throw new UnsupportedOperationException("ContainerEncryptionParams not supported"); - } final String originPath = packageURI.getPath(); try { mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName, - verificationParams, null, userId); + userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java index b7eaf3947a42..1f1f318be5c1 100644 --- a/core/java/android/app/AutomaticZenRule.java +++ b/core/java/android/app/AutomaticZenRule.java @@ -27,14 +27,13 @@ import java.util.Objects; /** * Rule instance information for zen mode. */ -public class AutomaticZenRule implements Parcelable { +public final class AutomaticZenRule implements Parcelable { private boolean enabled = false; private String name; private @InterruptionFilter int interruptionFilter; private Uri conditionId; private ComponentName owner; - private String id; private long creationTime; /** @@ -63,9 +62,8 @@ public class AutomaticZenRule implements Parcelable { * @hide */ public AutomaticZenRule(String name, ComponentName owner, Uri conditionId, - int interruptionFilter, boolean enabled, String id, long creationTime) { + int interruptionFilter, boolean enabled, long creationTime) { this(name, owner, conditionId, interruptionFilter, enabled); - this.id = id; this.creationTime = creationTime; } @@ -77,9 +75,6 @@ public class AutomaticZenRule implements Parcelable { interruptionFilter = source.readInt(); conditionId = source.readParcelable(null); owner = source.readParcelable(null); - if (source.readInt() == 1) { - id = source.readString(); - } creationTime = source.readLong(); } @@ -119,20 +114,13 @@ public class AutomaticZenRule implements Parcelable { } /** - * Returns the wall time in milliseconds when this rule was created, if known. + * Returns the time this rule was created, represented as milliseconds since the epoch. */ public long getCreationTime() { return creationTime; } /** - * Returns the unique identifier for this rule. - */ - public String getId() { - return id; - } - - /** * Sets the representation of the state that causes this rule to become active. */ public void setConditionId(Uri conditionId) { @@ -178,12 +166,6 @@ public class AutomaticZenRule implements Parcelable { dest.writeInt(interruptionFilter); dest.writeParcelable(conditionId, 0); dest.writeParcelable(owner, 0); - if (id != null) { - dest.writeInt(1); - dest.writeString(id); - } else { - dest.writeInt(0); - } dest.writeLong(creationTime); } @@ -195,7 +177,6 @@ public class AutomaticZenRule implements Parcelable { .append(",interruptionFilter=").append(interruptionFilter) .append(",conditionId=").append(conditionId) .append(",owner=").append(owner) - .append(",id=").append(id) .append(",creationTime=").append(creationTime) .append(']').toString(); } @@ -210,13 +191,12 @@ public class AutomaticZenRule implements Parcelable { && other.interruptionFilter == interruptionFilter && Objects.equals(other.conditionId, conditionId) && Objects.equals(other.owner, owner) - && Objects.equals(other.id, id) && other.creationTime == creationTime; } @Override public int hashCode() { - return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, id, creationTime); + return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, creationTime); } public static final Parcelable.Creator<AutomaticZenRule> CREATOR diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 4b0dfc7e0a8b..3a51aff37921 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -16,8 +16,6 @@ package android.app; -import com.android.internal.util.FastPrintWriter; - import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; @@ -33,6 +31,8 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import com.android.internal.util.FastPrintWriter; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -717,10 +717,12 @@ final class BackStackRecord extends FragmentTransaction implements bumpBackStackNesting(1); - SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); - SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); - calculateFragments(firstOutFragments, lastInFragments); - beginTransition(firstOutFragments, lastInFragments, false); + if (mManager.mCurState >= Fragment.CREATED) { + SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); + SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); + calculateFragments(firstOutFragments, lastInFragments); + beginTransition(firstOutFragments, lastInFragments, false); + } Op op = mHead; while (op != null) { @@ -842,6 +844,14 @@ final class BackStackRecord extends FragmentTransaction implements firstOutFragments.remove(containerId); } } + /** + * Ensure that fragments that are entering are at least at the CREATED state + * so that they may load Transitions using TransitionInflater. + */ + if (fragment.mState < Fragment.CREATED && mManager.mCurState >= Fragment.CREATED) { + mManager.makeActive(fragment); + mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false); + } } } @@ -986,7 +996,6 @@ final class BackStackRecord extends FragmentTransaction implements */ private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments, boolean isBack) { - ensureFragmentsAreInitialized(lastInFragments); TransitionState state = new TransitionState(); // Adding a non-existent target view makes sure that the transitions don't target @@ -1012,21 +1021,6 @@ final class BackStackRecord extends FragmentTransaction implements return state; } - /** - * Ensure that fragments that are entering are at least at the CREATED state - * so that they may load Transitions using TransitionInflater. - */ - private void ensureFragmentsAreInitialized(SparseArray<Fragment> lastInFragments) { - final int count = lastInFragments.size(); - for (int i = 0; i < count; i++) { - final Fragment fragment = lastInFragments.valueAt(i); - if (fragment.mState < Fragment.CREATED) { - mManager.makeActive(fragment); - mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false); - } - } - } - private static Transition cloneTransition(Transition transition) { if (transition != null) { transition = transition.clone(); @@ -1663,12 +1657,14 @@ final class BackStackRecord extends FragmentTransaction implements pw.flush(); } - if (state == null) { - if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) { - state = beginTransition(firstOutFragments, lastInFragments, true); + if (mManager.mCurState >= Fragment.CREATED) { + if (state == null) { + if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) { + state = beginTransition(firstOutFragments, lastInFragments, true); + } + } else if (!doStateMove) { + setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames); } - } else if (!doStateMove) { - setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames); } bumpBackStackNesting(-1); diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index aafb3c638a65..6870bbff48c7 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -2509,6 +2509,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onDestroy()"); } + mChildFragmentManager = null; } private static Transition loadTransition(Context context, TypedArray typedArray, diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 78a054b3a717..063194310e77 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1525,7 +1525,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate throw new IllegalStateException("Must be called from main thread of fragment host"); } - if (allowStateLoss) { + if (!allowStateLoss) { checkStateLoss(); } @@ -1625,7 +1625,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate final BackStackRecord bss = mBackStack.remove(last); SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); - bss.calculateBackFragments(firstOutFragments, lastInFragments); + if (mCurState >= Fragment.CREATED) { + bss.calculateBackFragments(firstOutFragments, lastInFragments); + } bss.popFromBackStack(true, null, firstOutFragments, lastInFragments); reportBackStackChanged(); } else { @@ -1672,8 +1674,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate final int LAST = states.size()-1; SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); - for (int i=0; i<=LAST; i++) { - states.get(i).calculateBackFragments(firstOutFragments, lastInFragments); + if (mCurState >= Fragment.CREATED) { + for (int i = 0; i <= LAST; i++) { + states.get(i).calculateBackFragments(firstOutFragments, lastInFragments); + } } BackStackRecord.TransitionState state = null; for (int i=0; i<=LAST; i++) { diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 2cb615103024..4bfd049fca75 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -305,7 +305,7 @@ public interface IActivityManager extends IInterface { String packageName, boolean waitForDebugger, boolean persistent) throws RemoteException; public void setAlwaysFinish(boolean enabled) throws RemoteException; - public void setActivityController(IActivityController watcher) + public void setActivityController(IActivityController watcher, boolean imAMonkey) throws RemoteException; public void setLenientBackgroundCheck(boolean enabled) throws RemoteException; public int getMemoryTrimLevel() throws RemoteException; diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 8be00aa50ca3..569792438f23 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -97,9 +97,9 @@ interface INotificationManager boolean isNotificationPolicyAccessGrantedForPackage(String pkg); void setNotificationPolicyAccessGranted(String pkg, boolean granted); AutomaticZenRule getAutomaticZenRule(String id); - List<AutomaticZenRule> getAutomaticZenRules(); - AutomaticZenRule addAutomaticZenRule(in AutomaticZenRule automaticZenRule); - boolean updateAutomaticZenRule(in AutomaticZenRule automaticZenRule); + List<ZenModeConfig.ZenRule> getZenRules(); + String addAutomaticZenRule(in AutomaticZenRule automaticZenRule); + boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule); boolean removeAutomaticZenRule(String id); boolean removeAutomaticZenRules(String packageName); int getRuleInstanceCount(in ComponentName owner); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 06fe515c22db..b65faa98cdca 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -382,7 +382,7 @@ public final class LoadedApk { String libraryPermittedPath = mDataDir; boolean isBundledApp = false; - if (mApplicationInfo.isSystemApp()) { + if (mApplicationInfo.isSystemApp() && !mApplicationInfo.isUpdatedSystemApp()) { isBundledApp = true; // Add path to system libraries to libPaths; // Access to system libs should be limited diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index 873e3373d80d..2a1e3c250a00 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -144,7 +144,7 @@ public class LocalActivityManager { if (desiredState == RESUMED) { if (localLOGV) Log.v(TAG, r.id + ": resuming"); - mActivityThread.performResumeActivity(r, true); + mActivityThread.performResumeActivity(r, true, "moveToState-INITIALIZING"); r.curState = RESUMED; } @@ -167,7 +167,7 @@ public class LocalActivityManager { if (desiredState == RESUMED) { if (localLOGV) Log.v(TAG, r.id + ": restarting and resuming"); mActivityThread.performRestartActivity(r); - mActivityThread.performResumeActivity(r, true); + mActivityThread.performResumeActivity(r, true, "moveToState-CREATED"); r.curState = RESUMED; } return; @@ -176,13 +176,13 @@ public class LocalActivityManager { if (desiredState == RESUMED) { // Need to resume it... if (localLOGV) Log.v(TAG, r.id + ": resuming"); - mActivityThread.performResumeActivity(r, true); + mActivityThread.performResumeActivity(r, true, "moveToState-STARTED"); r.instanceState = null; r.curState = RESUMED; } if (desiredState == CREATED) { if (localLOGV) Log.v(TAG, r.id + ": stopping"); - mActivityThread.performStopActivity(r, false); + mActivityThread.performStopActivity(r, false, "moveToState-STARTED"); r.curState = CREATED; } return; @@ -197,7 +197,7 @@ public class LocalActivityManager { if (localLOGV) Log.v(TAG, r.id + ": pausing"); performPause(r, mFinishing); if (localLOGV) Log.v(TAG, r.id + ": stopping"); - mActivityThread.performStopActivity(r, false); + mActivityThread.performStopActivity(r, false, "moveToState-RESUMED"); r.curState = CREATED; } return; @@ -205,9 +205,9 @@ public class LocalActivityManager { } private void performPause(LocalActivityRecord r, boolean finishing) { - boolean needState = r.instanceState == null; - Bundle instanceState = mActivityThread.performPauseActivity(r, - finishing, needState); + final boolean needState = r.instanceState == null; + final Bundle instanceState = mActivityThread.performPauseActivity( + r, finishing, needState, "performPause"); if (needState) { r.instanceState = instanceState; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 344315d5266f..b6448ee06db4 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -48,8 +48,12 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.List; +import java.util.Set; /** * Class to notify the user of events that happen. This is how you tell @@ -413,13 +417,20 @@ public class NotificationManager * Returns AutomaticZenRules owned by the caller. * * <p> - * Only available if policy access is granted to this package. + * Throws a SecurityException if policy access is granted to this package. * See {@link #isNotificationPolicyAccessGranted}. */ - public List<AutomaticZenRule> getAutomaticZenRules() { + public Map<String, AutomaticZenRule> getAutomaticZenRules() { INotificationManager service = getService(); try { - return service.getAutomaticZenRules(); + List<ZenModeConfig.ZenRule> rules = service.getZenRules(); + Map<String, AutomaticZenRule> ruleMap = new HashMap<>(); + for (ZenModeConfig.ZenRule rule : rules) { + ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component, + rule.conditionId, zenModeToInterruptionFilter(rule.zenMode), rule.enabled, + rule.creationTime)); + } + return ruleMap; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -429,7 +440,7 @@ public class NotificationManager * Returns the AutomaticZenRule with the given id, if it exists and the caller has access. * * <p> - * Only available if policy access is granted to this package. + * Throws a SecurityException if policy access is granted to this package. * See {@link #isNotificationPolicyAccessGranted}. * * <p> @@ -449,14 +460,13 @@ public class NotificationManager * Creates the given zen rule. * * <p> - * Only available if policy access is granted to this package. + * Throws a SecurityException if policy access is granted to this package. * See {@link #isNotificationPolicyAccessGranted}. * * @param automaticZenRule the rule to create. - * @return A fully populated {@link AutomaticZenRule} if the rule was persisted successfully, - * null otherwise. + * @return The id of the newly created rule; null if the rule could not be created. */ - public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule) { + public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) { INotificationManager service = getService(); try { return service.addAutomaticZenRule(automaticZenRule); @@ -469,18 +479,19 @@ public class NotificationManager * Updates the given zen rule. * * <p> - * Only available if policy access is granted to this package. + * Throws a SecurityException if policy access is granted to this package. * See {@link #isNotificationPolicyAccessGranted}. * * <p> * Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}. + * @param id The id of the rule to update * @param automaticZenRule the rule to update. * @return Whether the rule was successfully updated. */ - public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule) { + public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) { INotificationManager service = getService(); try { - return service.updateAutomaticZenRule(automaticZenRule); + return service.updateAutomaticZenRule(id, automaticZenRule); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -490,7 +501,7 @@ public class NotificationManager * Deletes the automatic zen rule with the given id. * * <p> - * Only available if policy access is granted to this package. + * Throws a SecurityException if policy access is granted to this package. * See {@link #isNotificationPolicyAccessGranted}. * * <p> diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 74fe13ac1961..6e29eaab26d0 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2921,7 +2921,7 @@ public class DevicePolicyManager { * Called by a device owner to request a bugreport. * * <p>There must be only one user on the device, managed by the device owner. - * Otherwise a security exception will be thrown. + * Otherwise a {@link SecurityException} will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return {@code true} if the bugreport collection started successfully, or {@code false} @@ -5686,6 +5686,9 @@ public class DevicePolicyManager { * <p> Device logs contain various information intended for security auditing purposes. * See {@link SecurityEvent} for details. * + * <p>There must be only one user on the device, managed by the device owner. + * Otherwise a {@link SecurityException} will be thrown. + * * @param admin Which device owner this request is associated with. * @param enabled whether device logging should be enabled or not. * @see #retrieveDeviceLogs @@ -5701,6 +5704,9 @@ public class DevicePolicyManager { /** * Return whether device logging is enabled or not by the device owner. * + * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be + * thrown. + * * @param admin Which device owner this request is associated with. * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise. */ @@ -5720,6 +5726,9 @@ public class DevicePolicyManager { * <p> Access to the logs is rate limited and it will only return new logs after the device * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}. * + * <p>There must be only one user on the device, managed by the device owner. + * Otherwise a {@link SecurityException} will be thrown. + * * @param admin Which device owner this request is associated with. * @return the new batch of device logs which is a list of {@link SecurityEvent}, * or {@code null} if rate limitation is exceeded or if logging is currently disabled. @@ -5764,6 +5773,9 @@ public class DevicePolicyManager { * result, this API is provided as best-effort and the returned logs may contain corrupted data. * </strong> * + * <p>There must be only one user on the device, managed by the device owner. + * Otherwise a {@link SecurityException} will be thrown. + * * @param admin Which device owner this request is associated with. * @return Device logs from before the latest reboot of the system. */ diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/auditing/SecurityLog.java index 829685b83b5b..13823a23f43b 100644 --- a/core/java/android/auditing/SecurityLog.java +++ b/core/java/android/auditing/SecurityLog.java @@ -116,7 +116,7 @@ public class SecurityLog { /** * A class representing a security event log entry. */ - public static class SecurityEvent implements Parcelable { + public static final class SecurityEvent implements Parcelable { private Event mEvent; /** @hide */ diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java index 01f72efb22ac..71949381a4eb 100644 --- a/core/java/android/bluetooth/OobData.java +++ b/core/java/android/bluetooth/OobData.java @@ -23,8 +23,9 @@ import android.util.Log; /** * Out Of Band Data for Bluetooth device. + * @hide */ -public class OobData implements Parcelable { +public final class OobData implements Parcelable { private byte[] securityManagerTk; public byte[] getSecurityManagerTk() { diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java deleted file mode 100644 index ab3aa27cfeb6..000000000000 --- a/core/java/android/content/pm/ContainerEncryptionParams.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Slog; - -import java.security.InvalidAlgorithmParameterException; -import java.security.spec.AlgorithmParameterSpec; -import java.util.Arrays; - -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; - -/** - * Represents encryption parameters used to read a container. - * - * @deprecated encrypted containers are legacy. - * @hide - */ -@SystemApi -@Deprecated -public class ContainerEncryptionParams implements Parcelable { - protected static final String TAG = "ContainerEncryptionParams"; - - /** What we print out first when toString() is called. */ - private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{"; - - /** - * Parameter type for parceling that indicates the next parameters are - * IvParameters. - */ - private static final int ENC_PARAMS_IV_PARAMETERS = 1; - - /** Parameter type for paceling that indicates there are no MAC parameters. */ - private static final int MAC_PARAMS_NONE = 1; - - /** The encryption algorithm used. */ - private final String mEncryptionAlgorithm; - - /** The parameter spec to be used for encryption. */ - private final IvParameterSpec mEncryptionSpec; - - /** Secret key to be used for decryption. */ - private final SecretKey mEncryptionKey; - - /** Algorithm name for the MAC to be used. */ - private final String mMacAlgorithm; - - /** The parameter spec to be used for the MAC tag authentication. */ - private final AlgorithmParameterSpec mMacSpec; - - /** Secret key to be used for MAC tag authentication. */ - private final SecretKey mMacKey; - - /** MAC tag authenticating the data in the container. */ - private final byte[] mMacTag; - - /** Offset into file where authenticated (e.g., MAC protected) data begins. */ - private final long mAuthenticatedDataStart; - - /** Offset into file where encrypted data begins. */ - private final long mEncryptedDataStart; - - /** - * Offset into file for the end of encrypted data (and, by extension, - * authenticated data) in file. - */ - private final long mDataEnd; - - public ContainerEncryptionParams(String encryptionAlgorithm, - AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey) - throws InvalidAlgorithmParameterException { - this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1, - -1); - } - - /** - * Creates container encryption specifications for installing from encrypted - * containers. - * - * @param encryptionAlgorithm encryption algorithm to use; format matches - * JCE - * @param encryptionSpec algorithm parameter specification - * @param encryptionKey key used for decryption - * @param macAlgorithm MAC algorithm to use; format matches JCE - * @param macSpec algorithm parameters specification, may be {@code null} - * @param macKey key used for authentication (i.e., for the MAC tag) - * @param macTag message authentication code (MAC) tag for the authenticated - * data - * @param authenticatedDataStart offset of start of authenticated data in - * stream - * @param encryptedDataStart offset of start of encrypted data in stream - * @param dataEnd offset of the end of both the authenticated and encrypted - * data - * @throws InvalidAlgorithmParameterException - */ - public ContainerEncryptionParams(String encryptionAlgorithm, - AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm, - AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag, - long authenticatedDataStart, long encryptedDataStart, long dataEnd) - throws InvalidAlgorithmParameterException { - if (TextUtils.isEmpty(encryptionAlgorithm)) { - throw new NullPointerException("algorithm == null"); - } else if (encryptionSpec == null) { - throw new NullPointerException("encryptionSpec == null"); - } else if (encryptionKey == null) { - throw new NullPointerException("encryptionKey == null"); - } - - if (!TextUtils.isEmpty(macAlgorithm)) { - if (macKey == null) { - throw new NullPointerException("macKey == null"); - } - } - - if (!(encryptionSpec instanceof IvParameterSpec)) { - throw new InvalidAlgorithmParameterException( - "Unknown parameter spec class; must be IvParameters"); - } - - mEncryptionAlgorithm = encryptionAlgorithm; - mEncryptionSpec = (IvParameterSpec) encryptionSpec; - mEncryptionKey = encryptionKey; - - mMacAlgorithm = macAlgorithm; - mMacSpec = macSpec; - mMacKey = macKey; - mMacTag = macTag; - - mAuthenticatedDataStart = authenticatedDataStart; - mEncryptedDataStart = encryptedDataStart; - mDataEnd = dataEnd; - } - - public String getEncryptionAlgorithm() { - return mEncryptionAlgorithm; - } - - public AlgorithmParameterSpec getEncryptionSpec() { - return mEncryptionSpec; - } - - public SecretKey getEncryptionKey() { - return mEncryptionKey; - } - - public String getMacAlgorithm() { - return mMacAlgorithm; - } - - public AlgorithmParameterSpec getMacSpec() { - return mMacSpec; - } - - public SecretKey getMacKey() { - return mMacKey; - } - - public byte[] getMacTag() { - return mMacTag; - } - - public long getAuthenticatedDataStart() { - return mAuthenticatedDataStart; - } - - public long getEncryptedDataStart() { - return mEncryptedDataStart; - } - - public long getDataEnd() { - return mDataEnd; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof ContainerEncryptionParams)) { - return false; - } - - final ContainerEncryptionParams other = (ContainerEncryptionParams) o; - - // Primitive comparison - if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart) - || (mEncryptedDataStart != other.mEncryptedDataStart) - || (mDataEnd != other.mDataEnd)) { - return false; - } - - // String comparison - if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm) - || !mMacAlgorithm.equals(other.mMacAlgorithm)) { - return false; - } - - // Object comparison - if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey) - || !isSecretKeyEqual(mMacKey, other.mMacKey)) { - return false; - } - - if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV()) - || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) { - return false; - } - - return true; - } - - private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) { - final String keyFormat = key1.getFormat(); - final String otherKeyFormat = key2.getFormat(); - - if (keyFormat == null) { - if (keyFormat != otherKeyFormat) { - return false; - } - - if (key1.getEncoded() != key2.getEncoded()) { - return false; - } - } else { - if (!keyFormat.equals(key2.getFormat())) { - return false; - } - - if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) { - return false; - } - } - - return true; - } - - @Override - public int hashCode() { - int hash = 3; - - hash += 5 * mEncryptionAlgorithm.hashCode(); - hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV()); - hash += 11 * mEncryptionKey.hashCode(); - hash += 13 * mMacAlgorithm.hashCode(); - hash += 17 * mMacKey.hashCode(); - hash += 19 * Arrays.hashCode(mMacTag); - hash += 23 * mAuthenticatedDataStart; - hash += 29 * mEncryptedDataStart; - hash += 31 * mDataEnd; - - return hash; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX); - - sb.append("mEncryptionAlgorithm=\""); - sb.append(mEncryptionAlgorithm); - sb.append("\","); - sb.append("mEncryptionSpec="); - sb.append(mEncryptionSpec.toString()); - sb.append("mEncryptionKey="); - sb.append(mEncryptionKey.toString()); - - sb.append("mMacAlgorithm=\""); - sb.append(mMacAlgorithm); - sb.append("\","); - sb.append("mMacSpec="); - sb.append(mMacSpec.toString()); - sb.append("mMacKey="); - sb.append(mMacKey.toString()); - - sb.append(",mAuthenticatedDataStart="); - sb.append(mAuthenticatedDataStart); - sb.append(",mEncryptedDataStart="); - sb.append(mEncryptedDataStart); - sb.append(",mDataEnd="); - sb.append(mDataEnd); - sb.append('}'); - - return sb.toString(); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mEncryptionAlgorithm); - dest.writeInt(ENC_PARAMS_IV_PARAMETERS); - dest.writeByteArray(mEncryptionSpec.getIV()); - dest.writeSerializable(mEncryptionKey); - - dest.writeString(mMacAlgorithm); - dest.writeInt(MAC_PARAMS_NONE); - dest.writeByteArray(new byte[0]); - dest.writeSerializable(mMacKey); - - dest.writeByteArray(mMacTag); - - dest.writeLong(mAuthenticatedDataStart); - dest.writeLong(mEncryptedDataStart); - dest.writeLong(mDataEnd); - } - - private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException { - mEncryptionAlgorithm = source.readString(); - final int encParamType = source.readInt(); - final byte[] encParamsEncoded = source.createByteArray(); - mEncryptionKey = (SecretKey) source.readSerializable(); - - mMacAlgorithm = source.readString(); - final int macParamType = source.readInt(); - source.createByteArray(); // byte[] macParamsEncoded - mMacKey = (SecretKey) source.readSerializable(); - - mMacTag = source.createByteArray(); - - mAuthenticatedDataStart = source.readLong(); - mEncryptedDataStart = source.readLong(); - mDataEnd = source.readLong(); - - switch (encParamType) { - case ENC_PARAMS_IV_PARAMETERS: - mEncryptionSpec = new IvParameterSpec(encParamsEncoded); - break; - default: - throw new InvalidAlgorithmParameterException("Unknown parameter type " - + encParamType); - } - - switch (macParamType) { - case MAC_PARAMS_NONE: - mMacSpec = null; - break; - default: - throw new InvalidAlgorithmParameterException("Unknown parameter type " - + macParamType); - } - - if (mEncryptionKey == null) { - throw new NullPointerException("encryptionKey == null"); - } - } - - public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR = - new Parcelable.Creator<ContainerEncryptionParams>() { - public ContainerEncryptionParams createFromParcel(Parcel source) { - try { - return new ContainerEncryptionParams(source); - } catch (InvalidAlgorithmParameterException e) { - Slog.e(TAG, "Invalid algorithm parameters specified", e); - return null; - } - } - - public ContainerEncryptionParams[] newArray(int size) { - return new ContainerEncryptionParams[size]; - } - }; -}
\ No newline at end of file diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index d6b674c0edee..9959f2749609 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -46,7 +46,6 @@ import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; -import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.graphics.Bitmap; import android.net.Uri; @@ -214,19 +213,11 @@ interface IPackageManager { List<InstrumentationInfo> queryInstrumentation( String targetPackage, int flags); - void installPackage(in String originPath, - in IPackageInstallObserver2 observer, - int flags, - in String installerPackageName, - in VerificationParams verificationParams, - in String packageAbiOverride); - + /** @deprecated Use PackageInstaller instead */ void installPackageAsUser(in String originPath, in IPackageInstallObserver2 observer, int flags, in String installerPackageName, - in VerificationParams verificationParams, - in String packageAbiOverride, int userId); void finishPackageInstall(int token); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 4dd8155f1b10..c2d1bdda3d1f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4598,60 +4598,20 @@ public abstract class PackageManager { */ @Deprecated public abstract void installPackage( - Uri packageURI, IPackageInstallObserver observer, @InstallFlags int flags, + Uri packageURI, + IPackageInstallObserver observer, + @InstallFlags int flags, String installerPackageName); - /** * @deprecated replaced by {@link PackageInstaller} * @hide */ @Deprecated - public abstract void installPackageWithVerification(Uri packageURI, - IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName, - Uri verificationURI, ContainerEncryptionParams encryptionParams); - - /** - * @deprecated replaced by {@link PackageInstaller} - * @hide - */ - @Deprecated - public abstract void installPackageWithVerificationAndEncryption(Uri packageURI, - IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams); - - /** - * @deprecated replaced by {@link PackageInstaller} - * @hide - */ - @Deprecated - public abstract void installPackage(Uri packageURI, PackageInstallObserver observer, - @InstallFlags int flags, String installerPackageName); - - /** - * @deprecated replaced by {@link PackageInstaller} - * @hide - */ - @Deprecated - public abstract void installPackageAsUser(Uri packageURI, PackageInstallObserver observer, - @InstallFlags int flags, String installerPackageName, @UserIdInt int userId); - - /** - * @deprecated replaced by {@link PackageInstaller} - * @hide - */ - @Deprecated - public abstract void installPackageWithVerification(Uri packageURI, - PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName, - Uri verificationURI, ContainerEncryptionParams encryptionParams); - - /** - * @deprecated replaced by {@link PackageInstaller} - * @hide - */ - @Deprecated - public abstract void installPackageWithVerificationAndEncryption(Uri packageURI, - PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams); + public abstract void installPackage( + Uri packageURI, + PackageInstallObserver observer, + @InstallFlags int flags, + String installerPackageName); /** * If there is already an application with the given package name installed diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/content/pm/VerificationParams.aidl deleted file mode 100644 index 5bb7f6962fe8..000000000000 --- a/core/java/android/content/pm/VerificationParams.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -parcelable VerificationParams; diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java index d040a8563440..098f1e6947a3 100644 --- a/core/java/android/net/ConnectivityMetricsEvent.java +++ b/core/java/android/net/ConnectivityMetricsEvent.java @@ -16,12 +16,11 @@ package android.net; -import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -@SystemApi -public class ConnectivityMetricsEvent implements Parcelable { +/** {@hide} */ +public final class ConnectivityMetricsEvent implements Parcelable { /** The time when this event was collected, as returned by System.currentTimeMillis(). */ final public long timestamp; diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java index 5e96cc1fe04a..8526584d640d 100644 --- a/core/java/android/net/DataUsageRequest.java +++ b/core/java/android/net/DataUsageRequest.java @@ -29,7 +29,7 @@ import java.util.Objects; * If no {@code uid}s are set, callbacks are restricted to device-owners, * carrier-privileged apps, or system apps. */ -public class DataUsageRequest implements Parcelable { +public final class DataUsageRequest implements Parcelable { /** * @hide diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 1085b1e9dc6b..307bd2d13f83 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -258,6 +258,20 @@ public class Environment { return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId)); } + private static File getDataProfilesDeDirectory(int userId) { + return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId)); + } + + /** {@hide} */ + public static File getDataProfilesDePackageDirectory(int userId, String packageName) { + return buildPath(getDataProfilesDeDirectory(userId), packageName); + } + + /** {@hide} */ + public static File getDataProfilesDeForeignDexDirectory(int userId) { + return buildPath(getDataProfilesDeDirectory(userId), "foreign-dex"); + } + /** {@hide} */ public static File getDataAppDirectory(String volumeUuid) { return new File(getDataDirectory(volumeUuid), "app"); @@ -493,7 +507,7 @@ public class Environment { * </ul> * @hide */ - private static final String[] STANDARD_DIRECTORIES = { + public static final String[] STANDARD_DIRECTORIES = { DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java index d860c7d8ad2e..54d20d361a26 100644 --- a/core/java/android/os/storage/StorageVolume.java +++ b/core/java/android/os/storage/StorageVolume.java @@ -76,7 +76,7 @@ import java.io.File; */ // NOTE: This is a legacy specialization of VolumeInfo which describes the volume for a specific // user, but is now part of the public API. -public class StorageVolume implements Parcelable { +public final class StorageVolume implements Parcelable { private final String mId; private final int mStorageId; diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java index b9213513cc17..0439fe247ee1 100644 --- a/core/java/android/provider/BlockedNumberContract.java +++ b/core/java/android/provider/BlockedNumberContract.java @@ -29,8 +29,11 @@ import android.os.Bundle; * <p> * The content provider exposes a table containing blocked numbers. The columns and URIs for * accessing this table are defined by the {@link BlockedNumbers} class. Messages, and calls from - * blocked numbers are discarded by the platform. Notifications upon provider changes can be - * received using a {@link android.database.ContentObserver}. + * blocked numbers are discarded by the platform. If the user contacts emergency + * services, number blocking is disabled by the platform for a duration defined by + * {@link android.telephony.CarrierConfigManager#KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT}. + * Notifications upon provider changes can be received using a + * {@link android.database.ContentObserver}. * </p> * * <h3> Permissions </h3> @@ -141,25 +144,26 @@ public class BlockedNumberContract { /** * Content URI for the blocked numbers. - * - * Supported operations - * blocked - * - query - * - delete - * - insert - * - * blocked/ID - * - query (selection is not supported) - * - delete (selection is not supported) + * <h3> Supported operations </h3> + * <p> blocked + * <ul> + * <li> query + * <li> delete + * <li> insert + * </ul> + * <p> blocked/ID + * <ul> + * <li> query (selection is not supported) + * <li> delete (selection is not supported) + * </ul> */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, - "blocked"); + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "blocked"); /** * The MIME type of {@link #CONTENT_URI} itself providing a directory of blocked phone * numbers. */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number"; /** * The MIME type of a blocked phone number under {@link #CONTENT_URI}. @@ -215,7 +219,7 @@ public class BlockedNumberContract { /** * Returns {@code true} if blocking numbers is supported for the current user. - * <p> Typically, blocking numbers is only supported for the primary user. + * <p> Typically, blocking numbers is only supported for one user at a time. */ public static boolean canCurrentUserBlockNumbers(Context context) { final Bundle res = context.getContentResolver().call( @@ -292,6 +296,9 @@ public class BlockedNumberContract { return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false); } + /** + * Returns the current status of block suppression. + */ public static BlockSuppressionStatus getBlockSuppressionStatus(Context context) { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_GET_BLOCK_SUPPRESSION_STATUS, null, null); diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java index b5387f14e40c..41af837a1dbc 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -18,18 +18,17 @@ package android.service.notification; import android.annotation.SdkConstant; import android.annotation.SystemApi; -import android.app.INotificationManager; -import android.app.Notification; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Handler; import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; +import com.android.internal.os.SomeArgs; /** * A service that helps the user manage notifications by modifying the @@ -125,8 +124,24 @@ public abstract class NotificationAssistantService extends NotificationListenerS } } + private Handler mHandler; + + /** @hide */ + @Override + public void registerAsSystemService(Context context, ComponentName componentName, + int currentUser) throws RemoteException { + super.registerAsSystemService(context, componentName, currentUser); + mHandler = new MyHandler(getContext().getMainLooper()); + } + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + mHandler = new MyHandler(getContext().getMainLooper()); + } + @Override - public IBinder onBind(Intent intent) { + public final IBinder onBind(Intent intent) { if (mWrapper == null) { mWrapper = new NotificationAssistantWrapper(); } @@ -198,8 +213,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS * @param key the notification key * @param adjustment the new importance with an explanation */ - public final void adjustImportance(String key, Adjustment adjustment) - { + public final void adjustImportance(String key, Adjustment adjustment) { if (!isBound()) return; try { getNotificationInterface().setImportanceFromAssistant(mWrapper, key, @@ -212,7 +226,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS private class NotificationAssistantWrapper extends NotificationListenerWrapper { @Override public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder, - int importance, boolean user) throws RemoteException { + int importance, boolean user) { StatusBarNotification sbn; try { sbn = sbnHolder.get(); @@ -221,54 +235,114 @@ public abstract class NotificationAssistantService extends NotificationListenerS return; } - try { - Adjustment adjustment = - NotificationAssistantService.this.onNotificationEnqueued(sbn, importance, user); - if (adjustment != null) { - adjustImportance(sbn.getKey(), adjustment); - } - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationEnqueued", t); - } + SomeArgs args = SomeArgs.obtain(); + args.arg1 = sbn; + args.argi1 = importance; + args.argi2 = user ? 1 : 0; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED, + args).sendToTarget(); } @Override - public void onNotificationVisibilityChanged(String key, long time, boolean visible) - throws RemoteException { - try { - NotificationAssistantService.this.onNotificationVisibilityChanged(key, time, - visible); - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationVisibilityChanged", t); - } + public void onNotificationVisibilityChanged(String key, long time, boolean visible) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = key; + args.arg2 = time; + args.argi1 = visible ? 1 : 0; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_VISIBILITY_CHANGED, + args).sendToTarget(); } @Override - public void onNotificationClick(String key, long time) throws RemoteException { - try { - NotificationAssistantService.this.onNotificationClick(key, time); - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationClick", t); - } + public void onNotificationClick(String key, long time) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = key; + args.arg2 = time; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_CLICK, + args).sendToTarget(); } @Override - public void onNotificationActionClick(String key, long time, int actionIndex) - throws RemoteException { - try { - NotificationAssistantService.this.onNotificationActionClick(key, time, actionIndex); - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationActionClick", t); - } + public void onNotificationActionClick(String key, long time, int actionIndex) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = key; + args.arg2 = time; + args.argi1 = actionIndex; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ACTION_CLICK, + args).sendToTarget(); } @Override - public void onNotificationRemovedReason(String key, long time, int reason) - throws RemoteException { - try { - NotificationAssistantService.this.onNotificationRemoved(key, time, reason); - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationRemoved", t); + public void onNotificationRemovedReason(String key, long time, int reason) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = key; + args.arg2 = time; + args.argi1 = reason; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED_REASON, + args).sendToTarget(); + } + } + + private final class MyHandler extends Handler { + public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1; + public static final int MSG_ON_NOTIFICATION_VISIBILITY_CHANGED = 2; + public static final int MSG_ON_NOTIFICATION_CLICK = 3; + public static final int MSG_ON_NOTIFICATION_ACTION_CLICK = 4; + public static final int MSG_ON_NOTIFICATION_REMOVED_REASON = 5; + + public MyHandler(Looper looper) { + super(looper, null, false); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_ON_NOTIFICATION_ENQUEUED: { + SomeArgs args = (SomeArgs) msg.obj; + StatusBarNotification sbn = (StatusBarNotification) args.arg1; + final int importance = args.argi1; + final boolean user = args.argi2 == 1; + args.recycle(); + Adjustment adjustment = onNotificationEnqueued(sbn, importance, user); + if (adjustment != null) { + adjustImportance(sbn.getKey(), adjustment); + } + } break; + + case MSG_ON_NOTIFICATION_VISIBILITY_CHANGED: { + SomeArgs args = (SomeArgs) msg.obj; + final String key = (String) args.arg1; + final long time = (long) args.arg2; + final boolean visible = args.argi1 == 1; + args.recycle(); + onNotificationVisibilityChanged(key, time, visible); + } break; + + case MSG_ON_NOTIFICATION_CLICK: { + SomeArgs args = (SomeArgs) msg.obj; + final String key = (String) args.arg1; + final long time = (long) args.arg2; + args.recycle(); + onNotificationClick(key, time); + } break; + + case MSG_ON_NOTIFICATION_ACTION_CLICK: { + SomeArgs args = (SomeArgs) msg.obj; + final String key = (String) args.arg1; + final long time = (long) args.arg2; + final int actionIndex = args.argi1; + args.recycle(); + onNotificationActionClick(key, time, actionIndex); + } break; + + case MSG_ON_NOTIFICATION_REMOVED_REASON: { + SomeArgs args = (SomeArgs) msg.obj; + final String key = (String) args.arg1; + final long time = (long) args.arg2; + final int reason = args.argi1; + args.recycle(); + onNotificationRemoved(key, time, reason); + } break; } } } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index b4332e181fc4..73a890fb0308 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -16,6 +16,10 @@ package android.service.notification; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + import android.annotation.IntDef; import android.annotation.SystemApi; import android.annotation.SdkConstant; @@ -43,7 +47,8 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.widget.RemoteViews; - +import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.SomeArgs; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -163,8 +168,14 @@ public abstract class NotificationListenerService extends Service { @SystemApi public static final int TRIM_LIGHT = 1; + private final Object mLock = new Object(); + + private Handler mHandler; + /** @hide */ protected NotificationListenerWrapper mWrapper = null; + + @GuardedBy("mLock") private RankingMap mRankingMap; private INotificationManager mNoMan; @@ -195,6 +206,12 @@ public abstract class NotificationListenerService extends Service { public static final String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications"; + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + mHandler = new MyHandler(getMainLooper()); + } + /** * Implement this method to learn about new notifications as they are posted by apps. * @@ -642,7 +659,9 @@ public abstract class NotificationListenerService extends Service { * @return A {@link RankingMap} object providing access to ranking information */ public RankingMap getCurrentRanking() { - return mRankingMap; + synchronized (mLock) { + return mRankingMap; + } } @Override @@ -684,6 +703,7 @@ public abstract class NotificationListenerService extends Service { INotificationManager noMan = getNotificationInterface(); noMan.registerListener(mWrapper, componentName, currentUser); mCurrentUser = currentUser; + mHandler = new MyHandler(context.getMainLooper()); } /** @@ -710,7 +730,7 @@ public abstract class NotificationListenerService extends Service { * <P>The service should wait for the {@link #onListenerConnected()} event * before performing any operations. */ - public static final void requestRebind(ComponentName componentName) + public static void requestRebind(ComponentName componentName) throws RemoteException { INotificationManager noMan = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); @@ -782,7 +802,6 @@ public abstract class NotificationListenerService extends Service { } try { - Notification notification = sbn.getNotification(); // convert icon metadata to legacy format for older clients createLegacyIconExtras(sbn.getNotification()); maybePopulateRemoteViews(sbn.getNotification()); @@ -794,20 +813,23 @@ public abstract class NotificationListenerService extends Service { } // protect subclass from concurrent modifications of (@link mNotificationKeys}. - synchronized (mWrapper) { - applyUpdate(update); - try { - if (sbn != null) { - NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap); - } else { - // still pass along the ranking map, it may contain other information - NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap); - } - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationPosted", t); + synchronized (mLock) { + applyUpdateLocked(update); + if (sbn != null) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = sbn; + args.arg2 = mRankingMap; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_POSTED, + args).sendToTarget(); + } else { + // still pass along the ranking map, it may contain other information + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE, + mRankingMap).sendToTarget(); } } + } + @Override public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder, NotificationRankingUpdate update) { @@ -819,56 +841,48 @@ public abstract class NotificationListenerService extends Service { return; } // protect subclass from concurrent modifications of (@link mNotificationKeys}. - synchronized (mWrapper) { - applyUpdate(update); - try { - NotificationListenerService.this.onNotificationRemoved(sbn, mRankingMap); - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationRemoved", t); - } + synchronized (mLock) { + applyUpdateLocked(update); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = sbn; + args.arg2 = mRankingMap; + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED, + args).sendToTarget(); } + } + @Override public void onListenerConnected(NotificationRankingUpdate update) { // protect subclass from concurrent modifications of (@link mNotificationKeys}. - synchronized (mWrapper) { - applyUpdate(update); - try { - NotificationListenerService.this.onListenerConnected(); - } catch (Throwable t) { - Log.w(TAG, "Error running onListenerConnected", t); - } + synchronized (mLock) { + applyUpdateLocked(update); } + mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget(); } + @Override public void onNotificationRankingUpdate(NotificationRankingUpdate update) throws RemoteException { // protect subclass from concurrent modifications of (@link mNotificationKeys}. - synchronized (mWrapper) { - applyUpdate(update); - try { - NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap); - } catch (Throwable t) { - Log.w(TAG, "Error running onNotificationRankingUpdate", t); - } + synchronized (mLock) { + applyUpdateLocked(update); + mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE, + mRankingMap).sendToTarget(); } + } + @Override public void onListenerHintsChanged(int hints) throws RemoteException { - try { - NotificationListenerService.this.onListenerHintsChanged(hints); - } catch (Throwable t) { - Log.w(TAG, "Error running onListenerHintsChanged", t); - } + mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_HINTS_CHANGED, + hints, 0).sendToTarget(); } @Override public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException { - try { - NotificationListenerService.this.onInterruptionFilterChanged(interruptionFilter); - } catch (Throwable t) { - Log.w(TAG, "Error running onInterruptionFilterChanged", t); - } + mHandler.obtainMessage(MyHandler.MSG_ON_INTERRUPTION_FILTER_CHANGED, + interruptionFilter, 0).sendToTarget(); } @Override @@ -901,11 +915,12 @@ public abstract class NotificationListenerService extends Service { } } - private void applyUpdate(NotificationRankingUpdate update) { + private void applyUpdateLocked(NotificationRankingUpdate update) { mRankingMap = new RankingMap(update); } - private Context getContext() { + /** @hide */ + protected Context getContext() { if (mSystemContext != null) { return mSystemContext; } @@ -1289,4 +1304,57 @@ public abstract class NotificationListenerService extends Service { } }; } + + private final class MyHandler extends Handler { + public static final int MSG_ON_NOTIFICATION_POSTED = 1; + public static final int MSG_ON_NOTIFICATION_REMOVED = 2; + public static final int MSG_ON_LISTENER_CONNECTED = 3; + public static final int MSG_ON_NOTIFICATION_RANKING_UPDATE = 4; + public static final int MSG_ON_LISTENER_HINTS_CHANGED = 5; + public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6; + + public MyHandler(Looper looper) { + super(looper, null, false); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_ON_NOTIFICATION_POSTED: { + SomeArgs args = (SomeArgs) msg.obj; + StatusBarNotification sbn = (StatusBarNotification) args.arg1; + RankingMap rankingMap = (RankingMap) args.arg2; + args.recycle(); + onNotificationPosted(sbn, rankingMap); + } break; + + case MSG_ON_NOTIFICATION_REMOVED: { + SomeArgs args = (SomeArgs) msg.obj; + StatusBarNotification sbn = (StatusBarNotification) args.arg1; + RankingMap rankingMap = (RankingMap) args.arg2; + args.recycle(); + onNotificationRemoved(sbn, rankingMap); + } break; + + case MSG_ON_LISTENER_CONNECTED: { + onListenerConnected(); + } break; + + case MSG_ON_NOTIFICATION_RANKING_UPDATE: { + RankingMap rankingMap = (RankingMap) msg.obj; + onNotificationRankingUpdate(rankingMap); + } break; + + case MSG_ON_LISTENER_HINTS_CHANGED: { + final int hints = msg.arg1; + onListenerHintsChanged(hints); + } break; + + case MSG_ON_INTERRUPTION_FILTER_CHANGED: { + final int interruptionFilter = msg.arg1; + onInterruptionFilterChanged(interruptionFilter); + } break; + } + } + } } diff --git a/core/java/android/service/notification/ZenModeConfig.aidl b/core/java/android/service/notification/ZenModeConfig.aidl index c73b75ef821f..4644103c435c 100644 --- a/core/java/android/service/notification/ZenModeConfig.aidl +++ b/core/java/android/service/notification/ZenModeConfig.aidl @@ -17,4 +17,5 @@ package android.service.notification; parcelable ZenModeConfig; +parcelable ZenModeConfig.ZenRule; diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 97939a9ba3af..27315ee86d32 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -1017,7 +1017,7 @@ public class ZenModeConfig implements Parcelable { public static class ZenRule implements Parcelable { public boolean enabled; public boolean snoozing; // user manually disabled this instance - public String name; // required for automatic (unique) + public String name; // required for automatic public int zenMode; public Uri conditionId; // required for automatic public Condition condition; // optional diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e7be7af48a7b..9bd3df0c1a1f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10270,6 +10270,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window + * is currently in without any insets. + * + * @hide + */ + public void getWindowDisplayFrame(Rect outRect) { + if (mAttachInfo != null) { + try { + mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); + } catch (RemoteException e) { + return; + } + return; + } + // The view is not attached to a display so we don't have a context. + // Make a best guess about the display size. + Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); + d.getRectSize(outRect); + } + + /** * Dispatch a notification about a resource configuration change down * the view hierarchy. * ViewGroups should override to route to their children. diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 54b3932dfeb2..df2f57589361 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -23,7 +23,6 @@ import com.android.internal.R; import android.annotation.NonNull; import android.content.Context; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.PixelFormat; import android.graphics.Rect; @@ -1587,18 +1586,16 @@ public class PopupWindow { public int getMaxAvailableHeight( @NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) { final Rect displayFrame = new Rect(); - anchor.getWindowVisibleDisplayFrame(displayFrame); + if (ignoreBottomDecorations) { + anchor.getWindowDisplayFrame(displayFrame); + } else { + anchor.getWindowVisibleDisplayFrame(displayFrame); + } final int[] anchorPos = mDrawingLocation; anchor.getLocationOnScreen(anchorPos); - final int bottomEdge; - if (ignoreBottomDecorations) { - final Resources res = anchor.getContext().getResources(); - bottomEdge = res.getDisplayMetrics().heightPixels; - } else { - bottomEdge = displayFrame.bottom; - } + final int bottomEdge = displayFrame.bottom; final int distanceToBottom; if (mOverlapAnchor) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 95fcdc179643..f19bf02a238f 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -662,11 +662,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ private int mDeviceProvisionedState = DEVICE_PROVISIONED_UNKNOWN; - /* + /** * Kick-start the font cache for the zygote process (to pay the cost of * initializing freetype for our default font only once). + * @hide */ - static { + public static void preloadFontCache() { Paint p = new Paint(); p.setAntiAlias(true); // We don't care about the result, just the side-effect of measuring. diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 6ad9e20360e0..eb509c2632c1 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -36,6 +36,7 @@ import android.text.Hyphenator; import android.util.EventLog; import android.util.Log; import android.webkit.WebViewFactory; +import android.widget.TextView; import com.android.internal.os.InstallerConnection.InstallerException; @@ -214,6 +215,7 @@ public class ZygoteInit { private static void preloadTextResources() { Hyphenator.init(); + TextView.preloadFontCache(); } /** diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index cbc735fc065c..795012dab4d1 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -896,8 +896,7 @@ public class LockPatternUtils { * @return true if device is file encrypted */ public static boolean isFileEncryptionEnabled() { - final String status = SystemProperties.get("ro.crypto.type", ""); - return "file".equalsIgnoreCase(status); + return StorageManager.isFileBasedEncryptionEnabled(); } /** diff --git a/core/jni/Android.mk b/core/jni/Android.mk index d5f080ae4b27..ed3fe428b5a3 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -33,6 +33,7 @@ LOCAL_SRC_FILES:= \ com_android_internal_content_NativeLibraryHelper.cpp \ com_google_android_gles_jni_EGLImpl.cpp \ com_google_android_gles_jni_GLImpl.cpp.arm \ + android_app_Activity.cpp \ android_app_ApplicationLoaders.cpp \ android_app_NativeActivity.cpp \ android_auditing_SecurityLog.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 6ed07a7c9990..2a04526ed3eb 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -178,6 +178,7 @@ extern int register_android_backup_FileBackupHelperBase(JNIEnv *env); extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env); extern int register_android_app_backup_FullBackup(JNIEnv *env); extern int register_android_app_ApplicationLoaders(JNIEnv* env); +extern int register_android_app_Activity(JNIEnv *env); extern int register_android_app_ActivityThread(JNIEnv *env); extern int register_android_app_NativeActivity(JNIEnv *env); extern int register_android_media_RemoteDisplay(JNIEnv *env); @@ -1373,6 +1374,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_backup_BackupHelperDispatcher), REG_JNI(register_android_app_backup_FullBackup), REG_JNI(register_android_app_ApplicationLoaders), + REG_JNI(register_android_app_Activity), REG_JNI(register_android_app_ActivityThread), REG_JNI(register_android_app_NativeActivity), REG_JNI(register_android_util_jar_StrictJarFile), diff --git a/core/jni/android_app_Activity.cpp b/core/jni/android_app_Activity.cpp new file mode 100644 index 000000000000..b1d7e82c73ae --- /dev/null +++ b/core/jni/android_app_Activity.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <poll.h> +#include <android/dlext.h> + +#include "core_jni_helpers.h" + +namespace android +{ + +static jstring getDlWarning_native(JNIEnv* env, jobject) { + const char* text = android_dlwarning(); + return text == nullptr ? nullptr : env->NewStringUTF(text); +} + +static const JNINativeMethod g_methods[] = { + { "getDlWarning", + "()Ljava/lang/String;", + reinterpret_cast<void*>(getDlWarning_native) }, +}; + +static const char* const kActivityPathName = "android/app/Activity"; + +int register_android_app_Activity(JNIEnv* env) { + return RegisterMethodsOrDie(env, kActivityPathName, g_methods, NELEM(g_methods)); +} + +} // namespace android diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 2fb749866f62..1eb011100919 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -320,7 +320,7 @@ android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source) static jint android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz) { - return AudioSystem::newAudioUniqueId(); + return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION); } static jint diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 03d93a1720df..588e738ba1b8 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1598,6 +1598,11 @@ <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE" android:protectionLevel="signature|privileged" /> + <!-- Allows use of PendingIntent.getIntent(). + @hide --> + <permission android:name="android.permission.GET_INTENT_SENDER_INTENT" + android:protectionLevel="signature" /> + <!-- ================================== --> <!-- Permissions affecting the display of other applications --> <!-- ================================== --> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 7c0212801851..90a573ba8fbd 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8189,11 +8189,8 @@ i <!-- @hide From Theme.colorPrimary, used for the TaskDescription primary color. --> <attr name="colorPrimary" /> - <!-- @hide From Theme.windowBackground, used for calculating the - TaskDescription background color. --> - <attr name="windowBackground" /> - <!-- @hide From Theme.windowBackgroundFallback, used for calculating the - TaskDescription background color. --> - <attr name="windowBackgroundFallback" /> + <!-- @hide From Theme.colorBackground, used for the TaskDescription background + color. --> + <attr name="colorBackground" /> </declare-styleable> </resources> diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index dd8baa76c05e..11bb106a6873 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -544,9 +544,7 @@ easier. <item name="windowNoTitle">true</item> <item name="windowBackground">@color/transparent</item> <item name="backgroundDimEnabled">true</item> - <item name="windowTranslucentStatus">false</item> - <item name="windowTranslucentNavigation">false</item> - <item name="windowDrawsSystemBarBackgrounds">false</item> + <item name="statusBarColor">@color/transparent</item> <item name="windowContentOverlay">@null</item> <item name="colorControlActivated">?attr/colorControlHighlight</item> <item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item> diff --git a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java b/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java deleted file mode 100644 index 7deaa9a70a81..000000000000 --- a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -import android.os.Parcel; -import android.test.AndroidTestCase; - -import java.util.Arrays; - -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -public class ContainerEncryptionParamsTest extends AndroidTestCase { - private static final String ENC_ALGORITHM = "AES/CBC/PKCS7Padding"; - - private static final byte[] IV_BYTES = "FOOBAR".getBytes(); - - private static final IvParameterSpec ENC_PARAMS = new IvParameterSpec(IV_BYTES); - - private static final byte[] ENC_KEY_BYTES = "abcd1234wxyz7890".getBytes(); - - private static final SecretKey ENC_KEY = new SecretKeySpec(ENC_KEY_BYTES, "RAW"); - - private static final String MAC_ALGORITHM = "HMAC-SHA1"; - - private static final byte[] MAC_KEY_BYTES = "4wxyzabcd1237890".getBytes(); - - private static final SecretKey MAC_KEY = new SecretKeySpec(MAC_KEY_BYTES, "RAW"); - - private static final byte[] MAC_TAG = "faketag".getBytes(); - - private static final int AUTHENTICATED_START = 5; - - private static final int ENCRYPTED_START = 11; - - private static final int DATA_END = 19; - - public void testParcel() throws Exception { - ContainerEncryptionParams expected = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - Parcel parcel = Parcel.obtain(); - expected.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - ContainerEncryptionParams actual = ContainerEncryptionParams.CREATOR - .createFromParcel(parcel); - - assertEquals(ENC_ALGORITHM, actual.getEncryptionAlgorithm()); - - if (!(actual.getEncryptionSpec() instanceof IvParameterSpec)) { - fail("encryption parameters should be IvParameterSpec"); - } else { - IvParameterSpec actualParams = (IvParameterSpec) actual.getEncryptionSpec(); - assertTrue(Arrays.equals(IV_BYTES, actualParams.getIV())); - } - - assertEquals(ENC_KEY, actual.getEncryptionKey()); - - assertEquals(MAC_ALGORITHM, actual.getMacAlgorithm()); - - assertNull(actual.getMacSpec()); - - assertEquals(MAC_KEY, actual.getMacKey()); - - assertTrue(Arrays.equals(MAC_TAG, actual.getMacTag())); - - assertEquals(AUTHENTICATED_START, actual.getAuthenticatedDataStart()); - - assertEquals(ENCRYPTED_START, actual.getEncryptedDataStart()); - - assertEquals(DATA_END, actual.getDataEnd()); - } - - public void testEquals_Success() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertEquals(params1, params2); - } - - public void testEquals_EncAlgo_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String( - "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_EncParams_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_EncKey_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_MacAlgo_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_MacKey_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_MacTag_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(), - AUTHENTICATED_START, ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_AuthenticatedStart_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_EncryptedStart_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START - 1, DATA_END); - - assertFalse(params1.equals(params2)); - } - - public void testEquals_DataEnd_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END + 1); - - assertFalse(params1.equals(params2)); - } - - public void testHashCode_Success() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertEquals(params1.hashCode(), params2.hashCode()); - } - - public void testHashCode_EncAlgo_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String( - "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_EncParams_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_EncKey_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_MacAlgo_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_MacKey_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_MacTag_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(), - AUTHENTICATED_START, ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_AuthenticatedStart_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1, - ENCRYPTED_START, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_EncryptedStart_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START - 1, DATA_END); - - assertFalse(params1.hashCode() == params2.hashCode()); - } - - public void testHashCode_DataEnd_Failure() throws Exception { - ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM, - ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END); - - ContainerEncryptionParams params2 = new ContainerEncryptionParams( - new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()), - new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null, - new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START, - ENCRYPTED_START, DATA_END + 1); - - assertFalse(params1.hashCode() == params2.hashCode()); - } -} diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index 302b0bd73065..6830a7487dbc 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -217,42 +217,42 @@ public class Credentials { } /** - * Delete all types (private key, certificate, CA certificate) for a + * Delete all types (private key, user certificate, CA certificate) for a * particular {@code alias}. All three can exist for any given alias. - * Returns {@code true} if there was at least one of those types. + * Returns {@code true} if the alias no longer contains any types. */ public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) { return deleteAllTypesForAlias(keystore, alias, KeyStore.UID_SELF); } /** - * Delete all types (private key, certificate, CA certificate) for a + * Delete all types (private key, user certificate, CA certificate) for a * particular {@code alias}. All three can exist for any given alias. - * Returns {@code true} if there was at least one of those types. + * Returns {@code true} if the alias no longer contains any types. */ public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias, int uid) { /* * Make sure every type is deleted. There can be all three types, so * don't use a conditional here. */ - return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid) - | keystore.delete(Credentials.USER_SECRET_KEY + alias, uid) - | deleteCertificateTypesForAlias(keystore, alias, uid); + return deletePrivateKeyTypeForAlias(keystore, alias, uid) + & deleteSecretKeyTypeForAlias(keystore, alias, uid) + & deleteCertificateTypesForAlias(keystore, alias, uid); } /** - * Delete all types (private key, certificate, CA certificate) for a - * particular {@code alias}. All three can exist for any given alias. - * Returns {@code true} if there was at least one of those types. + * Delete certificate types (user certificate, CA certificate) for a + * particular {@code alias}. Both can exist for any given alias. + * Returns {@code true} if the alias no longer contains either type. */ public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) { return deleteCertificateTypesForAlias(keystore, alias, KeyStore.UID_SELF); } /** - * Delete all types (private key, certificate, CA certificate) for a - * particular {@code alias}. All three can exist for any given alias. - * Returns {@code true} if there was at least one of those types. + * Delete certificate types (user certificate, CA certificate) for a + * particular {@code alias}. Both can exist for any given alias. + * Returns {@code true} if the alias no longer contains either type. */ public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias, int uid) { /* @@ -260,12 +260,12 @@ public class Credentials { * so don't use a conditional here. */ return keystore.delete(Credentials.USER_CERTIFICATE + alias, uid) - | keystore.delete(Credentials.CA_CERTIFICATE + alias, uid); + & keystore.delete(Credentials.CA_CERTIFICATE + alias, uid); } /** * Delete private key for a particular {@code alias}. - * Returns {@code true} if an entry was was deleted. + * Returns {@code true} if the entry no longer exists. */ static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias) { return deletePrivateKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF); @@ -273,7 +273,7 @@ public class Credentials { /** * Delete private key for a particular {@code alias}. - * Returns {@code true} if an entry was was deleted. + * Returns {@code true} if the entry no longer exists. */ static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias, int uid) { return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid); @@ -281,7 +281,7 @@ public class Credentials { /** * Delete secret key for a particular {@code alias}. - * Returns {@code true} if an entry was was deleted. + * Returns {@code true} if the entry no longer exists. */ public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias) { return deleteSecretKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF); @@ -289,7 +289,7 @@ public class Credentials { /** * Delete secret key for a particular {@code alias}. - * Returns {@code true} if an entry was was deleted. + * Returns {@code true} if the entry no longer exists. */ public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias, int uid) { return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid); diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 3090ac1c6180..70e4b6ff2e59 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -183,7 +183,8 @@ public class KeyStore { public boolean delete(String key, int uid) { try { - return mBinder.del(key, uid) == NO_ERROR; + int ret = mBinder.del(key, uid); + return (ret == NO_ERROR || ret == KEY_NOT_FOUND); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); return false; diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java index d7d4f1c50e32..fcbb553c7214 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java @@ -765,11 +765,6 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { @Override public void engineDeleteEntry(String alias) throws KeyStoreException { - if (!engineContainsAlias(alias)) { - return; - } - // At least one entry corresponding to this alias exists in keystore - if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid)) { throw new KeyStoreException("Failed to delete entry: " + alias); } diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index e04b9a2b5fd7..5bce8ac83020 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -353,7 +353,7 @@ void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) { bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) { Caches& caches = Caches::getInstance(); - if (layer + if (layer && layer->getRenderTarget() != GL_NONE && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index b0411a2b63f5..abb6f4e9964c 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -212,7 +212,7 @@ import java.util.Objects; * AudioTrack.getPlaybackHeadPosition()}), * depending on the context where audio frame is used. */ -public class AudioFormat implements Parcelable { +public final class AudioFormat implements Parcelable { //--------------------------------------------------------- // Constants diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java index c2cd9b3d0637..2fc8ee82efa9 100644 --- a/media/java/android/media/AudioRecordConfiguration.java +++ b/media/java/android/media/AudioRecordConfiguration.java @@ -29,7 +29,7 @@ import java.util.Objects; * {@link AudioManager#getActiveRecordConfigurations()} method. * */ -public class AudioRecordConfiguration implements Parcelable { +public final class AudioRecordConfiguration implements Parcelable { private final static String TAG = new String("AudioRecordConfiguration"); private final int mSessionId; diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 247c4aea9106..f597440ccbb3 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -638,7 +638,7 @@ public class AudioSystem public static final int PHONE_STATE_RINGING = 1; public static final int PHONE_STATE_INCALL = 2; - // device categories config for setForceUse, must match AudioSystem::forced_config + // device categories config for setForceUse, must match audio_policy_forced_cfg_t public static final int FORCE_NONE = 0; public static final int FORCE_SPEAKER = 1; public static final int FORCE_HEADPHONES = 2; @@ -652,17 +652,20 @@ public class AudioSystem public static final int FORCE_NO_BT_A2DP = 10; public static final int FORCE_SYSTEM_ENFORCED = 11; public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12; - private static final int NUM_FORCE_CONFIG = 13; + public static final int FORCE_ENCODED_SURROUND_NEVER = 13; + public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14; + public static final int NUM_FORCE_CONFIG = 15; public static final int FORCE_DEFAULT = FORCE_NONE; - // usage for setForceUse, must match AudioSystem::force_use + // usage for setForceUse, must match audio_policy_force_use_t public static final int FOR_COMMUNICATION = 0; public static final int FOR_MEDIA = 1; public static final int FOR_RECORD = 2; public static final int FOR_DOCK = 3; public static final int FOR_SYSTEM = 4; public static final int FOR_HDMI_SYSTEM_AUDIO = 5; - private static final int NUM_FORCE_USE = 6; + public static final int FOR_ENCODED_SURROUND = 6; + private static final int NUM_FORCE_USE = 7; // usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t public static final int SYNC_EVENT_NONE = 0; diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index f02e8375f072..c48bfc532965 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1214,13 +1214,12 @@ public class AudioTrack implements AudioRouting * An underrun occurs if the application does not write audio * data quickly enough, causing the buffer to underflow * and a potential audio glitch or pop. + * <p> * Underruns are less likely when buffer sizes are large. - * <p> Though the "int" type is signed 32-bits, the value should be reinterpreted - * as if it is unsigned 32-bits. - * That is, the next position after 0x7FFFFFFF is (int) 0x80000000. - * This is a continuously advancing counter. It can wrap around to zero - * if there are too many underruns. If there were, for example, 68 underruns per - * second then the counter would wrap in 2 years. + * It may be possible to eliminate underruns by recreating the AudioTrack with + * a larger buffer. + * Or by using {@link #setBufferSizeInFrames(int)} to dynamically increase the + * effective size of the buffer. */ public int getUnderrunCount() { return native_get_underrun_count(); diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index f1f84375c36b..4c6f0e6258f1 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -2221,7 +2221,10 @@ final public class MediaCodec { public int mode; /** - * Metadata describing encryption pattern for the protected bytes in a subsample. + * Metadata describing an encryption pattern for the protected bytes in + * a subsample. An encryption pattern consists of a repeating sequence + * of crypto blocks comprised of a number of encrypted blocks followed + * by a number of unencrypted, or skipped, blocks. */ public final static class Pattern { /** @@ -2273,6 +2276,10 @@ final public class MediaCodec { */ private Pattern pattern; + /** + * Set the subsample count, clear/encrypted sizes, key, IV and mode fields of + * a {@link MediaCodec.CryptoInfo} instance. + */ public void set( int newNumSubSamples, @NonNull int[] newNumBytesOfClearData, @@ -2289,6 +2296,10 @@ final public class MediaCodec { pattern = new Pattern(0, 0); } + /** + * Set the encryption pattern on a {@link MediaCodec.CryptoInfo} instance. + * See {@link MediaCodec.CryptoInfo.Pattern}. + */ public void setPattern(Pattern newPattern) { pattern = newPattern; } @@ -3339,14 +3350,6 @@ final public class MediaCodec { } - private int readInt(@NonNull ByteBuffer buffer, boolean asLong) { - if (asLong) { - return (int)buffer.getLong(); - } else { - return buffer.getInt(); - } - } - public MediaImage( @NonNull ByteBuffer buffer, @NonNull ByteBuffer info, boolean readOnly, long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) { @@ -3361,39 +3364,46 @@ final public class MediaCodec { mYOffset = yOffset; mInfo = info; - // read media-info. the size of media info can be 80 or 156/160 depending on - // whether it was created on a 32- or 64-bit process. See MediaImage - if (info.remaining() == 80 || info.remaining() == 156 || info.remaining() == 160) { - boolean sizeIsLong = info.remaining() != 80; - int type = readInt(info, info.remaining() == 160); + // read media-info. See MediaImage2 + if (info.remaining() == 104) { + int type = info.getInt(); if (type != TYPE_YUV) { throw new UnsupportedOperationException("unsupported type: " + type); } - int numPlanes = readInt(info, sizeIsLong); + int numPlanes = info.getInt(); if (numPlanes != 3) { throw new RuntimeException("unexpected number of planes: " + numPlanes); } - mWidth = readInt(info, sizeIsLong); - mHeight = readInt(info, sizeIsLong); + mWidth = info.getInt(); + mHeight = info.getInt(); if (mWidth < 1 || mHeight < 1) { throw new UnsupportedOperationException( "unsupported size: " + mWidth + "x" + mHeight); } - int bitDepth = readInt(info, sizeIsLong); + int bitDepth = info.getInt(); if (bitDepth != 8) { throw new UnsupportedOperationException("unsupported bit depth: " + bitDepth); } + int bitDepthAllocated = info.getInt(); + if (bitDepthAllocated != 8) { + throw new UnsupportedOperationException( + "unsupported allocated bit depth: " + bitDepthAllocated); + } mPlanes = new MediaPlane[numPlanes]; for (int ix = 0; ix < numPlanes; ix++) { - int planeOffset = readInt(info, sizeIsLong); - int colInc = readInt(info, sizeIsLong); - int rowInc = readInt(info, sizeIsLong); - int horiz = readInt(info, sizeIsLong); - int vert = readInt(info, sizeIsLong); + int planeOffset = info.getInt(); + int colInc = info.getInt(); + int rowInc = info.getInt(); + int horiz = info.getInt(); + int vert = info.getInt(); if (horiz != vert || horiz != (ix == 0 ? 1 : 2)) { throw new UnsupportedOperationException("unexpected subsampling: " + horiz + "x" + vert + " on plane " + ix); } + if (colInc < 1 || rowInc < 1) { + throw new UnsupportedOperationException("unexpected strides: " + + colInc + " pixel, " + rowInc + " row on plane " + ix); + } buffer.clear(); buffer.position(mBuffer.position() + planeOffset diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index d9690f005364..b1c1b79732c5 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -2231,6 +2231,7 @@ public final class MediaCodecInfo { switch (profileLevel.profile) { case CodecProfileLevel.HEVCProfileMain: case CodecProfileLevel.HEVCProfileMain10: + case CodecProfileLevel.HEVCProfileMain10HDR10: break; default: Log.w(TAG, "Unrecognized profile " @@ -2632,8 +2633,9 @@ public final class MediaCodecInfo { public static final int VP9Level62 = 0x1000; // from OMX_VIDEO_HEVCPROFILETYPE - public static final int HEVCProfileMain = 0x01; - public static final int HEVCProfileMain10 = 0x02; + public static final int HEVCProfileMain = 0x01; + public static final int HEVCProfileMain10 = 0x02; + public static final int HEVCProfileMain10HDR10 = 0x1000; // from OMX_VIDEO_HEVCLEVELTYPE public static final int HEVCMainTierLevel1 = 0x1; diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java index 8618ec98c6c3..ebe509ce1a29 100644 --- a/media/java/android/media/MediaMuxer.java +++ b/media/java/android/media/MediaMuxer.java @@ -127,7 +127,8 @@ final public class MediaMuxer { * @param path The path of the output media file. * @param format The format of the output media file. * @see android.media.MediaMuxer.OutputFormat - * @throws IOException if failed to open the file for write + * @throws IllegalArgumentException if path is invalid or format is not supported. + * @throws IOException if failed to open the file for write. */ public MediaMuxer(@NonNull String path, @Format int format) throws IOException { if (path == null) { @@ -165,6 +166,8 @@ final public class MediaMuxer { * By default, the rotation degree is 0.</p> * @param degrees the angle to be rotated clockwise in degrees. * The supported angles are 0, 90, 180, and 270 degrees. + * @throws IllegalArgumentException if degree is not supported. + * @throws IllegalStateException If this method is called after {@link #start}. */ public void setOrientationHint(int degrees) { if (degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270) { @@ -217,6 +220,8 @@ final public class MediaMuxer { * Starts the muxer. * <p>Make sure this is called after {@link #addTrack} and before * {@link #writeSampleData}.</p> + * @throws IllegalStateException If this method is called after {@link #start} + * or Muxer is released */ public void start() { if (mNativeObject == 0) { @@ -233,6 +238,7 @@ final public class MediaMuxer { /** * Stops the muxer. * <p>Once the muxer stops, it can not be restarted.</p> + * @throws IllegalStateException if muxer is in the wrong state. */ public void stop() { if (mState == MUXER_STATE_STARTED) { @@ -264,6 +270,8 @@ final public class MediaMuxer { * MediaFormat. * @return The track index for this newly added track, and it should be used * in the {@link #writeSampleData}. + * @throws IllegalArgumentException if format is invalid. + * @throws IllegalStateException if muxer is in the wrong state. */ public int addTrack(@NonNull MediaFormat format) { if (format == null) { @@ -314,6 +322,8 @@ final public class MediaMuxer { * @param byteBuf The encoded sample. * @param trackIndex The track index for this sample. * @param bufferInfo The buffer information related to this sample. + * @throws IllegalArgumentException if trackIndex, byteBuf or bufferInfo is invalid. + * @throws IllegalStateException if muxer is in wrong state. * MediaMuxer uses the flags provided in {@link MediaCodec.BufferInfo}, * to signal sync frames. */ diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl index 5dd4e85efa2c..72f8b5773c9e 100644 --- a/media/java/android/media/tv/ITvInputClient.aidl +++ b/media/java/android/media/tv/ITvInputClient.aidl @@ -45,7 +45,7 @@ oneway interface ITvInputClient { void onTimeShiftCurrentPositionChanged(long timeMs, int seq); // For the recording session - void onTuned(int seq); + void onTuned(int seq, in Uri channelUri); void onRecordingStopped(in Uri recordedProgramUri, int seq); void onError(int error, int seq); } diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl index 60d6f0df9855..af76f9033b25 100644 --- a/media/java/android/media/tv/ITvInputSessionCallback.aidl +++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl @@ -42,7 +42,7 @@ oneway interface ITvInputSessionCallback { void onTimeShiftCurrentPositionChanged(long timeMs); // For the recording session - void onTuned(); + void onTuned(in Uri channelUri); void onRecordingStopped(in Uri recordedProgramUri); void onError(int error); } diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java index 6e0f5f2c1a43..63e3edcffa40 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -677,11 +677,12 @@ public final class TvInputInfo implements Parcelable { * Constructs a new builder for {@link TvInputInfo}. * * @param context A Context of the application package implementing this class. - * @param cls The component class that is to be used for the {@link TvInputService}. + * @param component The name of the application component to be used for the + * {@link TvInputService}. */ - public Builder(Context context, Class<?> cls) { + public Builder(Context context, ComponentName component) { mContext = context; - Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setClass(context, cls); + Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); mResolveInfo = context.getPackageManager().resolveService(intent, PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 2703b1ae13e8..59dfbeebfd80 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -478,8 +478,10 @@ public final class TvInputManager { /** * This is called when the recording session has been tuned to the given channel and is * ready to start recording. + * + * @param channelUri The URI of a channel. */ - void onTuned(Session session) { + void onTuned(Session session, Uri channelUri) { } // For the recording session only @@ -653,11 +655,11 @@ public final class TvInputManager { } // For the recording session only - void postTuned() { + void postTuned(final Uri channelUri) { mHandler.post(new Runnable() { @Override public void run() { - mSessionCallback.onTuned(mSession); + mSessionCallback.onTuned(mSession, channelUri); } }); } @@ -1013,14 +1015,14 @@ public final class TvInputManager { } @Override - public void onTuned(int seq) { + public void onTuned(int seq, Uri channelUri) { synchronized (mSessionCallbackRecordMap) { SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); if (record == null) { Log.e(TAG, "Callback not found for seq " + seq); return; } - record.postTuned(); + record.postTuned(channelUri); } } diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index db851a31d363..8fb58b5ce068 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -1567,8 +1567,10 @@ public abstract class TvInputService extends Service { * passed channel and call this method to indicate that it is now available for immediate * recording. When {@link #onStartRecording(Uri)} is called, recording must start with * minimal delay. + * + * @param channelUri The URI of a channel. */ - public void notifyTuned() { + public void notifyTuned(Uri channelUri) { executeOrPostRunnableOnMainThread(new Runnable() { @MainThread @Override @@ -1576,7 +1578,7 @@ public abstract class TvInputService extends Service { try { if (DEBUG) Log.d(TAG, "notifyTuned"); if (mSessionCallback != null) { - mSessionCallback.onTuned(); + mSessionCallback.onTuned(channelUri); } } catch (RemoteException e) { Log.w(TAG, "error in notifyTuned", e); @@ -1679,7 +1681,7 @@ public abstract class TvInputService extends Service { * <p>The application may call this method before starting or after stopping recording, but * not during recording. * - * <p>The session must call {@link #notifyTuned()} if the tune request was fulfilled, or + * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or * {@link #notifyError(int)} otherwise. * * @param channelUri The URI of a channel. @@ -1708,8 +1710,8 @@ public abstract class TvInputService extends Service { * Called when the application requests to start TV program recording. Recording must start * immediately when this method is called. * - * <p>The application may supply the URI for a TV program as a hint for filling in program - * specific data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table. + * <p>The application may supply the URI for a TV program for filling in program specific + * data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table. * A non-null {@code programHint} implies the started recording should be of that specific * program, whereas null {@code programHint} does not impose such a requirement and the * recording can span across multiple TV programs. In either case, the application must call @@ -1718,10 +1720,10 @@ public abstract class TvInputService extends Service { * <p>The session must call {@link #notifyError(int)} if the start request cannot be * fulfilled. * - * @param programHint The URI for the TV program to record as a hint, built by + * @param programUri The URI for the TV program to record, built by * {@link TvContract#buildProgramUri(long)}. Can be {@code null}. */ - public abstract void onStartRecording(@Nullable Uri programHint); + public abstract void onStartRecording(@Nullable Uri programUri); /** * Called when the application requests to stop TV program recording. Recording must stop diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java index 1c920f57de2a..d48ea21e07d9 100644 --- a/media/java/android/media/tv/TvRecordingClient.java +++ b/media/java/android/media/tv/TvRecordingClient.java @@ -76,11 +76,12 @@ public class TvRecordingClient { * during recording. * * <p>The recording session will respond by calling - * {@link RecordingCallback#onTuned()} if the tune request was fulfilled, or + * {@link RecordingCallback#onTuned(Uri)} if the tune request was fulfilled, or * {@link RecordingCallback#onError(int)} otherwise. * * @param inputId The ID of the TV input for the given channel. * @param channelUri The URI of a channel. + * @throws IllegalStateException If recording is already started. */ public void tune(String inputId, Uri channelUri) { tune(inputId, channelUri, null); @@ -102,6 +103,7 @@ public class TvRecordingClient { * @param inputId The ID of the TV input for the given channel. * @param channelUri The URI of a channel. * @param params Extra parameters. + * @throws IllegalStateException If recording is already started. * @hide */ @SystemApi @@ -152,8 +154,8 @@ public class TvRecordingClient { * immediately when this method is called. If the current recording session has not yet tuned to * any channel, this method throws an exception. * - * <p>The application may supply the URI for a TV program as a hint for filling in program - * specific data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table. + * <p>The application may supply the URI for a TV program for filling in program specific data + * fields in the {@link android.media.tv.TvContract.RecordedPrograms} table. * A non-null {@code programHint} implies the started recording should be of that specific * program, whereas null {@code programHint} does not impose such a requirement and the * recording can span across multiple TV programs. In either case, the application must call @@ -162,15 +164,16 @@ public class TvRecordingClient { * <p>The recording session will respond by calling {@link RecordingCallback#onError(int)} if * the start request cannot be fulfilled. * - * @param programHint The URI for the TV program to record as a hint, built by + * @param programUri The URI for the TV program to record, built by * {@link TvContract#buildProgramUri(long)}. Can be {@code null}. + * @throws IllegalStateException If {@link #tune} request hasn't been handled yet. */ - public void startRecording(@Nullable Uri programHint) { + public void startRecording(@Nullable Uri programUri) { if (!mIsTuned) { throw new IllegalStateException("startRecording failed - not yet tuned"); } if (mSession != null) { - mSession.startRecording(programHint); + mSession.startRecording(programUri); mIsRecordingStarted = true; } } @@ -245,8 +248,10 @@ public class TvRecordingClient { /** * This is called when the recording session has been tuned to the given channel and is * ready to start recording. + * + * @param channelUri The URI of a channel. */ - public void onTuned() { + public void onTuned(Uri channelUri) { } /** @@ -327,7 +332,7 @@ public class TvRecordingClient { } @Override - void onTuned(TvInputManager.Session session) { + void onTuned(TvInputManager.Session session, Uri channelUri) { if (DEBUG) { Log.d(TAG, "onTuned()"); } @@ -336,7 +341,7 @@ public class TvRecordingClient { return; } mIsTuned = true; - mCallback.onTuned(); + mCallback.onTuned(channelUri); } @Override diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 29bcc1928115..760a2d13eecb 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -713,8 +713,7 @@ public class MtpDatabase implements AutoCloseable { }; } - - private MtpPropertyList getObjectPropertyList(long handle, int format, long property, + private MtpPropertyList getObjectPropertyList(int handle, int format, int property, int groupCode, int depth) { // FIXME - implement group support if (groupCode != 0) { @@ -722,29 +721,29 @@ public class MtpDatabase implements AutoCloseable { } MtpPropertyGroup propertyGroup; - if (property == 0xFFFFFFFFL) { - if (format == 0 && handle > 0) { + if (property == 0xffffffff) { + if (format == 0 && handle != 0 && handle != 0xffffffff) { // return properties based on the object's format - format = getObjectFormat((int)handle); + format = getObjectFormat(handle); } - propertyGroup = mPropertyGroupsByFormat.get(format); - if (propertyGroup == null) { + propertyGroup = mPropertyGroupsByFormat.get(format); + if (propertyGroup == null) { int[] propertyList = getSupportedObjectProperties(format); propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList); - mPropertyGroupsByFormat.put(new Integer(format), propertyGroup); + mPropertyGroupsByFormat.put(format, propertyGroup); } } else { - propertyGroup = mPropertyGroupsByProperty.get(property); - if (propertyGroup == null) { - int[] propertyList = new int[] { (int)property }; - propertyGroup = new MtpPropertyGroup(this, mMediaProvider, - mVolumeName, propertyList); - mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup); + propertyGroup = mPropertyGroupsByProperty.get(property); + if (propertyGroup == null) { + final int[] propertyList = new int[] { property }; + propertyGroup = new MtpPropertyGroup( + this, mMediaProvider, mVolumeName, propertyList); + mPropertyGroupsByProperty.put(property, propertyGroup); } } - return propertyGroup.getPropertyList((int)handle, format, depth); + return propertyGroup.getPropertyList(handle, format, depth); } private int renameFile(int handle, String newName) { @@ -970,7 +969,7 @@ public class MtpDatabase implements AutoCloseable { Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, FORMAT_PROJECTION, - ID_WHERE, new String[] { Integer.toString(handle) }, null, null); + ID_WHERE, new String[] { Integer.toString(handle) }, null, null); if (c != null && c.moveToNext()) { return c.getInt(1); } else { diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index 556f2c770648..5722cb013026 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -231,11 +231,11 @@ MyMtpDatabase::~MyMtpDatabase() { } MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path, - MtpObjectFormat format, - MtpObjectHandle parent, - MtpStorageID storage, - uint64_t size, - time_t modified) { + MtpObjectFormat format, + MtpObjectHandle parent, + MtpStorageID storage, + uint64_t size, + time_t modified) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jstring pathStr = env->NewStringUTF(path); MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject, @@ -249,7 +249,7 @@ MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path, } void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle, - MtpObjectFormat format, bool succeeded) { + MtpObjectFormat format, bool succeeded) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jstring pathStr = env->NewStringUTF(path); env->CallVoidMethod(mDatabase, method_endSendObject, pathStr, @@ -261,8 +261,8 @@ void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle, } MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID, - MtpObjectFormat format, - MtpObjectHandle parent) { + MtpObjectFormat format, + MtpObjectHandle parent) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList, (jint)storageID, (jint)format, (jint)parent); @@ -281,8 +281,8 @@ MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID, } int MyMtpDatabase::getNumObjects(MtpStorageID storageID, - MtpObjectFormat format, - MtpObjectHandle parent) { + MtpObjectFormat format, + MtpObjectHandle parent) { JNIEnv* env = AndroidRuntime::getJNIEnv(); int result = env->CallIntMethod(mDatabase, method_getNumObjects, (jint)storageID, (jint)format, (jint)parent); @@ -364,11 +364,21 @@ MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() { } MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle, - MtpObjectProperty property, - MtpDataPacket& packet) { + MtpObjectProperty property, + MtpDataPacket& packet) { + static_assert(sizeof(jint) >= sizeof(MtpObjectHandle), + "Casting MtpObjectHandle to jint loses a value"); + static_assert(sizeof(jint) >= sizeof(MtpObjectProperty), + "Casting MtpObjectProperty to jint loses a value"); JNIEnv* env = AndroidRuntime::getJNIEnv(); - jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList, - (jlong)handle, 0, (jlong)property, 0, 0); + jobject list = env->CallObjectMethod( + mDatabase, + method_getObjectPropertyList, + static_cast<jint>(handle), + 0, + static_cast<jint>(property), + 0, + 0); MtpResponseCode result = env->GetIntField(list, field_mResult); int count = env->GetIntField(list, field_mCount); if (result == MTP_RESPONSE_OK && count != 1) @@ -532,8 +542,8 @@ static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) { } MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle, - MtpObjectProperty property, - MtpDataPacket& packet) { + MtpObjectProperty property, + MtpDataPacket& packet) { int type; if (!getObjectPropertyInfo(property, type)) @@ -563,7 +573,7 @@ fail: } MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property, - MtpDataPacket& packet) { + MtpDataPacket& packet) { JNIEnv* env = AndroidRuntime::getJNIEnv(); if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) { @@ -636,7 +646,7 @@ MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property } MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, - MtpDataPacket& packet) { + MtpDataPacket& packet) { int type; if (!getDevicePropertyInfo(property, type)) @@ -670,12 +680,20 @@ MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property* } MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, - uint32_t format, uint32_t property, - int groupCode, int depth, - MtpDataPacket& packet) { + uint32_t format, uint32_t property, + int groupCode, int depth, + MtpDataPacket& packet) { + static_assert(sizeof(jint) >= sizeof(MtpObjectHandle), + "Casting MtpObjectHandle to jint loses a value"); JNIEnv* env = AndroidRuntime::getJNIEnv(); - jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList, - (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth); + jobject list = env->CallObjectMethod( + mDatabase, + method_getObjectPropertyList, + static_cast<jint>(handle), + static_cast<jint>(format), + static_cast<jint>(property), + static_cast<jint>(groupCode), + static_cast<jint>(depth)); checkAndClearExceptionFromCallback(env, __FUNCTION__); if (!list) return MTP_RESPONSE_GENERAL_ERROR; @@ -787,7 +805,7 @@ static long getLongFromExifEntry(ExifEntry *e) { } MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, - MtpObjectInfo& info) { + MtpObjectInfo& info) { MtpString path; int64_t length; MtpObjectFormat format; @@ -940,9 +958,9 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) } MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, - MtpString& outFilePath, - int64_t& outFileLength, - MtpObjectFormat& outFormat) { + MtpString& outFilePath, + int64_t& outFileLength, + MtpObjectFormat& outFormat) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath, (jint)handle, mStringBuffer, mLongBuffer); @@ -1056,7 +1074,7 @@ MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) } MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle, - MtpObjectHandleList* references) { + MtpObjectHandleList* references) { JNIEnv* env = AndroidRuntime::getJNIEnv(); int count = references->size(); jintArray array = env->NewIntArray(count); @@ -1077,7 +1095,7 @@ MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle, } MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property, - MtpObjectFormat format) { + MtpObjectFormat format) { static const int channelEnum[] = { 1, // mono 2, // stereo @@ -1313,7 +1331,7 @@ int register_android_mtp_MtpDatabase(JNIEnv *env) return -1; } method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList", - "(JIJII)Landroid/mtp/MtpPropertyList;"); + "(IIIII)Landroid/mtp/MtpPropertyList;"); if (method_getObjectPropertyList == NULL) { ALOGE("Can't find getObjectPropertyList"); return -1; diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml index b169ec89320a..29f65e09f184 100644 --- a/packages/DocumentsUI/res/layout/item_doc_list.xml +++ b/packages/DocumentsUI/res/layout/item_doc_list.xml @@ -73,7 +73,8 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:orientation="vertical" > + android:orientation="vertical" + android:layout_gravity="center_vertical" > <TextView android:id="@android:id/title" diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java index bff65d5b5caf..dcaea15459a6 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java @@ -16,10 +16,12 @@ package com.android.documentsui; +import static android.os.Environment.STANDARD_DIRECTORIES; import static com.android.documentsui.Shared.DEBUG; - import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.StringDef; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; @@ -32,6 +34,7 @@ import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperationService; import com.android.documentsui.services.FileOperationService.OpType; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.MetricsProto.MetricsEvent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -376,6 +379,84 @@ public final class Metrics { logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA)); } + // Types for logInvalidScopedAccessRequest + public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS = + "scoped_directory_access_invalid_args"; + public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY = + "scoped_directory_access_invalid_dir"; + public static final String SCOPED_DIRECTORY_ACCESS_ERROR = + "scoped_directory_access_error"; + + @StringDef(value = { + SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS, + SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY, + SCOPED_DIRECTORY_ACCESS_ERROR + }) + @Retention(RetentionPolicy.SOURCE) + public @interface InvalidScopedAccess{} + + public static void logInvalidScopedAccessRequest(Context context, + @InvalidScopedAccess String type) { + MetricsLogger.count(context, type, 1); + switch (type) { + case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS: + case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY: + case SCOPED_DIRECTORY_ACCESS_ERROR: + MetricsLogger.count(context, type, 1); + break; + default: + Log.wtf(TAG, "invalid InvalidScopedAccess: " + type); + } + } + + // Types for logValidScopedAccessRequest + public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0; + public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1; + public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2; + + @IntDef(flag = true, value = { + SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED, + SCOPED_DIRECTORY_ACCESS_GRANTED, + SCOPED_DIRECTORY_ACCESS_DENIED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ScopedAccessGrant {} + + public static void logValidScopedAccessRequest(Activity activity, String directory, + @ScopedAccessGrant int type) { + int index = -1; + for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) { + if (STANDARD_DIRECTORIES[i].equals(directory)) { + index = i; + break; + } + } + final String packageName = activity.getCallingPackage(); + switch (type) { + case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED: + MetricsLogger.action(activity, + MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, + packageName); + MetricsLogger.action(activity, + MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index); + break; + case SCOPED_DIRECTORY_ACCESS_GRANTED: + MetricsLogger.action(activity, + MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName); + MetricsLogger.action(activity, + MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index); + break; + case SCOPED_DIRECTORY_ACCESS_DENIED: + MetricsLogger.action(activity, + MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName); + MetricsLogger.action(activity, + MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index); + break; + default: + Log.wtf(TAG, "invalid ScopedAccessGrant: " + type); + } + } + /** * Internal method for making a MetricsLogger.count call. Increments the given counter by 1. * diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java index 27d6797fdce6..dc529ceb18ec 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java @@ -17,9 +17,18 @@ package com.android.documentsui; import static android.os.Environment.isStandardDirectory; +import static android.os.Environment.STANDARD_DIRECTORIES; import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME; import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME; import static com.android.documentsui.Shared.DEBUG; +import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest; +import static com.android.documentsui.Metrics.logValidScopedAccessRequest; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY; import android.app.Activity; import android.app.ActivityManager; @@ -73,6 +82,7 @@ public class OpenExternalDirectoryActivity extends Activity { final Intent intent = getIntent(); if (intent == null) { if (DEBUG) Log.d(TAG, "missing intent"); + logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS); setResult(RESULT_CANCELED); finish(); return; @@ -82,12 +92,14 @@ public class OpenExternalDirectoryActivity extends Activity { if (DEBUG) Log.d(TAG, "extra " + EXTRA_STORAGE_VOLUME + " is not a StorageVolume: " + storageVolume); + logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS); setResult(RESULT_CANCELED); finish(); return; } final String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME); if (directoryName == null) { + logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS); if (DEBUG) Log.d(TAG, "missing extra " + EXTRA_DIRECTORY_NAME + " on " + intent); setResult(RESULT_CANCELED); finish(); @@ -125,6 +137,7 @@ public class OpenExternalDirectoryActivity extends Activity { } catch (IOException e) { Log.e(TAG, "Could not get canonical file for volume " + storageVolume.dump() + " and directory " + directoryName); + logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR); return false; } final StorageManager sm = @@ -138,6 +151,7 @@ public class OpenExternalDirectoryActivity extends Activity { if (DEBUG) Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '" + file.getAbsolutePath() + "')"); + logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY); return false; } @@ -159,6 +173,8 @@ public class OpenExternalDirectoryActivity extends Activity { // Checks if the user has granted the permission already. final Intent intent = getIntentForExistingPermission(activity, file); if (intent != null) { + logValidScopedAccessRequest(activity, directory, + SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED); activity.setResult(RESULT_OK, intent); activity.finish(); return true; @@ -166,12 +182,14 @@ public class OpenExternalDirectoryActivity extends Activity { if (volumeLabel == null) { Log.e(TAG, "Could not get volume for " + file); + logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR); return false; } // Gets the package label. final String appLabel = getAppLabel(activity); if (appLabel == null) { + // Error already logged. return false; } @@ -198,6 +216,7 @@ public class OpenExternalDirectoryActivity extends Activity { try { return pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString(); } catch (NameNotFoundException e) { + logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR); Log.w(TAG, "Could not get label for package " + packageName); return null; } @@ -217,18 +236,21 @@ public class OpenExternalDirectoryActivity extends Activity { return volume.isVisibleForWrite(userId) && root.equals(path); } - private static Uri getGrantedUriPermission(ContentProviderClient provider, File file) { + private static Uri getGrantedUriPermission(Context context, ContentProviderClient provider, + File file) { // Calls ExternalStorageProvider to get the doc id for the file final Bundle bundle; try { bundle = provider.call("getDocIdForFileCreateNewDir", file.getPath(), null); } catch (RemoteException e) { Log.e(TAG, "Did not get doc id from External Storage provider for " + file, e); + logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR); return null; } final String docId = bundle == null ? null : bundle.getString("DOC_ID"); if (docId == null) { Log.e(TAG, "Did not get doc id from External Storage provider for " + file); + logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR); return null; } Log.d(TAG, "doc id for " + file + ": " + docId); @@ -242,9 +264,9 @@ public class OpenExternalDirectoryActivity extends Activity { return uri; } - private static Intent createGrantedUriPermissionsIntent(ContentProviderClient provider, - File file) { - final Uri uri = getGrantedUriPermission(provider, file); + private static Intent createGrantedUriPermissionsIntent(Context context, + ContentProviderClient provider, File file) { + final Uri uri = getGrantedUriPermission(context, provider, file); return createGrantedUriPermissionsIntent(uri); } @@ -261,7 +283,8 @@ public class OpenExternalDirectoryActivity extends Activity { private static Intent getIntentForExistingPermission(OpenExternalDirectoryActivity activity, File file) { final String packageName = activity.getCallingPackage(); - final Uri grantedUri = getGrantedUriPermission(activity.getExternalStorageClient(), file); + final Uri grantedUri = + getGrantedUriPermission(activity, activity.getExternalStorageClient(), file); if (DEBUG) Log.d(TAG, "checking if " + packageName + " already has permission for " + grantedUri); final ActivityManager am = @@ -298,7 +321,7 @@ public class OpenExternalDirectoryActivity extends Activity { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final String folder = mFile.getName(); + final String directory = mFile.getName(); final Activity activity = getActivity(); final OnClickListener listener = new OnClickListener() { @@ -306,12 +329,16 @@ public class OpenExternalDirectoryActivity extends Activity { public void onClick(DialogInterface dialog, int which) { Intent intent = null; if (which == DialogInterface.BUTTON_POSITIVE) { - intent = createGrantedUriPermissionsIntent( + intent = createGrantedUriPermissionsIntent(mActivity, mActivity.getExternalStorageClient(), mFile); } if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) { + logValidScopedAccessRequest(activity, directory, + SCOPED_DIRECTORY_ACCESS_DENIED); activity.setResult(RESULT_CANCELED); } else { + logValidScopedAccessRequest(activity, directory, + SCOPED_DIRECTORY_ACCESS_GRANTED); activity.setResult(RESULT_OK, intent); } activity.finish(); @@ -320,7 +347,7 @@ public class OpenExternalDirectoryActivity extends Activity { final CharSequence message = TextUtils .expandTemplate( - getText(R.string.open_external_dialog_request), mAppLabel, folder, + getText(R.string.open_external_dialog_request), mAppLabel, directory, mVolumeLabel); return new AlertDialog.Builder(activity, R.style.AlertDialogTheme) .setMessage(message) @@ -333,6 +360,7 @@ public class OpenExternalDirectoryActivity extends Activity { public void onCancel(DialogInterface dialog) { super.onCancel(dialog); final Activity activity = getActivity(); + logValidScopedAccessRequest(activity, mFile.getName(), SCOPED_DIRECTORY_ACCESS_DENIED); activity.setResult(RESULT_CANCELED); activity.finish(); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index ab67a51265e9..6856129cb530 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -115,7 +115,13 @@ public class RootsCache { * Gather roots from all known storage providers. */ public void updateAsync() { - // Verifying an assumption about the recents root being immutable. + + // NOTE: This method is called when the UI language changes. + // For that reason we upadte our RecentsRoot to reflect + // the current language. + mRecentsRoot.title = mContext.getString(R.string.root_recent); + + // Nothing else about the root should ever change. assert(mRecentsRoot.authority == null); assert(mRecentsRoot.rootId == null); assert(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent); @@ -123,7 +129,6 @@ public class RootsCache { assert(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE)); - assert(mRecentsRoot.title == mContext.getString(R.string.root_recent)); assert(mRecentsRoot.availableBytes == -1); new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java index b940ffbcda30..11f9aa710349 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java @@ -29,6 +29,7 @@ import android.text.format.Formatter; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.android.documentsui.R; @@ -38,9 +39,10 @@ import com.android.documentsui.State; final class ListDocumentHolder extends DocumentHolder { final TextView mTitle; - final TextView mSummary; + final LinearLayout mDetails; // Container of date/size/summary final TextView mDate; final TextView mSize; + final TextView mSummary; final ImageView mIconMime; final ImageView mIconThumb; final ImageView mIconCheck; @@ -50,9 +52,10 @@ final class ListDocumentHolder extends DocumentHolder { super(context, parent, R.layout.item_doc_list); mTitle = (TextView) itemView.findViewById(android.R.id.title); - mSummary = (TextView) itemView.findViewById(android.R.id.summary); + mDetails = (LinearLayout) itemView.findViewById(R.id.line2); mDate = (TextView) itemView.findViewById(R.id.date); mSize = (TextView) itemView.findViewById(R.id.size); + mSummary = (TextView) itemView.findViewById(android.R.id.summary); mIconMime = (ImageView) itemView.findViewById(R.id.icon_mime); mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb); mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check); @@ -91,6 +94,7 @@ final class ListDocumentHolder extends DocumentHolder { final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY); final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE); + final boolean isDirectory = Document.MIME_TYPE_DIR.equals(docMimeType); mIconHelper.stopLoading(mIconThumb); @@ -105,24 +109,36 @@ final class ListDocumentHolder extends DocumentHolder { mTitle.setText(docDisplayName, TextView.BufferType.SPANNABLE); mTitle.setVisibility(View.VISIBLE); - if (docSummary != null) { - mSummary.setText(docSummary); - mSummary.setVisibility(View.VISIBLE); - } else { - mSummary.setVisibility(View.INVISIBLE); - } - - if (docLastModified == -1) { - mDate.setText(null); - } else { - mDate.setText(Shared.formatTime(mContext, docLastModified)); - } - if (!state.showSize || Document.MIME_TYPE_DIR.equals(docMimeType) || docSize == -1) { - mSize.setVisibility(View.GONE); + // Note, we don't show any details for any directory...ever. + if (isDirectory) { + mDetails.setVisibility(View.GONE); } else { - mSize.setVisibility(View.VISIBLE); - mSize.setText(Formatter.formatFileSize(mContext, docSize)); + boolean hasDetails = false; + if (docSummary != null) { + hasDetails = true; + mSummary.setText(docSummary); + mSummary.setVisibility(View.VISIBLE); + } else { + mSummary.setVisibility(View.INVISIBLE); + } + + if (docLastModified == -1) { + hasDetails = true; + mDate.setText(null); + } else { + mDate.setText(Shared.formatTime(mContext, docLastModified)); + } + + if (!state.showSize || docSize == -1) { + hasDetails = true; + mSize.setVisibility(View.GONE); + mDetails.setVisibility(View.GONE); + } else { + mSize.setVisibility(View.VISIBLE); + mSize.setText(Formatter.formatFileSize(mContext, docSize)); + } + mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE); } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java index adcfef333def..4b98aaf940e9 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java @@ -93,7 +93,6 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen bots = new Bots(device, context, TIMEOUT); Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE); - bots.main.revealLauncher(); mResolver = context.getContentResolver(); mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY); @@ -103,8 +102,6 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen rootDir1 = mDocsHelper.getRoot(ROOT_1_ID); launchActivity(); - - bots.main.revealApp(); resetStorage(); } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java index a112081dda26..11f519411448 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java @@ -212,16 +212,6 @@ public class UiBot extends BaseBot { return mDevice.findObject(selector); } - public void revealLauncher() { - mDevice.pressHome(); - mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), mTimeout); - } - - public void revealApp() { - mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), mTimeout); - mDevice.waitForIdle(); - } - public void pressKey(int keyCode) { mDevice.pressKeyCode(keyCode); } diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 97dfd47aea9f..97527ddf3222 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -391,6 +391,10 @@ public class ExternalStorageProvider extends DocumentsProvider { if (mArchiveHelper.isArchivedDocument(docId)) { return mArchiveHelper.isChildDocument(parentDocId, docId); } + // Archives do not contain regular files. + if (mArchiveHelper.isArchivedDocument(parentDocId)) { + return false; + } final File parent = getFileForDocId(parentDocId).getCanonicalFile(); final File doc = getFileForDocId(docId).getCanonicalFile(); diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index 63c4ef8bb8c4..c031f34a37da 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -404,6 +404,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { for (final int id : keySet) { closeDeviceInternal(id); } + mRootScanner.pause(); } catch (InterruptedException|IOException e) { // It should fail unit tests by throwing runtime exception. throw new RuntimeException(e); diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java index 82ba21f659d1..2f66c5cf17d7 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java @@ -26,7 +26,6 @@ import java.io.FileNotFoundException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; final class RootScanner { @@ -56,7 +55,7 @@ final class RootScanner { final MtpDatabase mDatabase; ExecutorService mExecutor; - FutureTask<Void> mCurrentTask; + private UpdateRootsRunnable mCurrentTask; RootScanner( ContentResolver resolver, @@ -84,13 +83,12 @@ final class RootScanner { mExecutor = Executors.newSingleThreadExecutor(); } if (mCurrentTask != null) { - // Cancel previous task. - mCurrentTask.cancel(true); + // Stop previous task. + mCurrentTask.stop(); } - final UpdateRootsRunnable runnable = new UpdateRootsRunnable(); - mCurrentTask = new FutureTask<Void>(runnable, null); - mExecutor.submit(mCurrentTask); - return runnable.mFirstScanCompleted; + mCurrentTask = new UpdateRootsRunnable(); + mExecutor.execute(mCurrentTask); + return mCurrentTask.mFirstScanCompleted; } /** @@ -112,13 +110,21 @@ final class RootScanner { * Runnable to scan roots and update the database information. */ private final class UpdateRootsRunnable implements Runnable { + /** + * Count down latch that specifies the runnable is stopped. + */ + final CountDownLatch mStopped = new CountDownLatch(1); + + /** + * Count down latch that specifies the first scan is completed. + */ final CountDownLatch mFirstScanCompleted = new CountDownLatch(1); @Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); int pollingCount = 0; - while (true) { + while (mStopped.getCount() > 0) { boolean changed = false; // Update devices. @@ -171,12 +177,16 @@ final class RootScanner { // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is // more likely to add new root just after the device is added. // TODO: Use short interval only for a device that is just added. - Thread.sleep(pollingCount > SHORT_POLLING_TIMES ? - LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL); + mStopped.await(pollingCount > SHORT_POLLING_TIMES ? + LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL, TimeUnit.MILLISECONDS); } catch (InterruptedException exp) { break; } } } + + void stop() { + mStopped.countDown(); + } } } diff --git a/packages/Shell/res/layout/dialog_bugreport_info.xml b/packages/Shell/res/layout/dialog_bugreport_info.xml index 5d1e9f994946..b6b8d6bcf2b2 100644 --- a/packages/Shell/res/layout/dialog_bugreport_info.xml +++ b/packages/Shell/res/layout/dialog_bugreport_info.xml @@ -16,28 +16,44 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:paddingTop="15dp" + android:paddingStart="24dp" + android:paddingEnd="24dp" android:layout_width="wrap_content" android:layout_height="wrap_content"> + <TextView + android:inputType="textNoSuggestions" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/bugreport_info_name"/> <EditText android:id="@+id/name" android:maxLength="30" android:singleLine="true" + android:selectAllOnFocus="true" android:inputType="textNoSuggestions" android:layout_width="match_parent" + android:layout_height="wrap_content"/> + <TextView + android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="@string/bugreport_info_name"/> + android:text="@string/bugreport_info_title"/> <EditText android:id="@+id/title" android:maxLength="80" android:singleLine="true" + android:inputType="textAutoCorrect|textCapSentences" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + <TextView android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="@string/bugreport_info_title"/> + android:editable="false" + android:text="@string/bugreport_info_description"/> <EditText android:id="@+id/description" android:singleLine="false" - android:inputType="textMultiLine" + android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:hint="@string/bugreport_info_description"/> + android:layout_height="wrap_content"/> </LinearLayout> diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml index c26b54978e1d..38ea8804a2d8 100644 --- a/packages/Shell/res/values/strings.xml +++ b/packages/Shell/res/values/strings.xml @@ -59,13 +59,16 @@ <!-- Title of the dialog asking for user-defined bug report details like name, title, and description. --> <string name="bugreport_info_dialog_title">Bug report <xliff:g id="id">#%d</xliff:g> details</string> - <!-- Text of the hint asking for the bug report name, which when set will define a suffix in the + <!-- Text of the label identifying the bug report name, which when set will define a suffix in the bug report file names. [CHAR LIMIT=30] --> <string name="bugreport_info_name">Filename</string> - <!-- Text of hint asking for the bug report title, which when set will define the + <!-- Text of the label identifying the bug report title, which when set will define the Subject of the email message. [CHAR LIMIT=60] --> - <string name="bugreport_info_title">Title</string> - <!-- Text of hint asking for the bug report description, which when set will describe + <string name="bugreport_info_title">Bug title</string> + <!-- Text of the label identifying the bug report description, which when set will describe what the bug report is about. [CHAR LIMIT=NONE] --> - <string name="bugreport_info_description">Detailed description</string> + <string name="bugreport_info_description">Bug summary</string> + + <!-- Label of button that save bugreport details. --> + <string name="save">Save</string> </resources> diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 36097a124ff9..0b5258895775 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -601,7 +601,8 @@ public class BugreportProgressService extends Service { // Most likely am killed Shell before user tapped the notification. Since system might // be too busy anwyays, it's better to ignore the notification and switch back to the // non-interactive mode (where the bugerport will be shared upon completion). - Log.d(TAG, "launchBugreportInfoDialog(" + id + "): cancel notification"); + Log.w(TAG, "launchBugreportInfoDialog(): canceling notification because id " + id + + " was not found"); // TODO: add test case to make sure notification is canceled. NotificationManager.from(mContext).cancel(TAG, id); return; @@ -627,7 +628,8 @@ public class BugreportProgressService extends Service { // Most likely am killed Shell before user tapped the notification. Since system might // be too busy anwyays, it's better to ignore the notification and switch back to the // non-interactive mode (where the bugerport will be shared upon completion). - Log.d(TAG, "takeScreenshot(" + id + ", " + delayed + "): cancel notification"); + Log.w(TAG, "takeScreenshot(): canceling notification because id " + id + + " was not found"); // TODO: add test case to make sure notification is canceled. NotificationManager.from(mContext).cancel(TAG, id); return; @@ -1268,6 +1270,9 @@ public class BugreportProgressService extends Service { if (hasFocus) { return; } + // Select-all is useful just initially, since the date-based filename is + // full of hyphens. + mInfoName.setSelectAllOnFocus(false); sanitizeName(); } }); @@ -1276,7 +1281,7 @@ public class BugreportProgressService extends Service { .setView(view) .setTitle(dialogTitle) .setCancelable(false) - .setPositiveButton(context.getString(com.android.internal.R.string.ok), + .setPositiveButton(context.getString(R.string.save), null) .setNegativeButton(context.getString(com.android.internal.R.string.cancel), new DialogInterface.OnClickListener() diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java index d0499a5e3946..a629aac33d25 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java @@ -400,8 +400,8 @@ public class BugreportReceiverTest extends InstrumentationTestCase { DetailsUi detailsUi = new DetailsUi(mUiBot, ID); detailsUi.assertName(NAME); - detailsUi.assertTitle(mContext.getString(R.string.bugreport_info_title)); - detailsUi.assertDescription(mContext.getString(R.string.bugreport_info_description)); + detailsUi.assertTitle(""); + detailsUi.assertDescription(""); detailsUi.nameField.setText(NEW_NAME); detailsUi.titleField.setText(TITLE); detailsUi.descField.setText(DESCRIPTION); @@ -415,8 +415,8 @@ public class BugreportReceiverTest extends InstrumentationTestCase { detailsUi = new DetailsUi(mUiBot, ID2); detailsUi.assertName(NAME2); - detailsUi.assertTitle(mContext.getString(R.string.bugreport_info_title)); - detailsUi.assertDescription(mContext.getString(R.string.bugreport_info_description)); + detailsUi.assertTitle(""); + detailsUi.assertDescription(""); detailsUi.nameField.setText(NEW_NAME2); detailsUi.titleField.setText(TITLE2); detailsUi.descField.setText(DESCRIPTION2); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index c590ec7a97dd..b5b7bcd743d5 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -82,6 +82,7 @@ <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" /> <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" /> <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" /> + <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" /> <!-- WindowManager --> <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" /> diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/qs_background_secondary.xml deleted file mode 100644 index 31c01629cf67..000000000000 --- a/packages/SystemUI/res/drawable/qs_background_secondary.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@color/system_secondary_color" /> - <corners - android:topLeftRadius="0dp" - android:topRightRadius="0dp" /> -</shape> diff --git a/packages/SystemUI/res/drawable/qs_customizer_background.xml b/packages/SystemUI/res/drawable/qs_customizer_background.xml index 6bb27cc2a517..d90f820f5d4d 100644 --- a/packages/SystemUI/res/drawable/qs_customizer_background.xml +++ b/packages/SystemUI/res/drawable/qs_customizer_background.xml @@ -15,5 +15,5 @@ --> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/qs_detail_transition" /> - <item android:drawable="?android:attr/windowBackground" /> + <item android:drawable="@color/system_primary_color" /> </transition> diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml index 62f2b479cde9..4b0c834d8415 100644 --- a/packages/SystemUI/res/layout/notification_guts.xml +++ b/packages/SystemUI/res/layout/notification_guts.xml @@ -39,7 +39,7 @@ android:layout_gravity="center_vertical|start"> <ImageView - android:id="@android:id/icon" + android:id="@+id/app_icon" android:layout_width="18dp" android:layout_height="18dp" android:layout_marginEnd="6dp" diff --git a/packages/SystemUI/res/layout/notification_settings_icon_row.xml b/packages/SystemUI/res/layout/notification_settings_icon_row.xml index 52d07fcc5cb7..f47083af4902 100644 --- a/packages/SystemUI/res/layout/notification_settings_icon_row.xml +++ b/packages/SystemUI/res/layout/notification_settings_icon_row.xml @@ -19,6 +19,7 @@ xmlns:systemui="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:visibility="invisible" > <com.android.systemui.statusbar.AlphaOptimizedImageView @@ -31,7 +32,6 @@ android:paddingBottom="@dimen/notification_gear_padding" android:src="@drawable/ic_settings" android:tint="@color/notification_gear_color" - android:visibility="invisible" android:alpha="0" android:background="?android:attr/selectableItemBackgroundBorderless" /> diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 289b1d9db32c..656941f8b725 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -39,8 +39,9 @@ android:clipToPadding="false" android:clipChildren="false"> - <include - layout="@layout/qs_panel" + <com.android.systemui.DensityContainer + android:id="@+id/qs_density_container" + android:layout="@layout/qs_panel" android:layout_width="@dimen/notification_panel_width" android:layout_height="wrap_content" android:layout_gravity="@integer/notification_panel_layout_gravity" /> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 189eb3be302a..e040ab26f97a 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -93,5 +93,9 @@ <attr name="defValue" format="boolean" /> <attr name="metricsAction" format="integer" /> </declare-styleable> + + <declare-styleable name="DensityContainer"> + <attr name="android:layout" /> + </declare-styleable> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 8f69bbb16000..30acc72abae5 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -31,7 +31,7 @@ <color name="batterymeter_bolt_color">#FFFFFFFF</color> <color name="qs_batterymeter_frame_color">#FF404040</color> <color name="system_primary_color">#ff263238</color><!-- blue grey 900 --> - <color name="system_secondary_color">#ff384248</color> + <color name="system_secondary_color">#ff37474F</color><!-- blue grey 800 --> <color name="system_accent_color">#ff80CBC4</color><!-- deep teal 200 --> <color name="system_warning_color">#fff4511e</color><!-- deep orange 600 --> <color name="qs_text">#FFFFFFFF</color> diff --git a/packages/SystemUI/src/com/android/systemui/DensityContainer.java b/packages/SystemUI/src/com/android/systemui/DensityContainer.java new file mode 100644 index 000000000000..2e3cb4977488 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/DensityContainer.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui; + +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; + +import java.util.ArrayList; +import java.util.List; + +public class DensityContainer extends FrameLayout { + + private final List<InflateListener> mInflateListeners = new ArrayList<>(); + private final int mLayout; + private int mDensity; + + public DensityContainer(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + mDensity = context.getResources().getConfiguration().densityDpi; + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DensityContainer); + if (!a.hasValue(R.styleable.DensityContainer_android_layout)) { + throw new IllegalArgumentException("DensityContainer must contain a layout"); + } + mLayout = a.getResourceId(R.styleable.DensityContainer_android_layout, 0); + inflateLayout(); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + int density = newConfig.densityDpi; + if (density != mDensity) { + mDensity = density; + inflateLayout(); + } + } + + private void inflateLayout() { + removeAllViews(); + LayoutInflater.from(getContext()).inflate(mLayout, this); + final int N = mInflateListeners.size(); + for (int i = 0; i < N; i++) { + mInflateListeners.get(i).onInflated(getChildAt(0)); + } + } + + public void addInflateListener(InflateListener listener) { + mInflateListeners.add(listener); + listener.onInflated(getChildAt(0)); + } + + public interface InflateListener { + /** + * Called whenever a new view is inflated. + */ + void onInflated(View v); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java index ea7270ddb487..4b775a5a61e4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java +++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java @@ -38,7 +38,9 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings.Secure; import android.text.TextUtils; +import android.util.Pair; import android.util.Slog; +import android.widget.Toast; import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.CachedBluetoothDevice; @@ -46,6 +48,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothAdapter; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.bluetooth.Utils; import com.android.systemui.R; import com.android.systemui.SystemUI; @@ -76,8 +79,9 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha private static final int STATE_WAITING_FOR_BLUETOOTH = 4; private static final int STATE_PAIRING = 5; private static final int STATE_PAIRED = 6; - private static final int STATE_USER_CANCELLED = 7; - private static final int STATE_DEVICE_NOT_FOUND = 8; + private static final int STATE_PAIRING_FAILED = 7; + private static final int STATE_USER_CANCELLED = 8; + private static final int STATE_DEVICE_NOT_FOUND = 9; private static final int MSG_INIT = 0; private static final int MSG_ON_BOOT_COMPLETED = 1; @@ -90,6 +94,7 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha private static final int MSG_SHOW_BLUETOOTH_DIALOG = 8; private static final int MSG_DISMISS_BLUETOOTH_DIALOG = 9; private static final int MSG_BLE_ABORT_SCAN = 10; + private static final int MSG_SHOW_ERROR = 11; private volatile KeyboardHandler mHandler; private volatile KeyboardUIHandler mUIHandler; @@ -178,6 +183,7 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha mLocalBluetoothAdapter = bluetoothManager.getBluetoothAdapter(); mProfileManager = bluetoothManager.getProfileManager(); bluetoothManager.getEventManager().registerCallback(new BluetoothCallbackHandler()); + Utils.setErrorListener(new BluetoothErrorListener()); InputManager im = context.getSystemService(InputManager.class); im.registerOnTabletModeChangedListener(this, mHandler); @@ -204,13 +210,15 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha if (mInTabletMode != InputManager.SWITCH_STATE_OFF) { if (mState == STATE_WAITING_FOR_DEVICE_DISCOVERY) { stopScanning(); + } else if (mState == STATE_WAITING_FOR_BLUETOOTH) { + mUIHandler.sendEmptyMessage(MSG_DISMISS_BLUETOOTH_DIALOG); } mState = STATE_WAITING_FOR_TABLET_MODE_EXIT; return; } final int btState = mLocalBluetoothAdapter.getState(); - if (btState == BluetoothAdapter.STATE_TURNING_ON || btState == BluetoothAdapter.STATE_ON + if ((btState == BluetoothAdapter.STATE_TURNING_ON || btState == BluetoothAdapter.STATE_ON) && mState == STATE_WAITING_FOR_BLUETOOTH) { // If we're waiting for bluetooth but it has come on in the meantime, or is coming // on, just dismiss the dialog. This frequently happens during device startup. @@ -334,7 +342,10 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha private void stopScanning() { if (mScanCallback != null) { - mLocalBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback); + BluetoothLeScanner scanner = mLocalBluetoothAdapter.getBluetoothLeScanner(); + if (scanner != null) { + scanner.stopScan(mScanCallback); + } mScanCallback = null; } } @@ -370,10 +381,14 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha // Should only be called on the handler thread private void onDeviceBondStateChangedInternal(CachedBluetoothDevice d, int bondState) { - if (d.getName().equals(mKeyboardName) && bondState == BluetoothDevice.BOND_BONDED) { - // We don't need to manually connect to the device here because it will automatically - // try to connect after it has been paired. - mState = STATE_PAIRED; + if (mState == STATE_PAIRING && d.getName().equals(mKeyboardName)) { + if (bondState == BluetoothDevice.BOND_BONDED) { + // We don't need to manually connect to the device here because it will + // automatically try to connect after it has been paired. + mState = STATE_PAIRED; + } else if (bondState == BluetoothDevice.BOND_NONE) { + mState = STATE_PAIRING_FAILED; + } } } @@ -385,6 +400,17 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha } } + // Should only be called on the handler thread. We want to be careful not to show errors for + // pairings not initiated by this UI, so we only pop up the toast when we're at an appropriate + // point in our pairing flow and it's the expected device. + private void onShowErrorInternal(Context context, String name, int messageResId) { + if ((mState == STATE_PAIRING || mState == STATE_PAIRING_FAILED) + && mKeyboardName.equals(name)) { + String message = context.getString(messageResId, name); + Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + } + } + private final class KeyboardUIHandler extends Handler { public KeyboardUIHandler() { super(Looper.getMainLooper(), null, true /*async*/); @@ -393,19 +419,27 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha public void handleMessage(Message msg) { switch(msg.what) { case MSG_SHOW_BLUETOOTH_DIALOG: { - DialogInterface.OnClickListener listener = new BluetoothDialogClickListener(); + if (mDialog != null) { + // Don't show another dialog if one is already present + break; + } + DialogInterface.OnClickListener clickListener = + new BluetoothDialogClickListener(); + DialogInterface.OnDismissListener dismissListener = + new BluetoothDialogDismissListener(); mDialog = new BluetoothDialog(mContext); mDialog.setTitle(R.string.enable_bluetooth_title); mDialog.setMessage(R.string.enable_bluetooth_message); - mDialog.setPositiveButton(R.string.enable_bluetooth_confirmation_ok, listener); - mDialog.setNegativeButton(android.R.string.cancel, listener); + mDialog.setPositiveButton( + R.string.enable_bluetooth_confirmation_ok, clickListener); + mDialog.setNegativeButton(android.R.string.cancel, clickListener); + mDialog.setOnDismissListener(dismissListener); mDialog.show(); break; } case MSG_DISMISS_BLUETOOTH_DIALOG: { if (mDialog != null) { mDialog.dismiss(); - mDialog = null; } break; } @@ -469,6 +503,10 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha onBleScanFailedInternal(); break; } + case MSG_SHOW_ERROR: { + Pair<Context, String> p = (Pair<Context, String>) msg.obj; + onShowErrorInternal(p.first, p.second, msg.arg1); + } } } } @@ -482,6 +520,14 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha } } + private final class BluetoothDialogDismissListener + implements DialogInterface.OnDismissListener { + @Override + public void onDismiss(DialogInterface dialog) { + mDialog = null; + } + } + private final class KeyboardScanCallback extends ScanCallback { private boolean isDeviceDiscoverable(ScanResult result) { @@ -564,6 +610,13 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { } } + private final class BluetoothErrorListener implements Utils.ErrorListener { + public void onShowError(Context context, String name, int messageResId) { + mHandler.obtainMessage(MSG_SHOW_ERROR, messageResId, 0 /*unused*/, + new Pair<>(context, name)).sendToTarget(); + } + } + private static String stateToString(int state) { switch (state) { case STATE_NOT_ENABLED: @@ -580,13 +633,15 @@ public class KeyboardUI extends SystemUI implements InputManager.OnTabletModeCha return "STATE_PAIRING"; case STATE_PAIRED: return "STATE_PAIRED"; + case STATE_PAIRING_FAILED: + return "STATE_PAIRING_FAILED"; case STATE_USER_CANCELLED: return "STATE_USER_CANCELLED"; case STATE_DEVICE_NOT_FOUND: return "STATE_DEVICE_NOT_FOUND"; case STATE_UNKNOWN: default: - return "STATE_UNKNOWN"; + return "STATE_UNKNOWN (" + state + ")"; } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java index 267ed16d2d07..546f8c3c95af 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java @@ -23,7 +23,6 @@ import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; - import android.widget.ImageView.ScaleType; import com.android.systemui.R; @@ -34,6 +33,7 @@ public class QSIconView extends ViewGroup { private final View mIcon; private final int mIconSizePx; private final int mTilePaddingBelowIconPx; + private boolean mAnimationEnabled = true; public QSIconView(Context context) { super(context); @@ -46,6 +46,10 @@ public class QSIconView extends ViewGroup { addView(mIcon); } + public void disableAnimation() { + mAnimationEnabled = false; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int w = MeasureSpec.getSize(widthMeasureSpec); @@ -69,7 +73,9 @@ public class QSIconView extends ViewGroup { protected void setIcon(ImageView iv, QSTile.State state) { if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) { - Drawable d = state.icon != null ? state.icon.getDrawable(mContext) : null; + Drawable d = state.icon != null + ? iv.isShown() && mAnimationEnabled ? state.icon.getDrawable(mContext) + : state.icon.getInvisibleDrawable(mContext) : null; int padding = state.icon != null ? state.icon.getPadding() : null; if (d != null && state.autoMirrorDrawable) { d.setAutoMirrored(true); @@ -77,7 +83,7 @@ public class QSIconView extends ViewGroup { iv.setImageDrawable(d); iv.setTag(R.id.qs_icon_tag, state.icon); iv.setPadding(0, padding, 0, padding); - if (d instanceof Animatable) { + if (d instanceof Animatable && iv.isShown()) { Animatable a = (Animatable) d; a.start(); if (!iv.isShown()) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 30a985052bc2..71c1913d94e6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -31,6 +31,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.qs.QSTile.DetailAdapter; +import com.android.systemui.qs.QSTile.Host.Callback; import com.android.systemui.qs.customize.QSCustomizer; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.settings.BrightnessController; @@ -44,7 +45,7 @@ import java.util.ArrayList; import java.util.Collection; /** View that represents the quick settings tile panel. **/ -public class QSPanel extends LinearLayout implements Tunable { +public class QSPanel extends LinearLayout implements Tunable, Callback { public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness"; @@ -123,10 +124,16 @@ public class QSPanel extends LinearLayout implements Tunable { @Override protected void onDetachedFromWindow() { TunerService.get(mContext).removeTunable(this); + mHost.removeCallback(this); super.onDetachedFromWindow(); } @Override + public void onTilesChanged() { + setTiles(mHost.getTiles()); + } + + @Override public void onTuningChanged(String key, String newValue) { if (QS_SHOW_BRIGHTNESS.equals(key)) { mBrightnessView.setVisibility(newValue == null || Integer.parseInt(newValue) != 0 @@ -168,6 +175,8 @@ public class QSPanel extends LinearLayout implements Tunable { public void setHost(QSTileHost host) { mHost = host; + mHost.addCallback(this); + setTiles(mHost.getTiles()); mFooter.setHost(host); createCustomizePanel(); } @@ -272,7 +281,7 @@ public class QSPanel extends LinearLayout implements Tunable { } } - private void drawTile(TileRecord r, QSTile.State state) { + protected void drawTile(TileRecord r, QSTile.State state) { r.tileView.onStateChanged(state); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index df622b8f374c..42e98aa1ee01 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -390,6 +390,7 @@ public abstract class QSTile<TState extends State> implements Listenable { Context getContext(); Collection<QSTile<?>> getTiles(); void addCallback(Callback callback); + void removeCallback(Callback callback); BluetoothController getBluetoothController(); LocationController getLocationController(); RotationLockController getRotationLockController(); @@ -416,6 +417,10 @@ public abstract class QSTile<TState extends State> implements Listenable { public static abstract class Icon { abstract public Drawable getDrawable(Context context); + public Drawable getInvisibleDrawable(Context context) { + return getDrawable(context); + } + @Override public int hashCode() { return Icon.class.hashCode(); @@ -437,6 +442,11 @@ public abstract class QSTile<TState extends State> implements Listenable { public Drawable getDrawable(Context context) { return mDrawable; } + + @Override + public Drawable getInvisibleDrawable(Context context) { + return mDrawable; + } } public static class ResourceIcon extends Icon { @@ -463,6 +473,11 @@ public abstract class QSTile<TState extends State> implements Listenable { } @Override + public Drawable getInvisibleDrawable(Context context) { + return context.getDrawable(mResId); + } + + @Override public boolean equals(Object o) { return o instanceof ResourceIcon && ((ResourceIcon) o).mResId == mResId; } @@ -474,14 +489,17 @@ public abstract class QSTile<TState extends State> implements Listenable { } protected class AnimationIcon extends ResourceIcon { - public AnimationIcon(int resId) { - super(resId); + private final int mAnimatedResId; + + public AnimationIcon(int resId, int staticResId) { + super(staticResId); + mAnimatedResId = resId; } @Override public Drawable getDrawable(Context context) { // workaround: get a clean state for every new AVD - return context.getDrawable(mResId).getConstantState().newDrawable(); + return context.getDrawable(mAnimatedResId).getConstantState().newDrawable(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java index f35aacf8f72d..9e40cfd91ebb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java @@ -48,7 +48,7 @@ public class QSTileBaseView extends LinearLayout { // Default to Quick Tile padding, and QSTileView will specify its own padding. int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding); - setPadding(padding, padding, padding, padding); + setPadding(0, padding, 0, padding); setClipChildren(false); setClipToPadding(false); } @@ -113,7 +113,7 @@ public class QSTileBaseView extends LinearLayout { setContentDescription(state.contentDescription); } - View getIcon() { + public QSIconView getIcon() { return mIcon; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 4408dbf236bf..8b826eea4285 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -24,6 +24,8 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.Space; import com.android.systemui.R; +import com.android.systemui.qs.QSTile.SignalState; +import com.android.systemui.qs.QSTile.State; import java.util.ArrayList; import java.util.Collection; @@ -60,6 +62,19 @@ public class QuickQSPanel extends QSPanel { } @Override + protected void drawTile(TileRecord r, State state) { + if (state instanceof SignalState) { + State copy = r.tile.newTileState(); + state.copyTo(copy); + // No activity shown in the quick panel. + ((SignalState) copy).activityIn = false; + ((SignalState) copy).activityOut = false; + state = copy; + } + super.drawTile(r, state); + } + + @Override protected void showDetail(boolean show, Record r) { // Do nothing, will be handled by the QSPanel. } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index d1953b13eec9..aba9251e4bb8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -172,6 +172,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta if (itemView instanceof FrameLayout) { mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0); mTileView.setBackground(null); + mTileView.getIcon().disableAnimation(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index f0860fe181d3..89f1985b3f75 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -33,9 +33,11 @@ import com.android.systemui.qs.QSTile; /** Quick settings tile: Airplane mode **/ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> { private final AnimationIcon mEnable = - new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation); + new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation, + R.drawable.ic_signal_airplane_disable); private final AnimationIcon mDisable = - new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation); + new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation, + R.drawable.ic_signal_airplane_enable); private final GlobalSetting mSetting; private boolean mListening; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 42ce69c57978..a608316f8f72 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -30,9 +30,11 @@ import com.android.systemui.qs.SecureSetting; public class ColorInversionTile extends QSTile<QSTile.BooleanState> { private final AnimationIcon mEnable - = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation); + = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation, + R.drawable.ic_invert_colors_disable); private final AnimationIcon mDisable - = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation); + = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation, + R.drawable.ic_invert_colors_enable); private final SecureSetting mSetting; private boolean mListening; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 8982b3e1de13..8b2286842971 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -56,9 +56,11 @@ public class DndTile extends QSTile<QSTile.BooleanState> { ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence); private final AnimationIcon mDisable = - new AnimationIcon(R.drawable.ic_dnd_disable_animation); + new AnimationIcon(R.drawable.ic_dnd_disable_animation, + R.drawable.ic_qs_dnd_off); private final AnimationIcon mDisableTotalSilence = - new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation); + new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation, + R.drawable.ic_qs_dnd_off); private final ZenModeController mController; private final DndDetailAdapter mDetailAdapter; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index 12c8c44412ac..a01a9a5f68cb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -33,9 +33,11 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements FlashlightController.FlashlightListener { private final AnimationIcon mEnable - = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation); + = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation, + R.drawable.ic_signal_flashlight_disable); private final AnimationIcon mDisable - = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation); + = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation, + R.drawable.ic_signal_flashlight_enable); private final FlashlightController mFlashlightController; public FlashlightTile(Host host) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index ad1c7a0acf01..da931209dc19 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -29,9 +29,11 @@ import com.android.systemui.statusbar.policy.HotspotController; /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTile<QSTile.BooleanState> { private final AnimationIcon mEnable = - new AnimationIcon(R.drawable.ic_hotspot_enable_animation); + new AnimationIcon(R.drawable.ic_hotspot_enable_animation, + R.drawable.ic_hotspot_disable); private final AnimationIcon mDisable = - new AnimationIcon(R.drawable.ic_hotspot_disable_animation); + new AnimationIcon(R.drawable.ic_hotspot_disable_animation, + R.drawable.ic_hotspot_enable); private final HotspotController mController; private final Callback mCallback = new Callback(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index 65332529d881..b1d1c77f9d09 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -32,9 +32,11 @@ import com.android.systemui.statusbar.policy.LocationController.LocationSettings public class LocationTile extends QSTile<QSTile.BooleanState> { private final AnimationIcon mEnable = - new AnimationIcon(R.drawable.ic_signal_location_enable_animation); + new AnimationIcon(R.drawable.ic_signal_location_enable_animation, + R.drawable.ic_signal_location_disable); private final AnimationIcon mDisable = - new AnimationIcon(R.drawable.ic_signal_location_disable_animation); + new AnimationIcon(R.drawable.ic_signal_location_disable_animation, + R.drawable.ic_signal_location_enable); private final LocationController mController; private final KeyguardMonitor mKeyguard; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index b267ccd1ec46..d80ca104f59b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -31,14 +31,18 @@ import com.android.systemui.statusbar.policy.RotationLockController.RotationLock /** Quick settings tile: Rotation **/ public class RotationLockTile extends QSTile<QSTile.BooleanState> { private final AnimationIcon mPortraitToAuto - = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation); + = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation, + R.drawable.ic_portrait_from_auto_rotate); private final AnimationIcon mAutoToPortrait - = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation); + = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation, + R.drawable.ic_portrait_to_auto_rotate); private final AnimationIcon mLandscapeToAuto - = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation); + = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation, + R.drawable.ic_landscape_from_auto_rotate); private final AnimationIcon mAutoToLandscape - = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation); + = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation, + R.drawable.ic_landscape_to_auto_rotate); private final RotationLockController mController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 003e9c15ad43..421a2cf9cc51 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -28,9 +28,11 @@ import com.android.systemui.statusbar.phone.ManagedProfileController; public class WorkModeTile extends QSTile<QSTile.BooleanState> implements ManagedProfileController.Callback { private final AnimationIcon mEnable = - new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation); + new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation, + R.drawable.ic_signal_workmode_disable); private final AnimationIcon mDisable = - new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation); + new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation, + R.drawable.ic_signal_workmode_enable); private final ManagedProfileController mProfileController; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 6fef8a24fff3..abcb563339aa 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -133,7 +133,6 @@ public class RecentsTaskLoadPlan { SparseIntArray affiliatedTaskCounts = new SparseIntArray(); String dismissDescFormat = mContext.getString( R.string.accessibility_recents_item_will_be_dismissed); - Formatter dismissDescFormatter = new Formatter(); long lastStackActiveTime = Prefs.getLong(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0); if (RecentsDebugFlags.Static.EnableMockTasks) { @@ -184,8 +183,7 @@ public class RecentsTaskLoadPlan { ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey); String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription); String contentDescription = loader.getAndUpdateContentDescription(taskKey, res); - String dismissDescription = dismissDescFormatter.format(dismissDescFormat, - contentDescription).toString(); + String dismissDescription = String.format(dismissDescFormat, contentDescription); Drawable icon = isStackTask ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false) : null; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java index 2cd0c19a4352..d152010c71c8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -20,8 +20,8 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.res.Resources; -import android.graphics.Path; import android.graphics.RectF; +import android.util.Log; import android.view.View; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; @@ -441,11 +441,13 @@ public class TaskStackAnimationHelper { TaskStackViewScroller stackScroller = mStackView.getScroller(); TaskStack stack = mStackView.getStack(); + final float curScroll = stackScroller.getStackScroll(); final float newScroll = stackLayout.getStackScrollForTask(newFocusedTask); - boolean willScrollToFront = newScroll > stackScroller.getStackScroll(); - boolean willScroll = Float.compare(newScroll, stackScroller.getStackScroll()) != 0; + boolean willScrollToFront = newScroll > curScroll; + boolean willScroll = Float.compare(newScroll, curScroll) != 0; // Get the current set of task transforms + int taskViewCount = mStackView.getTaskViews().size(); ArrayList<Task> stackTasks = stack.getStackTasks(); mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms); @@ -463,6 +465,13 @@ public class TaskStackAnimationHelper { // Focus the task view TaskView newFocusedTaskView = mStackView.getChildViewForTask(newFocusedTask); + if (newFocusedTaskView == null) { + // Log the error if we have no task view, and skip the animation + Log.e("TaskStackAnimationHelper", "b/27389156 null-task-view prebind:" + taskViewCount + + " postbind:" + mStackView.getTaskViews().size() + " prescroll:" + curScroll + + " postscroll: " + newScroll); + return false; + } newFocusedTaskView.setFocusedState(true, requestViewFocus); // Setup the end listener to return all the hidden views to the view pool after the @@ -476,7 +485,7 @@ public class TaskStackAnimationHelper { }); List<TaskView> taskViews = mStackView.getTaskViews(); - int taskViewCount = taskViews.size(); + taskViewCount = taskViews.size(); int newFocusTaskViewIndex = taskViews.indexOf(newFocusedTaskView); for (int i = 0; i < taskViewCount; i++) { TaskView tv = taskViews.get(i); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index d0358f4cda60..178838ea939d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -983,7 +983,7 @@ public abstract class BaseStatusBar extends SystemUI implements pkgicon = pmUser.getDefaultActivityIcon(); } - ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon); + ((ImageView) row.findViewById(R.id.app_icon)).setImageDrawable(pkgicon); ((TextView) row.findViewById(R.id.pkgname)).setText(appname); final View settingsButton = guts.findViewById(R.id.more_settings); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java index b3265524965f..7f87c3c687d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java @@ -169,21 +169,23 @@ public class DragDownHelper implements Gefingerpoken { ? RUBBERBAND_FACTOR_EXPANDABLE : RUBBERBAND_FACTOR_STATIC; float rubberband = heightDelta * rubberbandFactor; - if (expandable && (rubberband + child.getMinHeight()) > child.getMaxContentHeight()) { - float overshoot = (rubberband + child.getMinHeight()) - child.getMaxContentHeight(); + if (expandable + && (rubberband + child.getMinExpandHeight()) > child.getMaxContentHeight()) { + float overshoot = + (rubberband + child.getMinExpandHeight()) - child.getMaxContentHeight(); overshoot *= (1 - RUBBERBAND_FACTOR_STATIC); rubberband -= overshoot; } - child.setActualHeight((int) (child.getMinHeight() + rubberband)); + child.setActualHeight((int) (child.getMinExpandHeight() + rubberband)); } private void cancelExpansion(final ExpandableView child) { - if (child.getActualHeight() == child.getMinHeight()) { + if (child.getActualHeight() == child.getMinExpandHeight()) { mCallback.setUserLockedChild(child, false); return; } ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight", - child.getActualHeight(), child.getMinHeight()); + child.getActualHeight(), child.getMinExpandHeight()); anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS); anim.addListener(new AnimatorListenerAdapter() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 9799d75a890f..f446593e6cb4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -412,7 +412,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } public ExpandableNotificationRow getViewAtPosition(float y) { - if (!mIsSummaryWithChildren || !mChildrenExpanded) { + if (!mIsSummaryWithChildren || !mChildrenExpanded + || (getNotificationChildren().size() == 1 && isClearable())) { return this; } else { ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y); @@ -1221,8 +1222,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { @Override public int getMinExpandHeight() { - if (mIsSummaryWithChildren && !mOnKeyguard) { - return mChildrenContainer.getMinExpandHeight(); + if (mIsSummaryWithChildren && !mShowingPublic) { + return mChildrenContainer.getMinExpandHeight(mOnKeyguard); } return getMinHeight(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java index 476e146d1859..375459f0f30c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java @@ -97,12 +97,12 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC private void setGearAlpha(float alpha) { if (alpha == 0) { mSettingsFadedIn = false; // Can fade in again once it's gone. - mGearIcon.setVisibility(View.INVISIBLE); + setVisibility(View.INVISIBLE); } else { if (alpha == 1) { mSettingsFadedIn = true; } - mGearIcon.setVisibility(View.VISIBLE); + setVisibility(View.VISIBLE); } mGearIcon.setAlpha(alpha); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index c892b11e33fa..960e4cf47001 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -227,6 +227,8 @@ public class SignalClusterView protected void onDetachedFromWindow() { mMobileSignalGroup.removeAllViews(); TunerService.get(mContext).removeTunable(this); + mSC.removeCallback(this); + mNC.removeSignalCallback(this); super.onDetachedFromWindow(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java index 5796edbeea61..ed71e5708ce1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java @@ -22,8 +22,12 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; +import android.graphics.Paint; import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; +import android.graphics.PorterDuff.Mode; import android.graphics.drawable.Drawable; import android.os.SystemClock; import android.util.Log; @@ -55,6 +59,7 @@ public class BarTransitions { private final BarBackgroundDrawable mBarBackground; private int mMode; + private boolean mAlwaysOpaque = false; public BarTransitions(View view, int gradientResourceId) { mTag = "BarTransitions." + view.getClass().getSimpleName(); @@ -69,13 +74,25 @@ public class BarTransitions { return mMode; } + /** + * @param alwaysOpaque if {@code true}, the bar's background will always be opaque, regardless + * of what mode it is currently set to. + */ + public void setAlwaysOpaque(boolean alwaysOpaque) { + mAlwaysOpaque = alwaysOpaque; + } + + public boolean isAlwaysOpaque() { + // Low-end devices do not support translucent modes, fallback to opaque + return !HIGH_END || mAlwaysOpaque; + } + public void transitionTo(int mode, boolean animate) { - // low-end devices do not support translucent modes, fallback to opaque - if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT + if (isAlwaysOpaque() && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT || mode == MODE_TRANSPARENT)) { mode = MODE_OPAQUE; } - if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) { + if (isAlwaysOpaque() && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) { mode = MODE_LIGHTS_OUT; } if (mMode == mode) return; @@ -131,10 +148,13 @@ public class BarTransitions { private int mGradientAlpha; private int mColor; + private PorterDuffColorFilter mTintFilter; + private Paint mPaint = new Paint(); private int mGradientAlphaStart; private int mColorStart; + public BarBackgroundDrawable(Context context, int gradientResourceId) { final Resources res = context.getResources(); if (DEBUG_COLORS) { @@ -163,6 +183,26 @@ public class BarTransitions { } @Override + public void setTint(int color) { + if (mTintFilter == null) { + mTintFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); + } else { + mTintFilter.setColor(color); + } + invalidateSelf(); + } + + @Override + public void setTintMode(Mode tintMode) { + if (mTintFilter == null) { + mTintFilter = new PorterDuffColorFilter(0, tintMode); + } else { + mTintFilter.setMode(tintMode); + } + invalidateSelf(); + } + + @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mGradient.setBounds(bounds); @@ -208,6 +248,7 @@ public class BarTransitions { } else { targetColor = mOpaque; } + if (!mAnimating) { mColor = targetColor; mGradientAlpha = targetGradientAlpha; @@ -234,7 +275,11 @@ public class BarTransitions { mGradient.draw(canvas); } if (Color.alpha(mColor) > 0) { - canvas.drawColor(mColor); + mPaint.setColor(mColor); + if (mTintFilter != null) { + mPaint.setColorFilter(mTintFilter); + } + canvas.drawPaint(mPaint); } if (mAnimating) { invalidateSelf(); // keep going diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java index eade2a89447d..6e1c862ebd73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone; import android.content.Context; import android.util.AttributeSet; import android.widget.RelativeLayout; - import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.NetworkControllerImpl; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 05ae41be33d4..127febae5ee8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -42,6 +42,8 @@ import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.DejankUtils; +import com.android.systemui.DensityContainer; +import com.android.systemui.DensityContainer.InflateListener; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.Interpolators; @@ -215,8 +217,14 @@ public class NotificationPanelView extends PanelView implements super.onFinishInflate(); mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header); mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view); - mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container); - mQsContainer.getHeader().setOnClickListener(this); + DensityContainer container = (DensityContainer) findViewById(R.id.qs_density_container); + container.addInflateListener(new InflateListener() { + @Override + public void onInflated(View v) { + mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container); + mQsContainer.getHeader().setOnClickListener(NotificationPanelView.this); + } + }); mClockView = (TextView) findViewById(R.id.clock_view); mNotificationContainerParent = (NotificationsQuickSettingsContainer) findViewById(R.id.notification_container_parent); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java index 7cc720df1c27..6d90e5cf416f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -47,7 +47,7 @@ public class NotificationsQuickSettingsContainer extends FrameLayout @Override protected void onFinishInflate() { super.onFinishInflate(); - mQsContainer = findViewById(R.id.quick_settings_container); + mQsContainer = findViewById(R.id.qs_density_container); mStackScroller = findViewById(R.id.notification_stack_scroller); mKeyguardStatusBar = findViewById(R.id.keyguard_header); ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 9b87a8adbeb6..e73994443491 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.IActivityManager; -import android.app.IWallpaperManagerCallback; import android.app.Notification; import android.app.PendingIntent; import android.app.StatusBarManager; @@ -104,6 +103,8 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.BatteryMeterView; import com.android.systemui.DemoMode; +import com.android.systemui.DensityContainer; +import com.android.systemui.DensityContainer.InflateListener; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.Interpolators; @@ -778,8 +779,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarView.setScrimController(mScrimController); mDozeScrimController = new DozeScrimController(mScrimController, context); - mHeader = (BaseStatusBarHeader) mStatusBarWindow.findViewById(R.id.header); - mHeader.setActivityStarter(this); mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header); mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view); mKeyguardBottomArea = @@ -839,12 +838,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, initSignalCluster(mStatusBarView); initSignalCluster(mKeyguardStatusBar); - initSignalCluster(mHeader); - - final boolean isAPhone = mNetworkController.hasVoiceCallingFeature(); - if (isAPhone) { - mNetworkController.addEmergencyListener(mHeader); - } mFlashlightController = new FlashlightController(mContext); mKeyguardBottomArea.setFlashlightController(mFlashlightController); @@ -863,39 +856,40 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } // Set up the quick settings tile panel - mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel); - if (mQSPanel != null) { + DensityContainer container = (DensityContainer) mStatusBarWindow.findViewById( + R.id.qs_density_container); + if (container != null) { final QSTileHost qsh = new QSTileHost(mContext, this, mBluetoothController, mLocationController, mRotationLockController, mNetworkController, mZenModeController, mHotspotController, mCastController, mFlashlightController, mUserSwitcherController, mUserInfoController, mKeyguardMonitor, - mSecurityController, mBatteryController, mIconController); - mQSPanel.setTiles(qsh.getTiles()); + mSecurityController, mBatteryController, mIconController, + mNextAlarmController); mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow); - mQSPanel.setBrightnessMirror(mBrightnessMirrorController); - QSContainer qsContainer = (QSContainer) mStatusBarWindow.findViewById( - R.id.quick_settings_container); - qsContainer.setHost(qsh); - qsh.addCallback(new QSTileHost.Callback() { + container.addInflateListener(new InflateListener() { @Override - public void onTilesChanged() { - mQSPanel.setTiles(qsh.getTiles()); + public void onInflated(View v) { + QSContainer qsContainer = (QSContainer) v.findViewById( + R.id.quick_settings_container); + qsContainer.setHost(qsh); + mQSPanel = qsContainer.getQsPanel(); + mQSPanel.setBrightnessMirror(mBrightnessMirrorController); + mHeader = qsContainer.getHeader(); + initSignalCluster(mHeader); + mHeader.setActivityStarter(PhoneStatusBar.this); } }); } // User info. Trigger first load. - mHeader.setUserInfoController(mUserInfoController); mKeyguardStatusBar.setUserInfoController(mUserInfoController); mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController); mUserInfoController.reloadUserInfo(); - mHeader.setBatteryController(mBatteryController); ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController( mBatteryController); mKeyguardStatusBar.setBatteryController(mBatteryController); - mHeader.setNextAlarmController(mNextAlarmController); PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mBroadcastReceiver.onReceive(mContext, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 80afb9a3c705..f894a22d4acb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -57,6 +57,7 @@ import com.android.systemui.qs.tiles.WorkModeTile; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; +import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.NightModeController; import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.HotspotController; @@ -111,16 +112,18 @@ public final class QSTileHost implements QSTile.Host, Tunable { private final NightModeController mNightModeController; private final AutoTileManager mAutoTiles; private final ManagedProfileController mProfileController; + private final NextAlarmController mNextAlarmController; private View mHeader; public QSTileHost(Context context, PhoneStatusBar statusBar, - BluetoothController bluetooth, LocationController location, - RotationLockController rotation, NetworkController network, - ZenModeController zen, HotspotController hotspot, - CastController cast, FlashlightController flashlight, - UserSwitcherController userSwitcher, UserInfoController userInfo, - KeyguardMonitor keyguard, SecurityController security, - BatteryController battery, StatusBarIconController iconController) { + BluetoothController bluetooth, LocationController location, + RotationLockController rotation, NetworkController network, + ZenModeController zen, HotspotController hotspot, + CastController cast, FlashlightController flashlight, + UserSwitcherController userSwitcher, UserInfoController userInfo, + KeyguardMonitor keyguard, SecurityController security, + BatteryController battery, StatusBarIconController iconController, + NextAlarmController nextAlarmController) { mContext = context; mStatusBar = statusBar; mBluetooth = bluetooth; @@ -137,6 +140,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { mSecurity = security; mBattery = battery; mIconController = iconController; + mNextAlarmController = nextAlarmController; mNightModeController = new NightModeController(mContext, true); mProfileController = new ManagedProfileController(this); @@ -152,6 +156,10 @@ public final class QSTileHost implements QSTile.Host, Tunable { mAutoTiles = new AutoTileManager(context, this); } + public NextAlarmController getNextAlarmController() { + return mNextAlarmController; + } + public void setHeaderView(View view) { mHeader = view; } @@ -171,6 +179,11 @@ public final class QSTileHost implements QSTile.Host, Tunable { } @Override + public void removeCallback(Callback callback) { + mCallbacks.remove(callback); + } + + @Override public Collection<QSTile<?>> getTiles() { return mTiles.values(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index b549d5912117..256cc6b6ae3f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -35,13 +35,13 @@ import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.qs.QSAnimator; import com.android.systemui.qs.QSPanel; -import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QuickQSPanel; import com.android.systemui.qs.TouchAnimator; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback; import com.android.systemui.statusbar.policy.UserInfoController; +import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener; import com.android.systemui.tuner.TunerService; public class QuickStatusBarHeader extends BaseStatusBarHeader implements @@ -90,6 +90,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private TouchAnimator mAlarmTranslation; private TouchAnimator mSettingsAlpha; private float mExpansionAmount; + private QSTileHost mHost; public QuickStatusBarHeader(Context context, AttributeSet attrs) { super(context, attrs); @@ -222,6 +223,14 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD); } + @Override + protected void onDetachedFromWindow() { + setListening(false); + mHost.getUserInfoController().remListener(mUserListener); + mHost.getNetworkController().removeEmergencyListener(this); + super.onDetachedFromWindow(); + } + private void updateAlarmVisibilities() { mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE); mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE); @@ -284,17 +293,19 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements } public void setupHost(final QSTileHost host) { + mHost = host; host.setHeaderView(this); mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this); - mHeaderQsPanel.setHost(host); mHeaderQsPanel.setMaxTiles(5); - mHeaderQsPanel.setTiles(host.getTiles()); - host.addCallback(new QSTile.Host.Callback() { - @Override - public void onTilesChanged() { - mHeaderQsPanel.setTiles(host.getTiles()); - } - }); + mHeaderQsPanel.setHost(host); + setUserInfoController(host.getUserInfoController()); + setBatteryController(host.getBatteryController()); + setNextAlarmController(host.getNextAlarmController()); + + final boolean isAPhone = mHost.getNetworkController().hasVoiceCallingFeature(); + if (isAPhone) { + mHost.getNetworkController().addEmergencyListener(this); + } } @Override @@ -340,12 +351,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements @Override public void setUserInfoController(UserInfoController userInfoController) { - userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() { - @Override - public void onUserInfoChanged(String name, Drawable picture) { - mMultiUserAvatar.setImageDrawable(picture); - } - }); + userInfoController.addListener(mUserListener); } @Override @@ -358,4 +364,11 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements } } } + + private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() { + @Override + public void onUserInfoChanged(String name, Drawable picture) { + mMultiUserAvatar.setImageDrawable(picture); + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index 3e3b16922f7a..a051973efdda 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -39,7 +39,6 @@ import android.widget.RelativeLayout; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; - import com.android.keyguard.KeyguardStatusView; import com.android.systemui.BatteryMeterView; import com.android.systemui.FontSizeUtils; @@ -48,7 +47,7 @@ import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QSTile.DetailAdapter; import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; +import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.tuner.TunerService; 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 e618cb87887d..3142ddfe9fb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java @@ -19,11 +19,10 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.telephony.SubscriptionInfo; - import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; import java.util.ArrayList; import java.util.List; 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 93c73228265e..348e0b003997 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.policy; import android.content.Context; import android.content.Intent; import android.telephony.SubscriptionInfo; - import com.android.settingslib.net.DataUsageController; import com.android.settingslib.wifi.AccessPoint; @@ -36,6 +35,11 @@ public interface NetworkController { DataUsageController getMobileDataController(); DataSaverController getDataSaverController(); + boolean hasVoiceCallingFeature(); + + void addEmergencyListener(EmergencyListener listener); + void removeEmergencyListener(EmergencyListener listener); + public interface SignalCallback { void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, boolean activityIn, boolean activityOut, String description); @@ -53,6 +57,10 @@ public interface NetworkController { void setMobileDataEnabled(boolean enabled); } + public interface EmergencyListener { + void setEmergencyCallsOnly(boolean emergencyOnly); + } + public static class IconState { public final boolean visible; public final int icon; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index eecf8c2ea39e..8193b52b569c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -252,6 +252,10 @@ public class NetworkControllerImpl extends BroadcastReceiver mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly()); } + public void removeEmergencyListener(EmergencyListener listener) { + mCallbackHandler.setListening(listener, false); + } + public boolean hasMobileDataFeature() { return mHasMobileDataFeature; } @@ -812,10 +816,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } }; - public interface EmergencyListener { - void setEmergencyCallsOnly(boolean emergencyOnly); - } - public static class SubscriptionDefaults { public int getDefaultVoiceSubId() { return SubscriptionManager.getDefaultVoiceSubscriptionId(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java index 0b1911bb15fc..4611ef9f31db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java @@ -14,17 +14,13 @@ package com.android.systemui.statusbar.policy; -import libcore.util.Objects; - import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.opengl.Matrix; -import android.provider.Settings; import android.provider.Settings.Secure; import android.util.MathUtils; - import com.android.systemui.tuner.TunerService; import java.util.ArrayList; @@ -189,8 +185,8 @@ public class NightModeController implements TunerService.Tunable { } private void updateNightMode(Intent intent) { - mIsNight = intent.getBooleanExtra(EXTRA_IS_NIGHT, false); - mAmount = intent.getFloatExtra(EXTRA_AMOUNT, 0); + mIsNight = intent != null && intent.getBooleanExtra(EXTRA_IS_NIGHT, false); + mAmount = intent != null ? intent.getFloatExtra(EXTRA_AMOUNT, 0) : 0; } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java index 030c8b737e84..795573352ba8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java @@ -167,6 +167,7 @@ public class NotificationChildrenContainer extends ViewGroup { int newIndex = childIndex < 0 ? mChildren.size() : childIndex; mChildren.add(newIndex, row); addView(row); + row.setUserLocked(mUserLocked); View divider = inflateDivider(); addView(divider); @@ -191,6 +192,7 @@ public class NotificationChildrenContainer extends ViewGroup { }); row.setSystemChildExpanded(false); + row.setUserLocked(false); updateGroupOverflow(); } @@ -262,10 +264,14 @@ public class NotificationChildrenContainer extends ViewGroup { } private void updateExpansionStates() { - // Let's make the first child expanded if the parent is - for (int i = 0; i < mChildren.size(); i++) { + if (mChildrenExpanded || mUserLocked) { + // we don't modify it the group is expanded or if we are expanding it + return; + } + int size = mChildren.size(); + for (int i = 0; i < size; i++) { ExpandableNotificationRow child = mChildren.get(i); - child.setSystemChildExpanded(false); + child.setSystemChildExpanded(i == 0 && size == 1); } } @@ -489,6 +495,7 @@ public class NotificationChildrenContainer extends ViewGroup { public void setChildrenExpanded(boolean childrenExpanded) { mChildrenExpanded = childrenExpanded; + updateExpansionStates(); } public void setNotificationParent(ExpandableNotificationRow parent) { @@ -566,8 +573,28 @@ public class NotificationChildrenContainer extends ViewGroup { return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED); } - public int getMinExpandHeight() { - return getIntrinsicHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */)); + public int getMinExpandHeight(boolean onKeyguard) { + int maxAllowedVisibleChildren = onKeyguard ? NUMBER_OF_CHILDREN_WHEN_COLLAPSED + : getMaxAllowedVisibleChildren(true /* forceCollapsed */); + int minExpandHeight = mNotificationHeaderHeight; + int visibleChildren = 0; + boolean firstChild = true; + int childCount = mChildren.size(); + for (int i = 0; i < childCount; i++) { + if (visibleChildren >= maxAllowedVisibleChildren) { + break; + } + if (!firstChild) { + minExpandHeight += mChildPadding; + } else { + firstChild = false; + } + ExpandableNotificationRow child = mChildren.get(i); + minExpandHeight += child.getMinHeight(); + visibleChildren++; + } + minExpandHeight += mCollapsedBottompadding; + return minExpandHeight; } public void setDark(boolean dark, boolean fade, long delay) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java index c06b63bd8f66..005767f7a09e 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java @@ -131,7 +131,7 @@ public class ZenFooter extends LinearLayout { final boolean isForever = mConfig != null && mConfig.manualRule != null && mConfig.manualRule.conditionId == null; - final String line2 = + final CharSequence line2 = isForever ? mContext.getString(com.android.internal.R.string.zen_mode_forever_dnd) : ZenModeConfig.getConditionSummary(mContext, mConfig, mController.getCurrentUser(), true /*shortVersion*/); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java index 18412519af50..01514646b66e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java @@ -43,7 +43,7 @@ public class TileServicesTests extends SysuiTestCase { QSTileHost host = new QSTileHost(mContext, null, null, null, null, networkController, null, Mockito.mock(HotspotController.class), null, - null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null); mTileService = new TestTileServices(host, Looper.myLooper()); } 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 00b8de237347..19cb24322095 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 @@ -19,12 +19,10 @@ import android.os.HandlerThread; import android.telephony.SubscriptionInfo; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; - import com.android.systemui.R; +import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; - import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 471feef15e6c..077b121b9adf 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -478,5 +478,34 @@ message MetricsEvent { // Logged when we execute an app transition. This indicates the device uptime in seconds when // the transition was executed. APP_TRANSITION_DEVICE_UPTIME_SECONDS = 325; + + // User granted access to the request folder; action takes an integer + // representing the folder's index on Environment.STANDARD_DIRECTORIES + ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326; + + // User denied access to the request folder; action takes an integer + // representing the folder's index on Environment.STANDARD_DIRECTORIES + ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327; + + // User granted access to the request folder; action pass package name + // of calling package. + ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE = 328; + + // User denied access to the request folder; action pass package name + // of calling package. + ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE = 329; + + // App requested access to a directory it has already been granted + // access before; action takes an integer representing the folder's + // index on Environment.STANDARD_DIRECTORIES + ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330; + + // App requested access to a directory it has already been granted + // access before; action pass package name of calling package. + ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331; + + // Add new aosp constants above this line. + // END OF AOSP CONSTANTS + } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 430092071d90..25b6fdd4c350 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -750,7 +750,7 @@ public class ConnectivityService extends IConnectivityManager.Stub intentFilter.addAction(Intent.ACTION_USER_STOPPING); intentFilter.addAction(Intent.ACTION_USER_ADDED); intentFilter.addAction(Intent.ACTION_USER_REMOVED); - intentFilter.addAction(Intent.ACTION_USER_PRESENT); + intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); mContext.registerReceiverAsUser( mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); @@ -3633,7 +3633,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void onUserPresent(int userId) { + private void onUserUnlocked(int userId) { // User present may be sent because of an unlock, which might mean an unlocked keystore. if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { updateLockdownVpn(); @@ -3657,8 +3657,8 @@ public class ConnectivityService extends IConnectivityManager.Stub onUserAdded(userId); } else if (Intent.ACTION_USER_REMOVED.equals(action)) { onUserRemoved(userId); - } else if (Intent.ACTION_USER_PRESENT.equals(action)) { - onUserPresent(userId); + } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { + onUserUnlocked(userId); } } }; diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index c318140ae7e8..ba2a2e05d3d8 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -545,9 +545,23 @@ public class LockSettingsService extends ILockSettings.Stub { final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); final KeyStore ks = KeyStore.getInstance(); - final List<UserInfo> profiles = um.getProfiles(userHandle); - for (UserInfo pi : profiles) { - ks.onUserPasswordChanged(pi.id, password); + if (um.getUserInfo(userHandle).isManagedProfile()) { + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) { + ks.onUserPasswordChanged(userHandle, password); + } else { + throw new RuntimeException("Can't set keystore password on a profile that " + + "doesn't have a profile challenge."); + } + } else { + final List<UserInfo> profiles = um.getProfiles(userHandle); + for (UserInfo pi : profiles) { + // Change password on the given user and all its profiles that don't have + // their own profile challenge enabled. + if (pi.id == userHandle || (pi.isManagedProfile() + && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) { + ks.onUserPasswordChanged(pi.id, password); + } + } } } @@ -555,9 +569,23 @@ public class LockSettingsService extends ILockSettings.Stub { final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); final KeyStore ks = KeyStore.getInstance(); - final List<UserInfo> profiles = um.getProfiles(userHandle); - for (UserInfo pi : profiles) { - ks.unlock(pi.id, password); + if (um.getUserInfo(userHandle).isManagedProfile()) { + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) { + ks.unlock(userHandle, password); + } else { + throw new RuntimeException("Can't unlock a profile explicitly if it " + + "doesn't have a profile challenge."); + } + } else { + final List<UserInfo> profiles = um.getProfiles(userHandle); + for (UserInfo pi : profiles) { + // Unlock the given user and all its profiles that don't have + // their own profile challenge enabled. + if (pi.id == userHandle || (pi.isManagedProfile() + && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) { + ks.unlock(pi.id, password); + } + } } } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 53923ba972c7..a3322fc99677 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -1945,11 +1945,16 @@ class MountService extends IMountService.Stub "Emulation not available on device with native FBE"); } - final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0; - SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe)); + final long token = Binder.clearCallingIdentity(); + try { + final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0; + SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe)); - // Perform hard reboot to kick policy into place - mContext.getSystemService(PowerManager.class).reboot(null); + // Perform hard reboot to kick policy into place + mContext.getSystemService(PowerManager.class).reboot(null); + } finally { + Binder.restoreCallingIdentity(token); + } } if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 71a0f495eea1..c81ee2c8c83d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1297,6 +1297,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean mSupportsPictureInPicture; Rect mDefaultPinnedStackBounds; IActivityController mController = null; + boolean mControllerIsAMonkey = false; String mProfileApp = null; ProcessRecord mProfileProc = null; String mProfileFile; @@ -6983,6 +6984,8 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public Intent getIntentForIntentSender(IIntentSender pendingResult) { + enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT, + "getIntentForIntentSender()"); if (!(pendingResult instanceof PendingIntentRecord)) { return null; } @@ -11423,11 +11426,12 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void setActivityController(IActivityController controller) { + public void setActivityController(IActivityController controller, boolean imAMonkey) { enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, "setActivityController()"); synchronized (this) { mController = controller; + mControllerIsAMonkey = imAMonkey; Watchdog.getInstance().setActivityController(controller); } } @@ -11454,7 +11458,7 @@ public final class ActivityManagerService extends ActivityManagerNative public boolean isUserAMonkey() { synchronized (this) { // If there is a controller also implies the user is a monkey. - return (mUserIsMonkey || mController != null); + return (mUserIsMonkey || (mController != null && mControllerIsAMonkey)); } } @@ -14123,10 +14127,13 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (dumpPackage == null) { - if (mAlwaysFinishActivities || mLenientBackgroundCheck || mController != null) { + if (mAlwaysFinishActivities || mLenientBackgroundCheck) { pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities - + " mLenientBackgroundCheck=" + mLenientBackgroundCheck - + " mController=" + mController); + + " mLenientBackgroundCheck=" + mLenientBackgroundCheck); + } + if (mController != null) { + pw.println(" mController=" + mController + + " mControllerIsAMonkey=" + mControllerIsAMonkey); } if (dumpAll) { pw.println(" Total persistent processes: " + numPers); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 5491b4f9021b..769bee4cff6e 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -3005,6 +3005,8 @@ final class ActivityStack { if (!r.visible) { mWindowManager.setAppVisibility(r.appToken, false); } + EventLogTags.writeAmStopActivity( + r.userId, System.identityHashCode(r), r.shortComponentName); r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); if (mService.isSleepingOrShuttingDown()) { r.setSleeping(true); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 20f8285cfee7..c7fc5e24669a 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2186,7 +2186,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final int resizeMode = task.mResizeMode; - if (stackId == DOCKED_STACK_ID && resizeMode == RESIZE_MODE_UNRESIZEABLE) { + if (stackId == DOCKED_STACK_ID && !task.isResizeable()) { // We don't allow moving a unresizeable task to the docked stack since the docked // stack is used for split-screen mode and will cause things like the docked divider to // show up. We instead leave the task in its current stack or move it to the fullscreen diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags index f2e8d090d85d..2329b2f82bb7 100644 --- a/services/core/java/com/android/server/am/EventLogTags.logtags +++ b/services/core/java/com/android/server/am/EventLogTags.logtags @@ -54,9 +54,9 @@ option java_package com.android.server.am # An activity has been relaunched: 30020 am_relaunch_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3) # The activity's onPause has been called. -30021 am_on_paused_called (User|1|5),(Component Name|3) +30021 am_on_paused_called (User|1|5),(Component Name|3),(Reason|3) # The activity's onResume has been called. -30022 am_on_resume_called (User|1|5),(Component Name|3) +30022 am_on_resume_called (User|1|5),(Component Name|3),(Reason|3) # Kill a process to reclaim memory. 30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3) # Discard an undelivered serialized broadcast (timeout/ANR/crash) @@ -103,3 +103,8 @@ option java_package com.android.server.am 30046 am_meminfo (Cached|2|2),(Free|2|2),(Zram|2|2),(Kernel|2|2),(Native|2|2) # Report collection of memory used by a process 30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2) + +# Attempting to stop an activity +30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3) +# The activity's onStop has been called. +30049 am_on_stop_called (User|1|5),(Component Name|3),(Reason|3) diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index a3100c820d99..5a3639a972fc 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -849,6 +849,7 @@ public class AudioService extends IAudioService.Stub { AudioSystem.setForceUse(AudioSystem.FOR_DOCK, mDockAudioMediaEnabled ? AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); + readEncodedSurroundMode(mContentResolver); } if (mHdmiManager != null) { synchronized (mHdmiManager) { @@ -1011,6 +1012,7 @@ public class AudioService extends IAudioService.Stub { 0); } + private void updateMasterMono(ContentResolver cr) { final boolean masterMono = System.getIntForUser( @@ -1021,6 +1023,44 @@ public class AudioService extends IAudioService.Stub { AudioSystem.setMasterMono(masterMono); } + private void readEncodedSurroundMode(ContentResolver cr) + { + int encodedSurroundMode = Settings.Global.getInt( + cr, Settings.Global.ENCODED_SURROUND_OUTPUT, + Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO); + sendEncodedSurroundMode(encodedSurroundMode); + } + + private void sendEncodedSurroundMode(int encodedSurroundMode) + { + // initialize to guaranteed bad value + int forceSetting = AudioSystem.NUM_FORCE_CONFIG; + switch (encodedSurroundMode) { + case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO: + forceSetting = AudioSystem.FORCE_NONE; + break; + case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER: + forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER; + break; + case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS: + forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS; + break; + default: + Log.e(TAG, "updateSurroundSoundSettings: illegal value " + + encodedSurroundMode); + break; + } + if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) { + sendMsg(mAudioHandler, + MSG_SET_FORCE_USE, + SENDMSG_QUEUE, + AudioSystem.FOR_ENCODED_SURROUND, + forceSetting, + null, + 0); + } + } + private void readPersistedSettings() { final ContentResolver cr = mContentResolver; @@ -1062,6 +1102,7 @@ public class AudioService extends IAudioService.Stub { updateRingerModeAffectedStreams(); readDockAudioSettings(cr); + readEncodedSurroundMode(cr); } mMuteAffectedStreams = System.getIntForUser(cr, @@ -4628,6 +4669,7 @@ public class AudioService extends IAudioService.Stub { } readDockAudioSettings(mContentResolver); updateMasterMono(mContentResolver); + readEncodedSurroundMode(mContentResolver); } } } @@ -6315,4 +6357,4 @@ public class AudioService extends IAudioService.Stub { if (DEBUG_VOL) Log.d(TAG, "Reloaded controller service: " + this); } } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 5d81daeccc6b..7b134cab2b95 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -905,13 +905,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe // Group ID is arbitrarily set to parent profile user ID. It just represents // the default fingerprints for the user. - final int effectiveGroupId = getEffectiveUserId(groupId); + if (!isCurrentUserOrProfile(groupId)) { + return; + } final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { - startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted); + startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted); } }); } @@ -1011,15 +1013,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe @Override // Binder call public void rename(final int fingerId, final int groupId, final String name) { checkPermission(MANAGE_FINGERPRINT); - - // Group ID is arbitrarily set to parent profile user ID. It just represents - // the default fingerprints for the user. - final int effectiveGroupId = getEffectiveUserId(groupId); + if (!isCurrentUserOrProfile(groupId)) { + return; + } mHandler.post(new Runnable() { @Override public void run() { mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, - effectiveGroupId, name); + groupId, name); } }); } @@ -1029,9 +1030,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) { return Collections.emptyList(); } - int effectiveUserId = getEffectiveUserId(userId); + if (!isCurrentUserOrProfile(userId)) { + return Collections.emptyList(); + } - return FingerprintService.this.getEnrolledFingerprints(effectiveUserId); + return FingerprintService.this.getEnrolledFingerprints(userId); } @Override // Binder call @@ -1040,8 +1043,10 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return false; } - int effectiveUserId = getEffectiveUserId(userId); - return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId); + if (!isCurrentUserOrProfile(userId)) { + return false; + } + return FingerprintService.this.hasEnrolledFingerprints(userId); } @Override // Binder call diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index bd888d809d78..fba7e7d76ac3 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -92,7 +92,7 @@ public final class JobSchedulerService extends com.android.server.SystemService /** The maximum number of concurrent jobs we run at one time. */ private static final int MAX_JOB_CONTEXTS_COUNT = 8; /** Enforce a per-app limit on scheduled jobs? */ - private static final boolean ENFORCE_MAX_JOBS = false; + private static final boolean ENFORCE_MAX_JOBS = true; /** The maximum number of jobs that we allow an unprivileged app to schedule */ private static final int MAX_JOBS_PER_APP = 100; diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 4268dab01a92..9837a566eb2d 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -543,7 +543,7 @@ public class JobStore { return null; } - final String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName"); + String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName"); final String sourceTag = parser.getAttributeValue(null, "sourceTag"); @@ -660,6 +660,18 @@ public class JobStore { jobBuilder.setExtras(extras); parser.nextTag(); // Consume </extras> + // Migrate sync jobs forward from earlier, incomplete representation + if ("android".equals(sourcePackageName) + && extras != null + && extras.getBoolean("SyncManagerJob", false)) { + sourcePackageName = extras.getString("owningPackage", sourcePackageName); + if (DEBUG) { + Slog.i(TAG, "Fixing up sync job source package name from 'android' to '" + + sourcePackageName + "'"); + } + } + + // And now we're done JobStatus js = new JobStatus( jobBuilder.build(), uid, sourcePackageName, sourceUserId, sourceTag, elapsedRuntimes.first, elapsedRuntimes.second); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java index a5dc008d4e6c..a626b5b33012 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java @@ -16,6 +16,8 @@ package com.android.server.net; +import static android.net.NetworkPolicyManager.POLICY_NONE; +import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; import static android.net.wifi.WifiInfo.removeDoubleQuotes; import static com.android.server.net.NetworkPolicyManagerService.newWifiPolicy; import static com.android.server.net.NetworkPolicyManagerService.TAG; @@ -83,6 +85,8 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { pw.println(""); pw.println(" add restrict-background-whitelist UID"); pw.println(" Adds a UID to the whitelist for restrict background usage."); + pw.println(" add restrict-background-blacklist UID"); + pw.println(" Adds a UID to the blacklist for restrict background usage."); pw.println(" get metered-network ID"); pw.println(" Checks whether the given non-mobile network is metered or not."); pw.println(" get restrict-background"); @@ -93,8 +97,12 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { pw.println(" networks."); pw.println(" list restrict-background-whitelist"); pw.println(" Lists UIDs that are whitelisted for restrict background usage."); + pw.println(" list restrict-background-blacklist"); + pw.println(" Lists UIDs that are blacklisted for restrict background usage."); pw.println(" remove restrict-background-whitelist UID"); pw.println(" Removes a UID from the whitelist for restrict background usage."); + pw.println(" remove restrict-background-blacklist UID"); + pw.println(" Removes a UID from the blacklist for restrict background usage."); pw.println(" set metered-network ID BOOLEAN"); pw.println(" Toggles whether the given non-mobile network is metered."); pw.println(" set restrict-background BOOLEAN"); @@ -147,6 +155,8 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { return listMeteredWifiNetworks(); case "restrict-background-whitelist": return listRestrictBackgroundWhitelist(); + case "restrict-background-blacklist": + return listRestrictBackgroundBlacklist(); } pw.println("Error: unknown list type '" + type + "'"); return -1; @@ -162,6 +172,8 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { switch(type) { case "restrict-background-whitelist": return addRestrictBackgroundWhitelist(); + case "restrict-background-blacklist": + return addRestrictBackgroundBlacklist(); } pw.println("Error: unknown add type '" + type + "'"); return -1; @@ -177,6 +189,8 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { switch(type) { case "restrict-background-whitelist": return removeRestrictBackgroundWhitelist(); + case "restrict-background-blacklist": + return removeRestrictBackgroundBlacklist(); } pw.println("Error: unknown remove type '" + type + "'"); return -1; @@ -199,6 +213,24 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { return 0; } + private int listRestrictBackgroundBlacklist() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + + final int[] uids = mInterface.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND); + pw.print("Restrict background blacklisted UIDs: "); + if (uids.length == 0) { + pw.println("none"); + } else { + for (int i = 0; i < uids.length; i++) { + int uid = uids[i]; + pw.print(uid); + pw.print(' '); + } + } + pw.println(); + return 0; + } + private int getRestrictBackground() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); pw.print("Restrict background status: "); @@ -233,6 +265,24 @@ class NetworkPolicyManagerShellCommand extends ShellCommand { return 0; } + private int addRestrictBackgroundBlacklist() throws RemoteException { + final int uid = getUidFromNextArg(); + if (uid < 0) { + return uid; + } + mInterface.setUidPolicy(uid, POLICY_REJECT_METERED_BACKGROUND); + return 0; + } + + private int removeRestrictBackgroundBlacklist() throws RemoteException { + final int uid = getUidFromNextArg(); + if (uid < 0) { + return uid; + } + mInterface.setUidPolicy(uid, POLICY_NONE); + return 0; + } + private int listMeteredWifiNetworks() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final String arg = getNextArg(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index e4c3c1432167..e8d27dbb80f3 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1698,9 +1698,9 @@ public class NotificationManagerService extends SystemService { } @Override - public List<AutomaticZenRule> getAutomaticZenRules() throws RemoteException { + public List<ZenModeConfig.ZenRule> getZenRules() throws RemoteException { enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRules"); - return mZenModeHelper.getAutomaticZenRules(); + return mZenModeHelper.getZenRules(); } @Override @@ -1711,7 +1711,7 @@ public class NotificationManagerService extends SystemService { } @Override - public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule) + public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) throws RemoteException { Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null"); Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null"); @@ -1724,7 +1724,7 @@ public class NotificationManagerService extends SystemService { } @Override - public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule) + public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) throws RemoteException { Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null"); Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null"); @@ -1732,7 +1732,7 @@ public class NotificationManagerService extends SystemService { Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null"); enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule"); - return mZenModeHelper.updateAutomaticZenRule(automaticZenRule, + return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule, "updateAutomaticZenRule"); } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 383c1ab5ebef..5c5c8f854105 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -238,13 +238,13 @@ public class ZenModeHelper { return mZenMode; } - public List<AutomaticZenRule> getAutomaticZenRules() { - List<AutomaticZenRule> rules = new ArrayList<>(); + public List<ZenRule> getZenRules() { + List<ZenRule> rules = new ArrayList<>(); synchronized (mConfig) { if (mConfig == null) return rules; for (ZenRule rule : mConfig.automaticRules.values()) { if (canManageAutomaticZenRule(rule)) { - rules.add(createAutomaticZenRule(rule)); + rules.add(rule); } } } @@ -264,18 +264,18 @@ public class ZenModeHelper { return null; } - public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) { - if (!TextUtils.isEmpty(automaticZenRule.getId())) { - throw new IllegalArgumentException("Rule already exists"); - } + public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) { if (!isSystemRule(automaticZenRule)) { ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner()); if (owner == null) { throw new IllegalArgumentException("Owner is not a condition provider service"); } - final int ruleInstanceLimit = owner.metaData.getInt( - ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); + int ruleInstanceLimit = -1; + if (owner.metaData != null) { + ruleInstanceLimit = owner.metaData.getInt( + ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); + } if (ruleInstanceLimit > 0 && ruleInstanceLimit < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) { throw new IllegalArgumentException("Rule instance limit exceeded"); @@ -293,14 +293,15 @@ public class ZenModeHelper { populateZenRule(automaticZenRule, rule, true); newConfig.automaticRules.put(rule.id, rule); if (setConfigLocked(newConfig, reason, true)) { - return createAutomaticZenRule(rule); + return rule.id; } else { return null; } } } - public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) { + public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, + String reason) { ZenModeConfig newConfig; synchronized (mConfig) { if (mConfig == null) return false; @@ -309,7 +310,6 @@ public class ZenModeHelper { + " reason=" + reason); } newConfig = mConfig.copy(); - final String ruleId = automaticZenRule.getId(); ZenModeConfig.ZenRule rule; if (ruleId == null) { throw new IllegalArgumentException("Rule doesn't exist"); @@ -437,7 +437,7 @@ public class ZenModeHelper { private AutomaticZenRule createAutomaticZenRule(ZenRule rule) { return new AutomaticZenRule(rule.name, rule.component, rule.conditionId, NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled, - rule.id, rule.creationTime); + rule.creationTime); } public void setManualZenMode(int zenMode, Uri conditionId, String reason) { diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 9a5a183233e2..d6b59f9ab35a 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -788,7 +788,7 @@ final class DefaultPermissionGrantPolicy { } private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions, - boolean systemFixed, boolean overrideUserChoice, int userId) { + boolean systemFixed, boolean isDefaultPhoneOrSms, int userId) { if (pkg.requestedPermissions.isEmpty()) { return; } @@ -796,7 +796,13 @@ final class DefaultPermissionGrantPolicy { List<String> requestedPermissions = pkg.requestedPermissions; Set<String> grantablePermissions = null; - if (pkg.isUpdatedSystemApp()) { + // If this is the default Phone or SMS app we grant permissions regardless + // whether the version on the system image declares the permission as used since + // selecting the app as the default Phone or SMS the user makes a deliberate + // choice to grant this app the permissions needed to function. For all other + // apps, (default grants on first boot and user creation) we don't grant default + // permissions if the version on the system image does not declare them. + if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) { PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName); if (sysPs != null) { if (sysPs.pkg.requestedPermissions.isEmpty()) { @@ -828,7 +834,7 @@ final class DefaultPermissionGrantPolicy { // Unless the caller wants to override user choices. The override is // to make sure we can grant the needed permission to the default // sms and phone apps after the user chooses this in the UI. - if (flags == 0 || overrideUserChoice) { + if (flags == 0 || isDefaultPhoneOrSms) { // Never clobber policy or system. final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED | PackageManager.FLAG_PERMISSION_POLICY_FIXED; diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index a3af561bf44f..a084d866ec64 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser; import android.content.pm.PackageParser.Package; +import android.os.Environment; import android.os.PowerManager; import android.os.UserHandle; import android.os.WorkSource; @@ -164,6 +165,10 @@ class PackageDexOptimizer { } for (String path : paths) { + if (useProfiles && isUsedByOtherApps(path)) { + // We cannot use profile guided compilation if the apk was used by another app. + useProfiles = false; + } int dexoptNeeded; try { @@ -204,8 +209,10 @@ class PackageDexOptimizer { + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable + " extractOnly=" + extractOnly + " oatDir = " + oatDir); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + // Profile guide compiled oat files should not be public. + final boolean isPublic = !pkg.isForwardLocked() && !useProfiles; final int dexFlags = adjustDexoptFlags( - (!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0) + ( isPublic ? DEXOPT_PUBLIC : 0) | (vmSafeMode ? DEXOPT_SAFEMODE : 0) | (debuggable ? DEXOPT_DEBUGGABLE : 0) | (extractOnly ? DEXOPT_EXTRACTONLY : 0) @@ -275,6 +282,25 @@ class PackageDexOptimizer { mSystemReady = true; } + private boolean isUsedByOtherApps(String apkPath) { + try { + apkPath = new File(apkPath).getCanonicalPath(); + } catch (IOException e) { + // Log an error but continue without it. + Slog.w(TAG, "Failed to get canonical path", e); + } + String useMarker = apkPath.replace('/', '@'); + final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); + for (int i = 0; i < currentUserIds.length; i++) { + File profileDir = Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]); + File foreignUseMark = new File(profileDir, useMarker); + if (foreignUseMark.exists()) { + return true; + } + } + return false; + } + /** * A specialized PackageDexOptimizer that overrides already-installed checks, forcing a * dexopt path. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 998869472c17..7f4976509bab 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -153,7 +153,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.content.pm.UserInfo; -import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.res.Resources; @@ -173,6 +172,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; +import android.os.Parcelable; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -2888,7 +2888,8 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean isPackageAvailable(String packageName, int userId) { if (!sUserManager.exists(userId)) return false; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "is package available"); synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (p != null) { @@ -2908,7 +2909,8 @@ public class PackageManagerService extends IPackageManager.Stub { public PackageInfo getPackageInfo(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForPackage(flags, userId, packageName); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get package info"); // reader synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); @@ -2954,7 +2956,8 @@ public class PackageManagerService extends IPackageManager.Stub { public int getPackageUid(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return -1; flags = updateFlagsForPackage(flags, userId, packageName); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get package uid"); // reader synchronized (mPackages) { @@ -2977,7 +2980,8 @@ public class PackageManagerService extends IPackageManager.Stub { public int[] getPackageGids(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForPackage(flags, userId, packageName); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "getPackageGids"); // reader @@ -3117,7 +3121,8 @@ public class PackageManagerService extends IPackageManager.Stub { public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForApplication(flags, userId, packageName); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get application info"); // writer synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); @@ -3332,7 +3337,8 @@ public class PackageManagerService extends IPackageManager.Stub { public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get activity info"); synchronized (mPackages) { PackageParser.Activity a = mActivities.mActivities.get(component); @@ -3377,7 +3383,8 @@ public class PackageManagerService extends IPackageManager.Stub { public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get receiver info"); synchronized (mPackages) { PackageParser.Activity a = mReceivers.mActivities.get(component); if (DEBUG_PACKAGE_INFO) Log.v( @@ -3396,7 +3403,8 @@ public class PackageManagerService extends IPackageManager.Stub { public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get service info"); synchronized (mPackages) { PackageParser.Service s = mServices.mServices.get(component); if (DEBUG_PACKAGE_INFO) Log.v( @@ -3415,7 +3423,8 @@ public class PackageManagerService extends IPackageManager.Stub { public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "get provider info"); synchronized (mPackages) { PackageParser.Provider p = mProviders.mProviders.get(component); if (DEBUG_PACKAGE_INFO) Log.v( @@ -3807,7 +3816,8 @@ public class PackageManagerService extends IPackageManager.Stub { android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, "grantRuntimePermission"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, true /* checkShell */, "grantRuntimePermission"); final int uid; @@ -3918,7 +3928,8 @@ public class PackageManagerService extends IPackageManager.Stub { android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, "revokeRuntimePermission"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, true /* checkShell */, "revokeRuntimePermission"); final int appId; @@ -4022,7 +4033,8 @@ public class PackageManagerService extends IPackageManager.Stub { enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, "getPermissionFlags"); synchronized (mPackages) { @@ -4055,7 +4067,8 @@ public class PackageManagerService extends IPackageManager.Stub { enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, true /* checkShell */, "updatePermissionFlags"); // Only the system can change these flags and nothing else. @@ -4112,7 +4125,8 @@ public class PackageManagerService extends IPackageManager.Stub { enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlagsForAllApps"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, true /* checkShell */, "updatePermissionFlagsForAllApps"); // Only the system can change system fixed flags. @@ -4545,7 +4559,8 @@ public class PackageManagerService extends IPackageManager.Stub { int flags, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForResolve(flags, userId, intent); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, "resolve intent"); List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId); final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId); @@ -5006,7 +5021,9 @@ public class PackageManagerService extends IPackageManager.Stub { String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return Collections.emptyList(); flags = updateFlagsForResolve(flags, userId, intent); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, + "query intent activities"); ComponentName comp = intent.getComponent(); if (comp == null) { if (intent.getSelector() != null) { @@ -5496,8 +5513,9 @@ public class PackageManagerService extends IPackageManager.Stub { String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return Collections.emptyList(); flags = updateFlagsForResolve(flags, userId, intent); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, - false, "query intent activity options"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + false /* requireFullPermission */, false /* checkShell */, + "query intent activity options"); final String resultsAction = intent.getAction(); List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags @@ -5798,7 +5816,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList(); flags = updateFlagsForPackage(flags, userId, null); final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0; - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, + "get installed packages"); // writer synchronized (mPackages) { @@ -5950,7 +5970,8 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS, "getEphemeralApplications"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, "getEphemeralApplications"); synchronized (mPackages) { List<EphemeralApplicationInfo> ephemeralApps = mEphemeralApplicationRegistry @@ -5964,7 +5985,8 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean isEphemeralApplication(String packageName, int userId) { - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, "isEphemeral"); if (DISABLE_EPHEMERAL_APPS) { return false; @@ -5988,7 +6010,8 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, "getCookie"); if (!isCallerSameApp(packageName)) { return null; @@ -6005,7 +6028,8 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, true /* checkShell */, "setCookie"); if (!isCallerSameApp(packageName)) { return false; @@ -6024,7 +6048,8 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS, "getEphemeralApplicationIcon"); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, "getEphemeralApplicationIcon"); synchronized (mPackages) { return mEphemeralApplicationRegistry.getEphemeralApplicationIconLPw( @@ -10376,21 +10401,13 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void installPackage(String originPath, IPackageInstallObserver2 observer, - int installFlags, String installerPackageName, VerificationParams verificationParams, - String packageAbiOverride) { - installPackageAsUser(originPath, observer, installFlags, installerPackageName, - verificationParams, packageAbiOverride, UserHandle.getCallingUserId()); - } - - @Override public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer, - int installFlags, String installerPackageName, VerificationParams verificationParams, - String packageAbiOverride, int userId) { + int installFlags, String installerPackageName, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser"); + enforceCrossUserPermission(callingUid, userId, + true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser"); if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { try { @@ -10429,14 +10446,15 @@ public class PackageManagerService extends IPackageManager.Stub { + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag"); } - verificationParams.setInstallerUid(callingUid); - final File originFile = new File(originPath); final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile); final Message msg = mHandler.obtainMessage(INIT_COPY); - final InstallParams params = new InstallParams(origin, null, observer, installFlags, - installerPackageName, null, verificationParams, user, packageAbiOverride, null); + final VerificationInfo verificationInfo = new VerificationInfo( + null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid); + final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer, + installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user, + null /*packageAbiOverride*/, null /*grantedPermissions*/); params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params)); msg.obj = params; @@ -10456,10 +10474,9 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.d(TAG, "Ephemeral install of " + packageName); } } - final VerificationParams verifParams = new VerificationParams( - null, sessionParams.originatingUri, sessionParams.referrerUri, - sessionParams.originatingUid); - verifParams.setInstallerUid(installerUid); + final VerificationInfo verificationInfo = new VerificationInfo( + sessionParams.originatingUri, sessionParams.referrerUri, + sessionParams.originatingUid, installerUid); final OriginInfo origin; if (stagedDir != null) { @@ -10471,7 +10488,7 @@ public class PackageManagerService extends IPackageManager.Stub { final Message msg = mHandler.obtainMessage(INIT_COPY); final InstallParams params = new InstallParams(origin, null, observer, sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid, - verifParams, user, sessionParams.abiOverride, + verificationInfo, user, sessionParams.abiOverride, sessionParams.grantedRuntimePermissions); params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params)); msg.obj = params; @@ -10521,7 +10538,8 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, true, true, + enforceCrossUserPermission(uid, userId, + true /* requireFullPermission */, true /* checkShell */, "setApplicationHiddenSetting for user " + userId); if (hidden && isPackageDeviceAdmin(packageName, userId)) { @@ -10594,8 +10612,9 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, - false, "getApplicationHidden for user " + userId); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, + "getApplicationHidden for user " + userId); PackageSetting pkgSetting; long callingId = Binder.clearCallingIdentity(); try { @@ -10621,8 +10640,9 @@ public class PackageManagerService extends IPackageManager.Stub { null); PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, true, true, "installExistingPackage for user " - + userId); + enforceCrossUserPermission(uid, userId, + true /* requireFullPermission */, true /* checkShell */, + "installExistingPackage for user " + userId); if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { return PackageManager.INSTALL_FAILED_USER_RESTRICTED; } @@ -10671,7 +10691,8 @@ public class PackageManagerService extends IPackageManager.Stub { public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, true, + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, true /* checkShell */, "setPackagesSuspended for user " + userId); if (ArrayUtils.isEmpty(packageNames)) { @@ -10729,8 +10750,9 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean isPackageSuspendedForUser(String packageName, int userId) { - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, - false, "isPackageSuspendedForUser for user " + userId); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, + "isPackageSuspendedForUser for user " + userId); synchronized (mPackages) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); return pkgSetting != null && pkgSetting.getSuspended(userId); @@ -11506,6 +11528,30 @@ public class PackageManagerService extends IPackageManager.Stub { } } + static class VerificationInfo { + /** A constant used to indicate that a uid value is not present. */ + public static final int NO_UID = -1; + + /** URI referencing where the package was downloaded from. */ + final Uri originatingUri; + + /** HTTP referrer URI associated with the originatingURI. */ + final Uri referrer; + + /** UID of the application that the install request originated from. */ + final int originatingUid; + + /** UID of application requesting the install */ + final int installerUid; + + VerificationInfo(Uri originatingUri, Uri referrer, int originatingUid, int installerUid) { + this.originatingUri = originatingUri; + this.referrer = referrer; + this.originatingUid = originatingUid; + this.installerUid = installerUid; + } + } + class InstallParams extends HandlerParams { final OriginInfo origin; final MoveInfo move; @@ -11513,15 +11559,15 @@ public class PackageManagerService extends IPackageManager.Stub { int installFlags; final String installerPackageName; final String volumeUuid; - final VerificationParams verificationParams; private InstallArgs mArgs; private int mRet; final String packageAbiOverride; final String[] grantedRuntimePermissions; + final VerificationInfo verificationInfo; InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, String volumeUuid, - VerificationParams verificationParams, UserHandle user, String packageAbiOverride, + VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride, String[] grantedPermissions) { super(user); this.origin = origin; @@ -11530,7 +11576,7 @@ public class PackageManagerService extends IPackageManager.Stub { this.installFlags = installFlags; this.installerPackageName = installerPackageName; this.volumeUuid = volumeUuid; - this.verificationParams = verificationParams; + this.verificationInfo = verificationInfo; this.packageAbiOverride = packageAbiOverride; this.grantedRuntimePermissions = grantedPermissions; } @@ -11794,26 +11840,22 @@ public class PackageManagerService extends IPackageManager.Stub { verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode); - if (verificationParams != null) { - if (verificationParams.getVerificationURI() != null) { - verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI, - verificationParams.getVerificationURI()); - } - if (verificationParams.getOriginatingURI() != null) { + if (verificationInfo != null) { + if (verificationInfo.originatingUri != null) { verification.putExtra(Intent.EXTRA_ORIGINATING_URI, - verificationParams.getOriginatingURI()); + verificationInfo.originatingUri); } - if (verificationParams.getReferrer() != null) { + if (verificationInfo.referrer != null) { verification.putExtra(Intent.EXTRA_REFERRER, - verificationParams.getReferrer()); + verificationInfo.referrer); } - if (verificationParams.getOriginatingUid() >= 0) { + if (verificationInfo.originatingUid >= 0) { verification.putExtra(Intent.EXTRA_ORIGINATING_UID, - verificationParams.getOriginatingUid()); + verificationInfo.originatingUid); } - if (verificationParams.getInstallerUid() >= 0) { + if (verificationInfo.installerUid >= 0) { verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID, - verificationParams.getInstallerUid()); + verificationInfo.installerUid); } } @@ -14102,25 +14144,48 @@ public class PackageManagerService extends IPackageManager.Stub { return; } - for (int currentUserId : users) { - if (getBlockUninstallForUser(packageName, currentUserId)) { - try { - observer.onPackageDeleted(packageName, - PackageManager.DELETE_FAILED_OWNER_BLOCKED, null); - } catch (RemoteException re) { - } - return; + if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) { + try { + observer.onPackageDeleted(packageName, + PackageManager.DELETE_FAILED_OWNER_BLOCKED, null); + } catch (RemoteException re) { } + return; } if (DEBUG_REMOVE) { - Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId); + Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId + + " deleteAllUsers: " + deleteAllUsers ); } // Queue up an async operation since the package deletion may take a little while. mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); - final int returnCode = deletePackageX(packageName, userId, flags); + int returnCode; + if (!deleteAllUsers) { + returnCode = deletePackageX(packageName, userId, flags); + } else { + int[] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users); + // If nobody is blocking uninstall, proceed with delete for all users + if (ArrayUtils.isEmpty(blockUninstallUserIds)) { + returnCode = deletePackageX(packageName, userId, flags); + } else { + // Otherwise uninstall individually for users with blockUninstalls=false + final int userFlags = flags & ~PackageManager.DELETE_ALL_USERS; + for (int userId : users) { + if (!ArrayUtils.contains(blockUninstallUserIds, userId)) { + returnCode = deletePackageX(packageName, userId, userFlags); + if (returnCode != PackageManager.DELETE_SUCCEEDED) { + Slog.w(TAG, "Package delete failed for user " + userId + + ", returnCode " + returnCode); + } + } + } + // The app has only been marked uninstalled for certain users. + // We still need to report that delete was blocked + returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED; + } + } try { observer.onPackageDeleted(packageName, returnCode, null); } catch (RemoteException e) { @@ -14130,6 +14195,16 @@ public class PackageManagerService extends IPackageManager.Stub { }); } + private int[] getBlockUninstallForUsers(String packageName, int[] userIds) { + int[] result = EMPTY_INT_ARRAY; + for (int userId : userIds) { + if (getBlockUninstallForUser(packageName, userId)) { + result = ArrayUtils.appendInt(result, userId); + } + } + return result; + } + @Override public boolean isPackageDeviceAdminOnAnyUser(String packageName) { return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL); @@ -14981,7 +15056,8 @@ public class PackageManagerService extends IPackageManager.Stub { final IPackageDataObserver observer, final int userId) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CLEAR_APP_USER_DATA, null); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "clear application data"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, + true /* requireFullPermission */, false /* checkShell */, "clear application data"); // Queue up an async operation since the package deletion may take a little while. mHandler.post(new Runnable() { public void run() { @@ -15444,7 +15520,8 @@ public class PackageManagerService extends IPackageManager.Stub { String opname) { // writer int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true, false, "add preferred activity"); + enforceCrossUserPermission(callingUid, userId, + true /* requireFullPermission */, false /* checkShell */, "add preferred activity"); if (filter.countActions() == 0) { Slog.w(TAG, "Cannot set a preferred activity with no filter actions"); return; @@ -15489,7 +15566,9 @@ public class PackageManagerService extends IPackageManager.Stub { } final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true, false, "replace preferred activity"); + enforceCrossUserPermission(callingUid, userId, + true /* requireFullPermission */, false /* checkShell */, + "replace preferred activity"); synchronized (mPackages) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) @@ -16307,7 +16386,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); final int uid = Binder.getCallingUid(); final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); - enforceCrossUserPermission(uid, userId, false, true, "set enabled"); + enforceCrossUserPermission(uid, userId, + false /* requireFullPermission */, true /* checkShell */, "set enabled"); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); boolean sendNow = false; boolean isApp = (className == null); @@ -16446,7 +16526,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); - enforceCrossUserPermission(uid, userId, true, true, "stop package"); + enforceCrossUserPermission(uid, userId, + true /* requireFullPermission */, true /* checkShell */, "stop package"); // writer synchronized (mPackages) { if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped, @@ -16468,7 +16549,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public int getApplicationEnabledSetting(String packageName, int userId) { if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED; int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, false, false, "get enabled"); + enforceCrossUserPermission(uid, userId, + false /* requireFullPermission */, false /* checkShell */, "get enabled"); // reader synchronized (mPackages) { return mSettings.getApplicationEnabledSettingLPr(packageName, userId); @@ -16479,7 +16561,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public int getComponentEnabledSetting(ComponentName componentName, int userId) { if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED; int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, false, false, "get component enabled"); + enforceCrossUserPermission(uid, userId, + false /* requireFullPermission */, false /* checkShell */, "get component enabled"); // reader synchronized (mPackages) { return mSettings.getComponentEnabledSettingLPr(componentName, userId); @@ -18384,7 +18467,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); final Message msg = mHandler.obtainMessage(INIT_COPY); final OriginInfo origin = OriginInfo.fromExistingFile(codeFile); final InstallParams params = new InstallParams(origin, move, installObserver, installFlags, - installerPackageName, volumeUuid, null, user, packageAbiOverride, null); + installerPackageName, volumeUuid, null /*verificationInfo*/, user, + packageAbiOverride, null); params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params)); msg.obj = params; diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 8a2729eec805..49aaa4aa1047 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -2512,7 +2512,7 @@ public final class TvInputManagerService extends SystemService { // For the recording session only @Override - public void onTuned() { + public void onTuned(Uri channelUri) { synchronized (mLock) { if (DEBUG) { Slog.d(TAG, "onTuned()"); @@ -2521,7 +2521,7 @@ public final class TvInputManagerService extends SystemService { return; } try { - mSessionState.client.onTuned(mSessionState.seq); + mSessionState.client.onTuned(mSessionState.seq, channelUri); } catch (RemoteException e) { Slog.e(TAG, "error in onTuned", e); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 69d2d20a9018..fe215d523338 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8777,10 +8777,10 @@ public class WindowManagerService extends IWindowManager.Stub i -= lastBelow; if (i != numRemoved) { displayContent.layoutNeeded = true; - Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + - numRemoved + " windows but added " + i, - new RuntimeException("here").fillInStackTrace()); - for (i=0; i<numRemoved; i++) { + Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() " + + " callers=" + Debug.getCallers(10)); + for (i = 0; i < numRemoved; i++) { WindowState ws = mRebuildTmp[i]; if (ws.mRebuilding) { StringWriter sw = new StringWriter(); diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java index 2a90c60656ab..46ecc50aeafc 100644 --- a/services/net/java/android/net/ip/IpManager.java +++ b/services/net/java/android/net/ip/IpManager.java @@ -241,15 +241,22 @@ public class IpManager extends StateMachine { public IpManager(Context context, String ifName, Callback callback) throws IllegalArgumentException { + this(context, ifName, callback, INetworkManagementService.Stub.asInterface( + ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE))); + } + + /** + * An expanded constructor, useful for dependency injection. + */ + public IpManager(Context context, String ifName, Callback callback, + INetworkManagementService nwService) throws IllegalArgumentException { super(IpManager.class.getSimpleName() + "." + ifName); mTag = getName(); mContext = context; mInterfaceName = ifName; mCallback = callback; - - mNwService = INetworkManagementService.Stub.asInterface( - ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); + mNwService = nwService; mNetlinkTracker = new NetlinkTracker( mInterfaceName, @@ -277,25 +284,6 @@ public class IpManager extends StateMachine { super.start(); } - /** - * A special constructor for use in testing that bypasses some of the more - * complicated setup bits. - * - * TODO: Figure out how to delete this yet preserve testability. - */ - @VisibleForTesting - protected IpManager(String ifName, Callback callback) { - super(IpManager.class.getSimpleName() + ".test-" + ifName); - mTag = getName(); - - mInterfaceName = ifName; - mCallback = callback; - - mContext = null; - mNwService = null; - mNetlinkTracker = null; - } - @Override protected void onQuitting() { mCallback.onQuit(); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index de9020250f25..10808da8785e 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -624,6 +624,21 @@ public final class Call { parcelableCall.getExtras(), parcelableCall.getIntentExtras()); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[pa: "); + sb.append(mAccountHandle); + sb.append(", hdl: "); + sb.append(Log.pii(mHandle)); + sb.append(", caps: "); + sb.append(capabilitiesToString(mCallCapabilities)); + sb.append(", props: "); + sb.append(mCallProperties); + sb.append("]"); + return sb.toString(); + } } public static abstract class Callback { @@ -1000,6 +1015,48 @@ public final class Call { } } + @Override + public String toString() { + return new StringBuilder(). + append("Call [id: "). + append(mTelecomCallId). + append(", state: "). + append(stateToString(mState)). + append(", details: "). + append(mDetails). + append("]").toString(); + } + + /** + * @param state An integer value of a {@code STATE_*} constant. + * @return A string representation of the value. + */ + private static String stateToString(int state) { + switch (state) { + case STATE_NEW: + return "NEW"; + case STATE_RINGING: + return "RINGING"; + case STATE_DIALING: + return "DIALING"; + case STATE_ACTIVE: + return "ACTIVE"; + case STATE_HOLDING: + return "HOLDING"; + case STATE_DISCONNECTED: + return "DISCONNECTED"; + case STATE_CONNECTING: + return "CONNECTING"; + case STATE_DISCONNECTING: + return "DISCONNECTING"; + case STATE_SELECT_PHONE_ACCOUNT: + return "SELECT_PHONE_ACCOUNT"; + default: + Log.w(Call.class, "Unknown state %d", state); + return "UNKNOWN"; + } + } + /** * Adds a listener to this {@code Call}. * diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java index 3f32dbe0fdbe..2ab0525a33c4 100644 --- a/telecomm/java/android/telecom/Log.java +++ b/telecomm/java/android/telecom/Log.java @@ -16,7 +16,10 @@ package android.telecom; +import android.net.Uri; import android.os.AsyncTask; +import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -152,10 +155,37 @@ final public class Log { public static String pii(Object pii) { if (pii == null || VERBOSE) { return String.valueOf(pii); + } if (pii instanceof Uri) { + return piiUri((Uri) pii); } return "[" + secureHash(String.valueOf(pii).getBytes()) + "]"; } + private static String piiUri(Uri handle) { + StringBuilder sb = new StringBuilder(); + String scheme = handle.getScheme(); + if (!TextUtils.isEmpty(scheme)) { + sb.append(scheme).append(":"); + } + String value = handle.getSchemeSpecificPart(); + if (!TextUtils.isEmpty(value)) { + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (PhoneNumberUtils.isStartsPostDial(c)) { + sb.append(c); + } else if (PhoneNumberUtils.isDialable(c)) { + sb.append("*"); + } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { + sb.append("*"); + } else { + sb.append(c); + } + } + } + return sb.toString(); + + } + private static String secureHash(byte[] input) { if (sMessageDigest != null) { sMessageDigest.reset(); diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 857d2df9b73c..605e0d3acd90 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -1425,6 +1425,7 @@ public class TelecomManager { * <p> This method displays the UI to manage blocked numbers only if * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns * {@code true} for the current user. + * @deprecated Use {@link #createManageBlockedNumbersIntent()} instead. */ // TODO: Delete this. public void launchManageBlockedNumbersActivity() { diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index da4346002110..c34d4a919242 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -25,7 +25,6 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; -import android.content.pm.ContainerEncryptionParams; import android.content.pm.EphemeralApplicationInfo; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; @@ -44,7 +43,6 @@ import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -602,14 +600,6 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } - /** @hide */ - @Override - public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer, - int flags, String installerPackageName, int userId) { - throw new UnsupportedOperationException(); - } - - @Override public void setInstallerPackageName(String targetPackage, String installerPackageName) { @@ -873,26 +863,6 @@ public class MockPackageManager extends PackageManager { * @hide */ @Override - public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, - int flags, String installerPackageName, Uri verificationURI, - ContainerEncryptionParams encryptionParams) { - throw new UnsupportedOperationException(); - } - - /** - * @hide - */ - @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, - IPackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { - throw new UnsupportedOperationException(); - } - - /** - * @hide - */ - @Override public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, UserHandle user) { return false; @@ -1024,27 +994,6 @@ public class MockPackageManager extends PackageManager { * @hide */ @Override - public void installPackageWithVerification(Uri packageURI, - PackageInstallObserver observer, int flags, String installerPackageName, - Uri verificationURI, - ContainerEncryptionParams encryptionParams) { - throw new UnsupportedOperationException(); - } - - /** - * @hide - */ - @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, - PackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { - throw new UnsupportedOperationException(); - } - - /** - * @hide - */ - @Override public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId, int flags) { throw new UnsupportedOperationException(); diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java index 3791d0246f69..d7f4a38f7644 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java @@ -140,7 +140,7 @@ public class ActivityManagerPermissionTests extends TestCase { @SmallTest public void testSET_ACTIVITY_WATCHER() { try { - mAm.setActivityController(null); + mAm.setActivityController(null, false); fail("IActivityManager.setActivityController did not throw SecurityException as" + " expected"); } catch (SecurityException e) { diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp index 9837c4efc4d2..bbf7f411d07e 100644 --- a/tools/aapt2/compile/Png.cpp +++ b/tools/aapt2/compile/Png.cpp @@ -1175,7 +1175,7 @@ getout: if (errorMsg) { std::stringstream err; err << "9-patch malformed: " << errorMsg; - if (!errorEdge) { + if (errorEdge) { err << "." << std::endl; if (errorPixel >= 0) { err << "Found at pixel #" << errorPixel << " along " << errorEdge << " edge"; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java index fcfbad2743ed..85e26103fbf5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java @@ -24,7 +24,6 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; -import android.content.pm.ContainerEncryptionParams; import android.content.pm.EphemeralApplicationInfo; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; @@ -43,7 +42,6 @@ import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -555,40 +553,11 @@ public class BridgePackageManager extends PackageManager { } @Override - public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, - int flags, String installerPackageName, Uri verificationURI, - ContainerEncryptionParams encryptionParams) { - } - - @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, - IPackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { - } - - @Override public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags, String installerPackageName) { } @Override - public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,int flags, - String installerPackageName, int userId) { - } - - @Override - public void installPackageWithVerification(Uri packageURI, PackageInstallObserver observer, - int flags, String installerPackageName, Uri verificationURI, - ContainerEncryptionParams encryptionParams) { - } - - @Override - public void installPackageWithVerificationAndEncryption(Uri packageURI, - PackageInstallObserver observer, int flags, String installerPackageName, - VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { - } - - @Override public int installExistingPackage(String packageName) throws NameNotFoundException { return 0; } |