Merge "Update javadoc for carrier phase alignment in getAccumulatedDeltaRangeMeters"
diff --git a/Android.bp b/Android.bp
index 8163ff8..93e6963 100644
--- a/Android.bp
+++ b/Android.bp
@@ -706,6 +706,8 @@
"android.hardware.contexthub-V1.0-java",
"android.hardware.health-V1.0-java-constants",
"android.hardware.thermal-V1.0-java-constants",
+ "android.hardware.thermal-V1.1-java",
+ "android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
@@ -764,6 +766,16 @@
],
}
+// A host library containing the inspector annotations for inspector-annotation-processor.
+java_library_host {
+ name: "inspector-annotation",
+ srcs: [
+ "core/java/android/view/inspector/InspectableChildren.java",
+ "core/java/android/view/inspector/InspectableNodeName.java",
+ "core/java/android/view/inspector/InspectableProperty.java",
+ ],
+}
+
// A host library including just UnsupportedAppUsage.java so that the annotation
// processor can also use this annotation.
java_library_host {
diff --git a/api/current.txt b/api/current.txt
index dd4c781..a5724fe 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -769,6 +769,7 @@
field public static final int insetRight = 16843192; // 0x10101b8
field public static final int insetTop = 16843193; // 0x10101b9
field public static final int installLocation = 16843447; // 0x10102b7
+ field public static final int interactiveUiTimeout = 16844181; // 0x1010595
field public static final int interpolator = 16843073; // 0x1010141
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
field public static final int isAsciiCapable = 16843753; // 0x10103e9
@@ -941,7 +942,6 @@
field public static final int minSdkVersion = 16843276; // 0x101020c
field public static final int minWidth = 16843071; // 0x101013f
field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
- field public static final int minimumUiTimeout = 16844175; // 0x101058f
field public static final int minimumVerticalAngle = 16843902; // 0x101047e
field public static final int mipMap = 16843725; // 0x10103cd
field public static final int mirrorForRtl = 16843726; // 0x10103ce
@@ -965,6 +965,7 @@
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
field public static final int noHistory = 16843309; // 0x101022d
+ field public static final int nonInteractiveUiTimeout = 16844175; // 0x101058f
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
@@ -2886,12 +2887,14 @@
method public int getCapabilities();
method public deprecated java.lang.String getDescription();
method public java.lang.String getId();
- method public int getMinimumUiTimeoutMillis();
+ method public int getInteractiveUiTimeoutMillis();
+ method public int getNonInteractiveUiTimeoutMillis();
method public android.content.pm.ResolveInfo getResolveInfo();
method public java.lang.String getSettingsActivityName();
method public java.lang.String loadDescription(android.content.pm.PackageManager);
method public java.lang.CharSequence loadSummary(android.content.pm.PackageManager);
- method public void setMinimumUiTimeoutMillis(int);
+ method public void setInteractiveUiTimeoutMillis(int);
+ method public void setNonInteractiveUiTimeoutMillis(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
@@ -11176,12 +11179,17 @@
public static class PackageInstaller.Session implements java.io.Closeable {
method public void abandon();
+ method public void addChildSessionId(int);
method public void close();
method public void commit(android.content.IntentSender);
method public void fsync(java.io.OutputStream) throws java.io.IOException;
+ method public int[] getChildSessionIds();
method public java.lang.String[] getNames() throws java.io.IOException;
+ method public int getParentSessionId();
+ method public boolean isMultiPackage();
method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+ method public void removeChildSessionId(int);
method public void removeSplit(java.lang.String) throws java.io.IOException;
method public void setStagingProgress(float);
method public void transfer(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11202,20 +11210,24 @@
method public android.graphics.Bitmap getAppIcon();
method public java.lang.CharSequence getAppLabel();
method public java.lang.String getAppPackageName();
+ method public int[] getChildSessionIds();
method public int getInstallLocation();
method public int getInstallReason();
method public java.lang.String getInstallerPackageName();
method public int getMode();
method public int getOriginatingUid();
method public android.net.Uri getOriginatingUri();
+ method public int getParentSessionId();
method public float getProgress();
method public android.net.Uri getReferrerUri();
method public int getSessionId();
method public long getSize();
method public boolean isActive();
+ method public boolean isMultiPackage();
method public boolean isSealed();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
+ field public static final int INVALID_ID = -1; // 0xffffffff
}
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
@@ -11226,6 +11238,7 @@
method public void setAppPackageName(java.lang.String);
method public void setInstallLocation(int);
method public void setInstallReason(int);
+ method public void setMultiPackage();
method public void setOriginatingUid(int);
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
@@ -13878,6 +13891,7 @@
field public static final int RAW_SENSOR = 32; // 0x20
field public static final int RGB_565 = 4; // 0x4
field public static final int UNKNOWN = 0; // 0x0
+ field public static final int Y8 = 538982489; // 0x20203859
field public static final int YUV_420_888 = 35; // 0x23
field public static final int YUV_422_888 = 39; // 0x27
field public static final int YUV_444_888 = 40; // 0x28
@@ -14769,9 +14783,10 @@
public static class Typeface.CustomFallbackBuilder {
ctor public Typeface.CustomFallbackBuilder(android.graphics.fonts.FontFamily);
+ method public android.graphics.Typeface.CustomFallbackBuilder addCustomFallback(android.graphics.fonts.FontFamily);
method public android.graphics.Typeface build();
- method public android.graphics.Typeface.CustomFallbackBuilder setFallback(java.lang.String);
method public android.graphics.Typeface.CustomFallbackBuilder setStyle(android.graphics.fonts.FontStyle);
+ method public android.graphics.Typeface.CustomFallbackBuilder setSystemFallback(java.lang.String);
}
public class Xfermode {
@@ -14978,7 +14993,7 @@
method public final int getLevel();
method public int getMinimumHeight();
method public int getMinimumWidth();
- method public abstract int getOpacity();
+ method public abstract deprecated int getOpacity();
method public android.graphics.Insets getOpticalInsets();
method public void getOutline(android.graphics.Outline);
method public boolean getPadding(android.graphics.Rect);
@@ -16291,6 +16306,7 @@
method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeys();
method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeysNeedingPermission();
method public java.util.Set<java.lang.String> getPhysicalCameraIds();
+ method public android.hardware.camera2.params.RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap(int);
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AE_AVAILABLE_MODES;
@@ -16953,6 +16969,33 @@
field public static final int SURFACE_GROUP_ID_NONE = -1; // 0xffffffff
}
+ public final class RecommendedStreamConfigurationMap {
+ method public java.util.Set<android.util.Size> getHighResolutionOutputSizes(int);
+ method public java.util.Set<android.util.Range<java.lang.Integer>> getHighSpeedVideoFpsRanges();
+ method public java.util.Set<android.util.Range<java.lang.Integer>> getHighSpeedVideoFpsRangesFor(android.util.Size);
+ method public java.util.Set<android.util.Size> getHighSpeedVideoSizes();
+ method public java.util.Set<android.util.Size> getHighSpeedVideoSizesFor(android.util.Range<java.lang.Integer>);
+ method public java.util.Set<java.lang.Integer> getInputFormats();
+ method public java.util.Set<android.util.Size> getInputSizes(int);
+ method public java.util.Set<java.lang.Integer> getOutputFormats();
+ method public long getOutputMinFrameDuration(int, android.util.Size);
+ method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+ method public java.util.Set<android.util.Size> getOutputSizes(int);
+ method public <T> java.util.Set<android.util.Size> getOutputSizes(java.lang.Class<T>);
+ method public long getOutputStallDuration(int, android.util.Size);
+ method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+ method public int getRecommendedUseCase();
+ method public java.util.Set<java.lang.Integer> getValidOutputFormatsForInput(int);
+ method public boolean isOutputSupportedFor(int);
+ method public boolean isOutputSupportedFor(android.view.Surface);
+ field public static final int USECASE_PREVIEW = 0; // 0x0
+ field public static final int USECASE_RAW = 5; // 0x5
+ field public static final int USECASE_RECORD = 1; // 0x1
+ field public static final int USECASE_SNAPSHOT = 3; // 0x3
+ field public static final int USECASE_VIDEO_SNAPSHOT = 2; // 0x2
+ field public static final int USECASE_ZSL = 4; // 0x4
+ }
+
public final class RggbChannelVector {
ctor public RggbChannelVector(float, float, float, float);
method public void copyTo(float[], int);
@@ -28702,9 +28745,11 @@
field public java.lang.String SSID;
field public java.util.BitSet allowedAuthAlgorithms;
field public java.util.BitSet allowedGroupCiphers;
+ field public java.util.BitSet allowedGroupMgmtCiphers;
field public java.util.BitSet allowedKeyManagement;
field public java.util.BitSet allowedPairwiseCiphers;
field public java.util.BitSet allowedProtocols;
+ field public java.util.BitSet allowedSuiteBCiphers;
field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
field public boolean hiddenSSID;
field public boolean isHomeProviderNetwork;
@@ -28728,6 +28773,7 @@
public static class WifiConfiguration.GroupCipher {
field public static final int CCMP = 3; // 0x3
+ field public static final int GCMP_256 = 5; // 0x5
field public static final int TKIP = 2; // 0x2
field public static final deprecated int WEP104 = 1; // 0x1
field public static final deprecated int WEP40 = 0; // 0x0
@@ -28735,9 +28781,18 @@
field public static final java.lang.String varName = "group";
}
+ public static class WifiConfiguration.GroupMgmtCipher {
+ field public static final int BIP_CMAC_256 = 0; // 0x0
+ field public static final int BIP_GMAC_128 = 1; // 0x1
+ field public static final int BIP_GMAC_256 = 2; // 0x2
+ }
+
public static class WifiConfiguration.KeyMgmt {
field public static final int IEEE8021X = 3; // 0x3
field public static final int NONE = 0; // 0x0
+ field public static final int OWE = 9; // 0x9
+ field public static final int SAE = 8; // 0x8
+ field public static final int SUITE_B_192 = 10; // 0xa
field public static final int WPA_EAP = 2; // 0x2
field public static final int WPA_PSK = 1; // 0x1
field public static final java.lang.String[] strings;
@@ -28746,6 +28801,7 @@
public static class WifiConfiguration.PairwiseCipher {
field public static final int CCMP = 2; // 0x2
+ field public static final int GCMP_256 = 3; // 0x3
field public static final int NONE = 0; // 0x0
field public static final deprecated int TKIP = 1; // 0x1
field public static final java.lang.String[] strings;
@@ -28867,7 +28923,7 @@
method public boolean isEnhancedPowerReportingSupported();
method public boolean isP2pSupported();
method public boolean isPreferredNetworkOffloadSupported();
- method public boolean isScanAlwaysAvailable();
+ method public deprecated boolean isScanAlwaysAvailable();
method public boolean isTdlsSupported();
method public boolean isWifiEnabled();
method public deprecated boolean pingSupplicant();
@@ -34399,7 +34455,7 @@
}
public final class StorageVolume implements android.os.Parcelable {
- method public android.content.Intent createAccessIntent(java.lang.String);
+ method public deprecated android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
method public java.lang.String getState();
@@ -35638,6 +35694,15 @@
method public static java.lang.String getLastOutgoingCall(android.content.Context);
field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
field public static final int BLOCKED_TYPE = 6; // 0x6
+ field public static final java.lang.String BLOCK_REASON = "block_reason";
+ field public static final int BLOCK_REASON_BLOCKED_NUMBER = 3; // 0x3
+ field public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1; // 0x1
+ field public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2; // 0x2
+ field public static final int BLOCK_REASON_NOT_BLOCKED = 0; // 0x0
+ field public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7; // 0x7
+ field public static final int BLOCK_REASON_PAY_PHONE = 6; // 0x6
+ field public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5; // 0x5
+ field public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4; // 0x4
field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
field public static final java.lang.String CACHED_MATCHED_NUMBER = "matched_number";
@@ -35647,6 +35712,8 @@
field public static final java.lang.String CACHED_NUMBER_TYPE = "numbertype";
field public static final java.lang.String CACHED_PHOTO_ID = "photo_id";
field public static final java.lang.String CACHED_PHOTO_URI = "photo_uri";
+ field public static final java.lang.String CALL_SCREENING_APP_NAME = "call_screening_app_name";
+ field public static final java.lang.String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
@@ -37439,7 +37506,7 @@
field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
- field public static final java.lang.String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS = "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
+ field public static final deprecated java.lang.String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS = "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
@@ -40299,6 +40366,7 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public boolean audiblyAlerted();
method public boolean canShowBadge();
method public android.app.NotificationChannel getChannel();
method public int getImportance();
@@ -42831,6 +42899,16 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityLte> CREATOR;
}
+ public final class CellIdentityNr extends android.telephony.CellIdentity {
+ method public int getChannelNumber();
+ method public java.lang.String getMccString();
+ method public java.lang.String getMncString();
+ method public int getPci();
+ method public int getTac();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR;
+ }
+
public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
method public int getCid();
method public int getCpid();
@@ -42890,6 +42968,13 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellInfoLte> CREATOR;
}
+ public final class CellInfoNr extends android.telephony.CellInfo {
+ method public android.telephony.CellIdentity getCellIdentity();
+ method public android.telephony.CellSignalStrength getCellSignalStrength();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellInfoNr> CREATOR;
+ }
+
public final class CellInfoWcdma extends android.telephony.CellInfo implements android.os.Parcelable {
method public android.telephony.CellIdentityWcdma getCellIdentity();
method public android.telephony.CellSignalStrengthWcdma getCellSignalStrength();
@@ -42956,6 +43041,21 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthLte> CREATOR;
}
+ public final class CellSignalStrengthNr extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getAsuLevel();
+ method public int getCsiRsrp();
+ method public int getCsiRsrq();
+ method public int getCsiSinr();
+ method public int getDbm();
+ method public int getLevel();
+ method public int getSsRsrp();
+ method public int getSsRsrq();
+ method public int getSsSinr();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthNr> CREATOR;
+ }
+
public final class CellSignalStrengthWcdma extends android.telephony.CellSignalStrength implements android.os.Parcelable {
method public int describeContents();
method public int getAsuLevel();
@@ -50143,17 +50243,29 @@
method public int getStableInsetLeft();
method public int getStableInsetRight();
method public int getStableInsetTop();
+ method public android.graphics.Insets getStableInsets();
method public int getSystemWindowInsetBottom();
method public int getSystemWindowInsetLeft();
method public int getSystemWindowInsetRight();
method public int getSystemWindowInsetTop();
+ method public android.graphics.Insets getSystemWindowInsets();
method public boolean hasInsets();
method public boolean hasStableInsets();
method public boolean hasSystemWindowInsets();
+ method public android.view.WindowInsets inset(int, int, int, int);
method public boolean isConsumed();
method public boolean isRound();
- method public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
- method public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect);
+ method public deprecated android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
+ method public deprecated android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect);
+ }
+
+ public static class WindowInsets.Builder {
+ ctor public WindowInsets.Builder();
+ ctor public WindowInsets.Builder(android.view.WindowInsets);
+ method public android.view.WindowInsets build();
+ method public android.view.WindowInsets.Builder setDisplayCutout(android.view.DisplayCutout);
+ method public android.view.WindowInsets.Builder setStableInsets(android.graphics.Insets);
+ method public android.view.WindowInsets.Builder setSystemWindowInsets(android.graphics.Insets);
}
public abstract interface WindowManager implements android.view.ViewManager {
@@ -50409,7 +50521,7 @@
method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
- method public int getMinimumUiTimeoutMillis();
+ method public int getRecommendedTimeoutMillis(int, int);
method public void interrupt();
method public static boolean isAccessibilityButtonSupported();
method public boolean isEnabled();
@@ -50418,6 +50530,9 @@
method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ field public static final int FLAG_CONTENT_CONTROLS = 4; // 0x4
+ field public static final int FLAG_CONTENT_ICONS = 1; // 0x1
+ field public static final int FLAG_CONTENT_TEXT = 2; // 0x2
}
public static abstract interface AccessibilityManager.AccessibilityStateChangeListener {
@@ -73691,10 +73806,13 @@
method public abstract void beginHandshake() throws javax.net.ssl.SSLException;
method public abstract void closeInbound() throws javax.net.ssl.SSLException;
method public abstract void closeOutbound();
+ method public java.lang.String getApplicationProtocol();
method public abstract java.lang.Runnable getDelegatedTask();
method public abstract boolean getEnableSessionCreation();
method public abstract java.lang.String[] getEnabledCipherSuites();
method public abstract java.lang.String[] getEnabledProtocols();
+ method public java.lang.String getHandshakeApplicationProtocol();
+ method public java.util.function.BiFunction<javax.net.ssl.SSLEngine, java.util.List<java.lang.String>, java.lang.String> getHandshakeApplicationProtocolSelector();
method public javax.net.ssl.SSLSession getHandshakeSession();
method public abstract javax.net.ssl.SSLEngineResult.HandshakeStatus getHandshakeStatus();
method public abstract boolean getNeedClientAuth();
@@ -73711,6 +73829,7 @@
method public abstract void setEnableSessionCreation(boolean);
method public abstract void setEnabledCipherSuites(java.lang.String[]);
method public abstract void setEnabledProtocols(java.lang.String[]);
+ method public void setHandshakeApplicationProtocolSelector(java.util.function.BiFunction<javax.net.ssl.SSLEngine, java.util.List<java.lang.String>, java.lang.String>);
method public abstract void setNeedClientAuth(boolean);
method public void setSSLParameters(javax.net.ssl.SSLParameters);
method public abstract void setUseClientMode(boolean);
@@ -73769,6 +73888,7 @@
ctor public SSLParameters(java.lang.String[]);
ctor public SSLParameters(java.lang.String[], java.lang.String[]);
method public java.security.AlgorithmConstraints getAlgorithmConstraints();
+ method public java.lang.String[] getApplicationProtocols();
method public java.lang.String[] getCipherSuites();
method public java.lang.String getEndpointIdentificationAlgorithm();
method public boolean getNeedClientAuth();
@@ -73778,6 +73898,7 @@
method public final boolean getUseCipherSuitesOrder();
method public boolean getWantClientAuth();
method public void setAlgorithmConstraints(java.security.AlgorithmConstraints);
+ method public void setApplicationProtocols(java.lang.String[]);
method public void setCipherSuites(java.lang.String[]);
method public void setEndpointIdentificationAlgorithm(java.lang.String);
method public void setNeedClientAuth(boolean);
@@ -73882,9 +74003,12 @@
ctor protected SSLSocket(java.lang.String, int, java.net.InetAddress, int) throws java.io.IOException, java.net.UnknownHostException;
ctor protected SSLSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
method public abstract void addHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener);
+ method public java.lang.String getApplicationProtocol();
method public abstract boolean getEnableSessionCreation();
method public abstract java.lang.String[] getEnabledCipherSuites();
method public abstract java.lang.String[] getEnabledProtocols();
+ method public java.lang.String getHandshakeApplicationProtocol();
+ method public java.util.function.BiFunction<javax.net.ssl.SSLSocket, java.util.List<java.lang.String>, java.lang.String> getHandshakeApplicationProtocolSelector();
method public javax.net.ssl.SSLSession getHandshakeSession();
method public abstract boolean getNeedClientAuth();
method public javax.net.ssl.SSLParameters getSSLParameters();
@@ -73897,6 +74021,7 @@
method public abstract void setEnableSessionCreation(boolean);
method public abstract void setEnabledCipherSuites(java.lang.String[]);
method public abstract void setEnabledProtocols(java.lang.String[]);
+ method public void setHandshakeApplicationProtocolSelector(java.util.function.BiFunction<javax.net.ssl.SSLSocket, java.util.List<java.lang.String>, java.lang.String>);
method public abstract void setNeedClientAuth(boolean);
method public void setSSLParameters(javax.net.ssl.SSLParameters);
method public abstract void setUseClientMode(boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index d8da475..237d4c4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -300,8 +300,8 @@
method public static java.lang.String[] getOpStrs();
method public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, java.lang.String, int[]);
method public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOpStrs(java.lang.String[]);
+ method public static int opToDefaultMode(java.lang.String);
method public static java.lang.String opToPermission(java.lang.String);
- method public void resetUidMode(java.lang.String, int, boolean);
method public void setMode(java.lang.String, int, java.lang.String, int);
method public void setUidMode(java.lang.String, int, int);
field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
@@ -1052,6 +1052,7 @@
field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
+ field public static final java.lang.String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
@@ -2719,6 +2720,7 @@
public class LocationManager {
method public deprecated boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method public android.app.PendingIntent createManageLocationPermissionIntent(java.lang.String, java.lang.String);
method public void flushGnssBatch();
method public int getGnssBatchSize();
method public java.lang.String getNetworkProviderPackage();
@@ -3641,9 +3643,12 @@
method public int getWifiApState();
method public boolean isDeviceToApRttSupported();
method public boolean isDeviceToDeviceRttSupported();
+ method public boolean isOweSupported();
method public boolean isPortableHotspotSupported();
method public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
+ method public boolean isWpa3SaeSupported();
+ method public boolean isWpa3SuiteBSupported();
method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method public boolean startScan(android.os.WorkSource);
@@ -3829,6 +3834,14 @@
}
+package android.net.wifi.p2p {
+
+ public class WifiP2pManager {
+ method public void factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ }
+
+}
+
package android.net.wifi.rtt {
public static final class RangingRequest.Builder {
@@ -5557,8 +5570,12 @@
method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
- field public static final android.net.Uri ENHANCED_4G_ENABLED_CONTENT_URI;
+ field public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
+ field public static final android.net.Uri VT_ENABLED_CONTENT_URI;
field public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
+ field public static final android.net.Uri WFC_MODE_CONTENT_URI;
+ field public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
+ field public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
}
public final class SubscriptionPlan implements android.os.Parcelable {
@@ -5917,6 +5934,7 @@
field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+ field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd
field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
field public static final int RESULT_OK = 0; // 0x0
field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
@@ -6041,6 +6059,7 @@
method public void setCallExtra(java.lang.String, java.lang.String);
method public void setCallExtraBoolean(java.lang.String, boolean);
method public void setCallExtraInt(java.lang.String, int);
+ method public void setCallRestrictCause(int);
method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
method public void updateCallType(android.telephony.ims.ImsCallProfile);
method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
diff --git a/api/test-current.txt b/api/test-current.txt
index 604eebd..b2cf4c8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -208,10 +208,12 @@
method public int getActivityType();
method public android.graphics.Rect getAppBounds();
method public android.graphics.Rect getBounds();
+ method public int getRotation();
method public int getWindowingMode();
method public void setActivityType(int);
method public void setAppBounds(android.graphics.Rect);
method public void setBounds(android.graphics.Rect);
+ method public void setRotation(int);
method public void setTo(android.app.WindowConfiguration);
method public void setWindowingMode(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -220,6 +222,7 @@
field public static final int ACTIVITY_TYPE_RECENTS = 3; // 0x3
field public static final int ACTIVITY_TYPE_STANDARD = 1; // 0x1
field public static final int ACTIVITY_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int ROTATION_UNDEFINED = -1; // 0xffffffff
field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5
field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1
field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index fc1a61c..80ed807 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -18,6 +18,7 @@
#include "Log.h"
#include "FieldValue.h"
#include "HashableDimensionKey.h"
+#include "math.h"
namespace android {
namespace os {
@@ -174,6 +175,25 @@
}
}
+bool Value::isZero() const {
+ switch (type) {
+ case INT:
+ return int_value == 0;
+ case LONG:
+ return long_value == 0;
+ case FLOAT:
+ return fabs(float_value) <= std::numeric_limits<float>::epsilon();
+ case DOUBLE:
+ return fabs(double_value) <= std::numeric_limits<double>::epsilon();
+ case STRING:
+ return str_value.size() == 0;
+ case STORAGE:
+ return storage_value.size() == 0;
+ default:
+ return false;
+ }
+}
+
bool Value::operator==(const Value& that) const {
if (type != that.getType()) return false;
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 77163f9..a5d00ac 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -331,6 +331,8 @@
std::string toString() const;
+ bool isZero() const;
+
Type getType() const {
return type;
}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 065f49e..f0f5993 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -272,7 +272,7 @@
}
/*
- * onDumpReport dumps serialized ConfigMetricsReportList into outData.
+ * onDumpReport dumps serialized ConfigMetricsReportList into proto.
*/
void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTimeStampNs,
const bool include_current_partial_bucket,
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index d2919c5..a0d77d6 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -362,11 +362,17 @@
lock_guard<std::mutex> lock(mLock);
auto& pullStats = mPulledAtomStats[pullAtomId];
pullStats.maxPullDelayNs = std::max(pullStats.maxPullDelayNs, pullDelayNs);
- pullStats.avgPullDelayNs = (pullStats.avgPullDelayNs * pullStats.numPullDelay + pullDelayNs) /
- (pullStats.numPullDelay + 1);
+ pullStats.avgPullDelayNs =
+ (pullStats.avgPullDelayNs * pullStats.numPullDelay + pullDelayNs) /
+ (pullStats.numPullDelay + 1);
pullStats.numPullDelay += 1;
}
+void StatsdStats::notePullDataError(int pullAtomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].dataError++;
+}
+
void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
@@ -422,6 +428,7 @@
pullStats.second.avgPullDelayNs = 0;
pullStats.second.maxPullDelayNs = 0;
pullStats.second.numPullDelay = 0;
+ pullStats.second.dataError = 0;
}
}
@@ -530,11 +537,11 @@
dprintf(out,
"Atom %d->(total pull)%ld, (pull from cache)%ld, (min pull interval)%ld, (average "
"pull time nanos)%lld, (max pull time nanos)%lld, (average pull delay nanos)%lld, "
- "(max pull delay nanos)%lld\n",
+ "(max pull delay nanos)%lld, (data error)%ld\n",
(int)pair.first, (long)pair.second.totalPull, (long)pair.second.totalPullFromCache,
(long)pair.second.minPullIntervalSec, (long long)pair.second.avgPullTimeNs,
(long long)pair.second.maxPullTimeNs, (long long)pair.second.avgPullDelayNs,
- (long long)pair.second.maxPullDelayNs);
+ (long long)pair.second.maxPullDelayNs, pair.second.dataError);
}
if (mAnomalyAlarmRegisteredStats > 0) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 777d865..2008abd 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -279,6 +279,11 @@
void notePullFromCache(int pullAtomId);
/*
+ * Notify data error for pulled atom.
+ */
+ void notePullDataError(int pullAtomId);
+
+ /*
* Records time for actual pulling, not including those served from cache and not including
* statsd processing delays.
*/
@@ -329,6 +334,7 @@
int64_t avgPullDelayNs = 0;
int64_t maxPullDelayNs = 0;
long numPullDelay = 0;
+ long dataError = 0;
} PulledAtomStats;
private:
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 6367479..c8b1cf0 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -92,7 +92,9 @@
: StatsdStats::kDimensionKeySizeHardLimit),
mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()),
mAggregationType(metric.aggregation_type()),
- mValueType(metric.aggregation_type() == ValueMetric::AVG ? DOUBLE : LONG) {
+ mUseDiff(metric.has_use_diff() ? metric.use_diff() : (mIsPulled ? true : false)),
+ mValueDirection(metric.value_direction()),
+ mSkipZeroDiffOutput(metric.skip_zero_diff_output()) {
int64_t bucketSizeMills = 0;
if (metric.has_bucket()) {
bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket());
@@ -125,24 +127,25 @@
}
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) ||
- HasPositionALL(metric.dimensions_in_condition());
+ HasPositionALL(metric.dimensions_in_condition());
flushIfNeededLocked(startTimeNs);
- // Kicks off the puller immediately.
+
if (mIsPulled) {
mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
mBucketSizeNs);
}
- // TODO: Only do this for partial buckets like first bucket. All other buckets should use
+ // Only do this for partial buckets like first bucket. All other buckets should use
// flushIfNeeded to adjust start and end to bucket boundaries.
// Adjust start for partial bucket
mCurrentBucketStartTimeNs = startTimeNs;
- if (mIsPulled) {
+ // Kicks off the puller immediately if condition is true and diff based.
+ if (mIsPulled && mCondition && mUseDiff) {
pullLocked(startTimeNs);
}
- VLOG("value metric %lld created. bucket size %lld start_time: %lld",
- (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs);
+ VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
+ (long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
ValueMetricProducer::~ValueMetricProducer() {
@@ -188,14 +191,14 @@
// Fills the dimension path if not slicing by ALL.
if (!mSliceByPositionALL) {
if (!mDimensionsInWhat.empty()) {
- uint64_t dimenPathToken = protoOutput->start(
- FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT);
+ uint64_t dimenPathToken =
+ protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT);
writeDimensionPathToProto(mDimensionsInWhat, protoOutput);
protoOutput->end(dimenPathToken);
}
if (!mDimensionsInCondition.empty()) {
- uint64_t dimenPathToken = protoOutput->start(
- FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION);
+ uint64_t dimenPathToken =
+ protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION);
writeDimensionPathToProto(mDimensionsInCondition, protoOutput);
protoOutput->end(dimenPathToken);
}
@@ -221,15 +224,15 @@
// First fill dimension.
if (mSliceByPositionALL) {
- uint64_t dimensionToken = protoOutput->start(
- FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
+ uint64_t dimensionToken =
+ protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), str_set, protoOutput);
protoOutput->end(dimensionToken);
if (dimensionKey.hasDimensionKeyInCondition()) {
- uint64_t dimensionInConditionToken = protoOutput->start(
- FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
- writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(),
- str_set, protoOutput);
+ uint64_t dimensionInConditionToken =
+ protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
+ writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), str_set,
+ protoOutput);
protoOutput->end(dimensionInConditionToken);
}
} else {
@@ -237,8 +240,8 @@
FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
if (dimensionKey.hasDimensionKeyInCondition()) {
writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInCondition(),
- FIELD_ID_DIMENSION_LEAF_IN_CONDITION,
- str_set, protoOutput);
+ FIELD_ID_DIMENSION_LEAF_IN_CONDITION, str_set,
+ protoOutput);
}
}
@@ -256,15 +259,20 @@
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_NUM,
(long long)(getBucketNumFromEndTimeNs(bucket.mBucketEndNs)));
}
- if (mValueType == LONG) {
+ if (bucket.value.getType() == LONG) {
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_LONG,
- (long long)bucket.mValueLong);
+ (long long)bucket.value.long_value);
+ VLOG("\t bucket [%lld - %lld] count: %lld", (long long)bucket.mBucketStartNs,
+ (long long)bucket.mBucketEndNs, (long long)bucket.value.long_value);
+ } else if (bucket.value.getType() == DOUBLE) {
+ protoOutput->write(FIELD_TYPE_DOUBLE | FIELD_ID_VALUE_DOUBLE,
+ bucket.value.double_value);
+ VLOG("\t bucket [%lld - %lld] count: %.2f", (long long)bucket.mBucketStartNs,
+ (long long)bucket.mBucketEndNs, bucket.value.double_value);
} else {
- protoOutput->write(FIELD_TYPE_DOUBLE | FIELD_ID_VALUE_DOUBLE, bucket.mValueDouble);
+ VLOG("Wrong value type for ValueMetric output: %d", bucket.value.getType());
}
protoOutput->end(bucketInfoToken);
- VLOG("\t bucket [%lld - %lld] count: %lld, %.2f", (long long)bucket.mBucketStartNs,
- (long long)bucket.mBucketEndNs, (long long)bucket.mValueLong, bucket.mValueDouble);
}
protoOutput->end(wrapperToken);
}
@@ -279,8 +287,6 @@
void ValueMetricProducer::onConditionChangedLocked(const bool condition,
const int64_t eventTimeNs) {
- mCondition = condition;
-
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
@@ -289,9 +295,19 @@
flushIfNeededLocked(eventTimeNs);
- if (mIsPulled) {
+ // Pull on condition changes.
+ if (mIsPulled && (mCondition != condition)) {
pullLocked(eventTimeNs);
}
+
+ // when condition change from true to false, clear diff base
+ if (mUseDiff && mCondition && !condition) {
+ for (auto& slice : mCurrentSlicedBucket) {
+ slice.second.hasBase = false;
+ }
+ }
+
+ mCondition = condition;
}
void ValueMetricProducer::pullLocked(const int64_t timestampNs) {
@@ -306,30 +322,33 @@
}
}
+int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
+ return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
+}
+
void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mCondition == true || mConditionTrackerIndex < 0) {
+ if (mCondition) {
if (allData.size() == 0) {
return;
}
// For scheduled pulled data, the effective event time is snap to the nearest
- // bucket boundary to make bucket finalize.
+ // bucket end. In the case of waking up from a deep sleep state, we will
+ // attribute to the previous bucket end. If the sleep was long but not very long, we
+ // will be in the immediate next bucket. Previous bucket may get a larger number as
+ // we pull at a later time than real bucket end.
+ // If the sleep was very long, we skip more than one bucket before sleep. In this case,
+ // if the diff base will be cleared and this new data will serve as new diff base.
int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
- int64_t eventTime = mTimeBaseNs +
- ((realEventTime - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
-
- // close the end of the bucket
- mCondition = false;
- for (const auto& data : allData) {
- data->setElapsedTimestampNs(eventTime - 1);
- onMatchedLogEventLocked(0, *data);
+ int64_t bucketEndTime = calcPreviousBucketEndTime(realEventTime) - 1;
+ if (bucketEndTime < mCurrentBucketStartTimeNs) {
+ VLOG("Skip bucket end pull due to late arrival: %lld vs %lld", (long long)bucketEndTime,
+ (long long)mCurrentBucketStartTimeNs);
+ return;
}
-
- // start a new bucket
- mCondition = true;
for (const auto& data : allData) {
- data->setElapsedTimestampNs(eventTime);
+ data->setElapsedTimestampNs(bucketEndTime);
onMatchedLogEventLocked(0, *data);
}
}
@@ -363,8 +382,8 @@
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
if (newTupleCount > mDimensionHardLimit) {
- ALOGE("ValueMetric %lld dropping data for dimension key %s",
- (long long)mMetricId, newKey.toString().c_str());
+ ALOGE("ValueMetric %lld dropping data for dimension key %s", (long long)mMetricId,
+ newKey.toString().c_str());
return true;
}
}
@@ -393,10 +412,10 @@
return v;
}
-void ValueMetricProducer::onMatchedLogEventInternalLocked(
- const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIndex,
+ const MetricDimensionKey& eventKey,
+ const ConditionKey& conditionKey,
+ bool condition, const LogEvent& event) {
int64_t eventTimeNs = event.GetElapsedTimestampNs();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
@@ -406,6 +425,14 @@
flushIfNeededLocked(eventTimeNs);
+ // For pulled data, we already check condition when we decide to pull or
+ // in onDataPulled. So take all of them.
+ // For pushed data, just check condition.
+ if (!(mIsPulled || condition)) {
+ VLOG("ValueMetric skip event because condition is false");
+ return;
+ }
+
if (hitGuardRailLocked(eventKey)) {
return;
}
@@ -418,71 +445,70 @@
}
Value value = getDoubleOrLong(event.getValues()[mField - 1].mValue);
- Value diff;
- bool hasDiff = false;
- if (mIsPulled) {
- // Always require condition for pulled events. In the case of no condition, only pull
- // on bucket boundaries, in which we fake condition changes.
- if (mCondition == true) {
- if (!interval.startUpdated) {
- interval.start = value;
- interval.startUpdated = true;
- } else {
- // Skip it if there is already value recorded for the start. Happens when puller
- // takes too long to finish. In this case we take the previous value.
- VLOG("Already recorded value for this dimension %s", eventKey.toString().c_str());
- }
- } else {
- // Generally we expect value to be monotonically increasing.
- // If not, take absolute value or drop it, based on config.
- if (interval.startUpdated) {
- if (value >= interval.start) {
- diff = (value - interval.start);
- hasDiff = true;
+ if (mUseDiff) {
+ // no base. just update base and return.
+ if (!interval.hasBase) {
+ interval.base = value;
+ interval.hasBase = true;
+ return;
+ }
+ Value diff;
+ switch (mValueDirection) {
+ case ValueMetric::INCREASING:
+ if (value >= interval.base) {
+ diff = value - interval.base;
+ } else if (mUseAbsoluteValueOnReset) {
+ diff = value;
} else {
- if (mUseAbsoluteValueOnReset) {
- diff = value;
- hasDiff = true;
- } else {
- VLOG("Dropping data for atom %d, prev: %s, now: %s", mPullTagId,
- interval.start.toString().c_str(), value.toString().c_str());
- }
+ VLOG("Unexpected decreasing value");
+ StatsdStats::getInstance().notePullDataError(mPullTagId);
+ interval.base = value;
+ return;
}
- interval.startUpdated = false;
- } else {
- VLOG("No start for matching end %s", value.toString().c_str());
- }
+ break;
+ case ValueMetric::DECREASING:
+ if (interval.base >= value) {
+ diff = interval.base - value;
+ } else if (mUseAbsoluteValueOnReset) {
+ diff = value;
+ } else {
+ VLOG("Unexpected increasing value");
+ StatsdStats::getInstance().notePullDataError(mPullTagId);
+ interval.base = value;
+ return;
+ }
+ break;
+ case ValueMetric::ANY:
+ diff = value - interval.base;
+ break;
+ default:
+ break;
+ }
+ interval.base = value;
+ value = diff;
+ }
+
+ if (interval.hasValue) {
+ switch (mAggregationType) {
+ case ValueMetric::SUM:
+ // for AVG, we add up and take average when flushing the bucket
+ case ValueMetric::AVG:
+ interval.value += value;
+ break;
+ case ValueMetric::MIN:
+ interval.value = std::min(value, interval.value);
+ break;
+ case ValueMetric::MAX:
+ interval.value = std::max(value, interval.value);
+ break;
+ default:
+ break;
}
} else {
- // for pushed events, only aggregate when sliced condition is true
- if (condition == true || mConditionTrackerIndex < 0) {
- diff = value;
- hasDiff = true;
- }
+ interval.value = value;
+ interval.hasValue = true;
}
- if (hasDiff) {
- if (interval.hasValue) {
- switch (mAggregationType) {
- case ValueMetric::SUM:
- // for AVG, we add up and take average when flushing the bucket
- case ValueMetric::AVG:
- interval.value += diff;
- break;
- case ValueMetric::MIN:
- interval.value = diff < interval.value ? diff : interval.value;
- break;
- case ValueMetric::MAX:
- interval.value = diff > interval.value ? diff : interval.value;
- break;
- default:
- break;
- }
- } else {
- interval.value = diff;
- interval.hasValue = true;
- }
- interval.sampleSize += 1;
- }
+ interval.sampleSize += 1;
// TODO: propgate proper values down stream when anomaly support doubles
long wholeBucketVal = interval.value.long_value;
@@ -512,6 +538,10 @@
if (numBucketsForward > 1) {
VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
+ // take base again in future good bucket.
+ for (auto& slice : mCurrentSlicedBucket) {
+ slice.second.hasBase = false;
+ }
}
VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
(long long)mCurrentBucketStartTimeNs);
@@ -534,8 +564,18 @@
// The current bucket is large enough to keep.
for (const auto& slice : mCurrentSlicedBucket) {
if (slice.second.hasValue) {
- info.mValueLong = slice.second.value.long_value;
- info.mValueDouble = (double)slice.second.value.long_value / slice.second.sampleSize;
+ // skip the output if the diff is zero
+ if (mSkipZeroDiffOutput && mUseDiff && slice.second.value.isZero()) {
+ continue;
+ }
+ if (mAggregationType != ValueMetric::AVG) {
+ info.value = slice.second.value;
+ } else {
+ double sum = slice.second.value.type == LONG
+ ? (double)slice.second.value.long_value
+ : slice.second.value.double_value;
+ info.value.setDouble(sum / slice.second.sampleSize);
+ }
// it will auto create new vector of ValuebucketInfo if the key is not found.
auto& bucketList = mPastBuckets[slice.first];
bucketList.push_back(info);
@@ -581,7 +621,10 @@
}
// Reset counters
- mCurrentSlicedBucket.clear();
+ for (auto& slice : mCurrentSlicedBucket) {
+ slice.second.hasValue = false;
+ slice.second.sampleSize = 0;
+ }
}
size_t ValueMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 8db2d95..3416afe 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -34,8 +34,7 @@
struct ValueBucket {
int64_t mBucketStartNs;
int64_t mBucketEndNs;
- int64_t mValueLong;
- double mValueDouble;
+ Value value;
};
class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
@@ -54,35 +53,11 @@
void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version) override {
std::lock_guard<std::mutex> lock(mMutex);
-
- if (mIsPulled && (mCondition == true || mConditionTrackerIndex < 0)) {
- vector<shared_ptr<LogEvent>> allData;
- mPullerManager->Pull(mPullTagId, eventTimeNs, &allData);
- if (allData.size() == 0) {
- // This shouldn't happen since this valuemetric is not useful now.
- }
-
- // Pretend the pulled data occurs right before the app upgrade event.
- mCondition = false;
- for (const auto& data : allData) {
- data->setElapsedTimestampNs(eventTimeNs - 1);
- onMatchedLogEventLocked(0, *data);
- }
-
- flushCurrentBucketLocked(eventTimeNs);
- mCurrentBucketStartTimeNs = eventTimeNs;
-
- mCondition = true;
- for (const auto& data : allData) {
- data->setElapsedTimestampNs(eventTimeNs);
- onMatchedLogEventLocked(0, *data);
- }
- } else {
- // For pushed value metric or pulled metric where condition is not true,
- // we simply flush and reset the current bucket start.
- flushCurrentBucketLocked(eventTimeNs);
- mCurrentBucketStartTimeNs = eventTimeNs;
+ if (mIsPulled && mCondition) {
+ pullLocked(eventTimeNs - 1);
}
+ flushCurrentBucketLocked(eventTimeNs);
+ mCurrentBucketStartTimeNs = eventTimeNs;
};
protected:
@@ -117,6 +92,9 @@
void dropDataLocked(const int64_t dropTimeNs) override;
+ // Calculate previous bucket end time based on current time.
+ int64_t calcPreviousBucketEndTime(const int64_t currentTimeNs);
+
sp<StatsPullerManager> mPullerManager;
const FieldMatcher mValueField;
@@ -131,11 +109,10 @@
// internal state of a bucket.
typedef struct {
- // Pulled data always come in pair of <start, end>. This holds the value
- // for start. The diff (end - start) is taken as the real value.
- Value start;
- // Whether the start data point is updated
- bool startUpdated;
+ // Holds current base value of the dimension. Take diff and update if necessary.
+ Value base;
+ // Whether there is a base to diff to.
+ bool hasBase;
// Current value, depending on the aggregation type.
Value value;
// Number of samples collected.
@@ -172,7 +149,11 @@
const ValueMetric::AggregationType mAggregationType;
- const Type mValueType;
+ const bool mUseDiff;
+
+ const ValueMetric::ValueDirection mValueDirection;
+
+ const bool mSkipZeroDiffOutput;
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
@@ -187,13 +168,13 @@
FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition);
FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition);
FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2);
- FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3);
FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMin);
FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMax);
FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateAvg);
FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSum);
- FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced);
FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
+ FRIEND_TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime);
+ FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput);
};
} // namespace statsd
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 8bfa360..4da3828 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -374,6 +374,7 @@
optional int64 max_pull_time_nanos = 6;
optional int64 average_pull_delay_nanos = 7;
optional int64 max_pull_delay_nanos = 8;
+ optional int64 data_error = 9;
}
repeated PulledAtomStats pulled_atom_stats = 10;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 44fa72e..504c586 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -63,6 +63,7 @@
const int FIELD_ID_MAX_PULL_TIME_NANOS = 6;
const int FIELD_ID_AVERAGE_PULL_DELAY_NANOS = 7;
const int FIELD_ID_MAX_PULL_DELAY_NANOS = 8;
+const int FIELD_ID_DATA_ERROR = 9;
namespace {
@@ -446,6 +447,7 @@
(long long)pair.second.avgPullDelayNs);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_DELAY_NANOS,
(long long)pair.second.maxPullDelayNs);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DATA_ERROR, (long long)pair.second.dataError);
protoOutput->end(token);
}
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index b8f6850..61f31eb 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -21,6 +21,7 @@
#include "HashableDimensionKey.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "guardrail/StatsdStats.h"
+#include "statslog.h"
namespace android {
namespace os {
@@ -87,6 +88,10 @@
// Returns the truncated timestamp.
int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs);
+inline bool isPushedAtom(int atomId) {
+ return atomId <= util::kMaxPushedAtomId && atomId > 1;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index d5f81a59..5c46a29 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -270,6 +270,17 @@
optional int64 min_bucket_size_nanos = 10;
optional bool use_absolute_value_on_reset = 11 [default = false];
+
+ optional bool use_diff = 12;
+
+ enum ValueDirection {
+ INCREASING = 1;
+ DECREASING = 2;
+ ANY = 3;
+ }
+ optional ValueDirection value_direction = 13 [default = INCREASING];
+
+ optional bool skip_zero_diff_output = 14 [default = true];
}
message Alert {
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index fed5a3f..095b401 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -49,6 +49,7 @@
CreateDimensions(android::util::TEMPERATURE, {2/* sensor name field */ });
valueMetric->set_bucket(FIVE_MINUTES);
valueMetric->set_use_absolute_value_on_reset(true);
+ valueMetric->set_skip_zero_diff_output(false);
return config;
}
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 57aab97..ffa07081 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -47,7 +47,35 @@
const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
-const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+double epsilon = 0.001;
+
+/*
+ * Tests that the first bucket works correctly
+ */
+TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+
+ int64_t startTimeBase = 11;
+
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ // statsd started long ago.
+ // The metric starts in the middle of the bucket
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ -1, startTimeBase, 22, pullerManager);
+
+ EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+ EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+ EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
+ valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
+ EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
+ valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
+}
/*
* Tests that the first bucket works correctly
@@ -90,7 +118,7 @@
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
event->write(tagId);
event->write(3);
event->init();
@@ -114,12 +142,11 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // startUpdated:true sum:0 start:11
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(11, curInterval.start.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(8, curInterval.value.long_value);
+ EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -131,12 +158,14 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // tartUpdated:false sum:12
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(23, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(12, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -147,12 +176,14 @@
valueProducer.onDataPulled(allData);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // startUpdated:false sum:12
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(13, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+ EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
/*
@@ -170,7 +201,7 @@
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(true));
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
@@ -188,9 +219,9 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(11, curInterval.start.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
allData.clear();
@@ -203,11 +234,11 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(10, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -218,11 +249,13 @@
valueProducer.onDataPulled(allData);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(26, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+ EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
/*
@@ -257,9 +290,9 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(11, curInterval.start.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
allData.clear();
@@ -272,7 +305,8 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(10, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
@@ -285,11 +319,11 @@
valueProducer.onDataPulled(allData);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(26, curInterval.value.long_value);
+ EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
}
/*
@@ -309,21 +343,10 @@
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
- // should not take effect
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(tagId);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, int64_t timeNs,
- vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
event->write(tagId);
event->write(100);
event->init();
@@ -333,7 +356,7 @@
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
event->write(tagId);
event->write(120);
event->init();
@@ -349,8 +372,8 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
// startUpdated:false sum:0 start:100
- EXPECT_EQ(100, curInterval.start.long_value);
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
@@ -366,20 +389,20 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // startUpdated:false sum:0 start:110
- EXPECT_EQ(110, curInterval.start.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(110, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // startUpdated:false sum:0 start:110
+ EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(false, curInterval.startUpdated);
+ EXPECT_EQ(false, curInterval.hasBase);
}
TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
@@ -401,9 +424,9 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+ valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
event2->write(1);
@@ -411,7 +434,7 @@
event2->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
// Next value should create a new bucket.
shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
@@ -435,11 +458,11 @@
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
- .WillOnce(Return(false))
+ .WillOnce(Return(true))
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
event->write(tagId);
event->write(120);
event->init();
@@ -451,7 +474,7 @@
vector<shared_ptr<LogEvent>> allData;
allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
event->write(tagId);
event->write(100);
event->init();
@@ -460,21 +483,21 @@
valueProducer.onDataPulled(allData);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+ valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
+ EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].value.long_value);
allData.clear();
- event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
event->write(tagId);
event->write(150);
event->init();
allData.push_back(event);
valueProducer.onDataPulled(allData);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValueLong);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].value.long_value);
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
@@ -490,11 +513,10 @@
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
- .WillOnce(Return(false))
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
event->write(tagId);
event->write(100);
event->init();
@@ -504,7 +526,7 @@
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
event->write(tagId);
event->write(120);
event->init();
@@ -523,7 +545,7 @@
EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
- EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
+ EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].value.long_value);
EXPECT_FALSE(valueProducer.mCondition);
}
@@ -565,7 +587,7 @@
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
@@ -587,9 +609,7 @@
event1->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
// has 1 slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
@@ -600,6 +620,7 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
EXPECT_EQ(20, curInterval.value.long_value);
@@ -629,7 +650,7 @@
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
TEST(ValueMetricProducerTest, TestAnomalyDetection) {
@@ -727,7 +748,7 @@
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(true));
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
@@ -747,9 +768,9 @@
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
// startUpdated:true sum:0 start:11
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(11, curInterval.start.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// pull 2 at correct time
@@ -764,11 +785,11 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
// tartUpdated:false sum:12
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(23, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(12, curInterval.value.long_value);
+ EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// pull 3 come late.
// The previous bucket gets closed with error. (Has start value 23, no ending)
@@ -784,12 +805,12 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
// startUpdated:false sum:12
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(36, curInterval.start.long_value);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
/*
@@ -810,12 +831,11 @@
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
- .WillOnce(Return(false))
// condition becomes true
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
event->write(tagId);
event->write(100);
event->init();
@@ -826,7 +846,7 @@
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
event->write(tagId);
event->write(120);
event->init();
@@ -841,17 +861,17 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // startUpdated:false sum:0 start:100
- EXPECT_EQ(100, curInterval.start.long_value);
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// pull on bucket boundary come late, condition change happens before it
valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(false, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// Now the alarm is delivered.
@@ -866,8 +886,9 @@
valueProducer.onDataPulled(allData);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(false, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
}
@@ -889,12 +910,11 @@
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
- .WillOnce(Return(false))
// condition becomes true
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
event->write(tagId);
event->write(100);
event->init();
@@ -905,7 +925,7 @@
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
event->write(tagId);
event->write(120);
event->init();
@@ -916,7 +936,7 @@
.WillOnce(Invoke([](int tagId, int64_t timeNs,
vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
event->write(tagId);
event->write(130);
event->init();
@@ -932,24 +952,26 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
// startUpdated:false sum:0 start:100
- EXPECT_EQ(100, curInterval.start.long_value);
- EXPECT_EQ(true, curInterval.startUpdated);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// pull on bucket boundary come late, condition change happens before it
valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(false, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// condition changed to true again, before the pull alarm is delivered
valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(130, curInterval.start.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(130, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// Now the alarm is delivered, but it is considered late, it has no effect
@@ -963,89 +985,10 @@
valueProducer.onDataPulled(allData);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(130, curInterval.start.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
-}
-
-/*
- * Test pulled event with non sliced condition. The pull on boundary come late because the puller is
- * very slow.
- */
-TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
- .WillOnce(Return(false))
- // condition becomes true
- .WillOnce(Invoke([](int tagId, int64_t timeNs,
- vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }))
- // condition becomes false
- .WillOnce(Invoke([](int tagId, int64_t timeNs,
- vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 20);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- // startUpdated:false sum:0 start:100
- EXPECT_EQ(100, curInterval.start.long_value);
- EXPECT_EQ(true, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
-
- // pull on bucket boundary come late, condition change happens before it.
- // But puller is very slow in this one, so the data come after bucket finish
- valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(false, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
-
- // Alarm is delivered in time, but the pull is very slow, and pullers are called in order,
- // so this one comes even later
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 30);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer.onDataPulled(allData);
-
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(false, curInterval.startUpdated);
- EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(130, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
}
@@ -1088,7 +1031,7 @@
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
@@ -1130,7 +1073,7 @@
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
@@ -1175,7 +1118,7 @@
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(12.5, valueProducer.mPastBuckets.begin()->second.back().mValueDouble);
+ EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().value.double_value - 12.5) < epsilon);
}
TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
@@ -1217,67 +1160,75 @@
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
-TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced) {
- string slicedConditionName = "UID";
- const int conditionTagId = 2;
+TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
ValueMetric metric;
metric.set_id(metricId);
metric.set_bucket(ONE_MINUTE);
metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(1);
- metric.set_aggregation_type(ValueMetric::SUM);
-
- metric.set_condition(StringToId(slicedConditionName));
- MetricConditionLink* link = metric.add_links();
- link->set_condition(StringToId(slicedConditionName));
- buildSimpleAtomFieldMatcher(tagId, 2, link->mutable_fields_in_what());
- buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
-
- LogEvent event1(tagId, bucketStartTimeNs + 10);
- event1.write(10); // value
- event1.write("111"); // uid
- event1.init();
- ConditionKey key1;
- key1[StringToId(slicedConditionName)] =
- {getMockedDimensionKey(conditionTagId, 2, "111")};
-
- LogEvent event2(tagId, bucketStartTimeNs + 20);
- event2.write(15);
- event2.write("222");
- event2.init();
- ConditionKey key2;
- key2[StringToId(slicedConditionName)] =
- {getMockedDimensionKey(conditionTagId, 2, "222")};
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_aggregation_type(ValueMetric::MIN);
+ metric.set_use_diff(true);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
- EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
-
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-
+ shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event1->write(1);
+ event1->write(10);
+ event1->init();
+ shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+ event2->write(1);
+ event2->write(15);
+ event2->init();
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+ // has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(10, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
- EXPECT_EQ(15, curInterval.value.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(5, curInterval.value.long_value);
+
+ // no change in data.
+ shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+ event3->write(1);
+ event3->write(15);
+ event3->init();
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(15, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
+ event4->write(1);
+ event4->write(15);
+ event4->init();
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(15, curInterval.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(15, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+ EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second.back().value.long_value);
}
} // namespace statsd
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index ff436f1..e5764f0 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -24213,7 +24213,90 @@
HSPLandroid/icu/util/CharsTrie;->next(I)Landroid/icu/util/BytesTrie$Result;
HSPLandroid/icu/util/CharsTrie;->nextImpl(II)Landroid/icu/util/BytesTrie$Result;
HSPLandroid/icu/util/CharsTrie;->readValue(Ljava/lang/CharSequence;II)I
-HSPLandroid/icu/util/Currency$1;-><init>()V
+HSPLandroid/icu/util/CodePointTrie$Small8;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small8;
+HSPLandroid/icu/util/CodePointTrie$Small32;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small32;
+HSPLandroid/icu/util/CodePointTrie$Small16;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small16;
+HSPLandroid/icu/util/CodePointTrie$Fast8;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast8;
+HSPLandroid/icu/util/CodePointTrie$Fast8;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast8;->get(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast8;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast32;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast32;
+HSPLandroid/icu/util/CodePointTrie$Fast32;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast32;->get(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast32;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast16;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast16;
+HSPLandroid/icu/util/CodePointTrie$Fast16;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast16;->get(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast16;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Small;->fromBinary(Landroid/icu/util/CodePointTrie$ValueWidth;Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small;
+HSPLandroid/icu/util/CodePointTrie$Small;->cpIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Small;->getType()Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie$Small;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;
+HSPLandroid/icu/util/CodePointTrie$Fast;->fromBinary(Landroid/icu/util/CodePointTrie$ValueWidth;Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast;
+HSPLandroid/icu/util/CodePointTrie$Fast;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast;->cpIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast;->getType()Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie$Fast;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;
+HSPLandroid/icu/util/CodePointTrie$Fast;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Data8;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data8;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data8;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data8;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$Data32;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data32;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data32;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data32;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$Data16;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data16;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data16;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data16;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$Data;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$ValueWidth;->valueOf(Ljava/lang/String;)Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$ValueWidth;->values()[Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Type;->valueOf(Ljava/lang/String;)Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie$Type;->values()[Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie;->fromBinary(Landroid/icu/util/CodePointTrie$Type;Landroid/icu/util/CodePointTrie$ValueWidth;Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie;
+HSPLandroid/icu/util/CodePointTrie;->internalSmallIndex(Landroid/icu/util/CodePointTrie$Type;I)I
+HSPLandroid/icu/util/CodePointTrie;->maybeFilterValue(IIILandroid/icu/util/CodePointMap$ValueFilter;)I
+HSPLandroid/icu/util/CodePointTrie;->asciiGet(I)I
+HSPLandroid/icu/util/CodePointTrie;->cpIndex(I)I
+HSPLandroid/icu/util/CodePointTrie;->fastIndex(I)I
+HSPLandroid/icu/util/CodePointTrie;->get(I)I
+HSPLandroid/icu/util/CodePointTrie;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/CodePointTrie;->getType()Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie;->smallIndex(Landroid/icu/util/CodePointTrie$Type;I)I
+HSPLandroid/icu/util/CodePointTrie;->toBinary(Ljava/io/OutputStream;)I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->getCodePoint()I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->getIndex()I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->getValue()I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->next()Z
+HSPLandroid/icu/util/CodePointMap$StringIterator;->previous()Z
+HSPLandroid/icu/util/CodePointMap$StringIterator;->reset(Ljava/lang/CharSequence;I)V
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->hasNext()Z
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->next()Landroid/icu/util/CodePointMap$Range;
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->next()Ljava/lang/Object;
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->remove()V
+HSPLandroid/icu/util/CodePointMap$Range;->access$000(Landroid/icu/util/CodePointMap$Range;)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$002(Landroid/icu/util/CodePointMap$Range;I)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$100(Landroid/icu/util/CodePointMap$Range;)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$102(Landroid/icu/util/CodePointMap$Range;I)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$202(Landroid/icu/util/CodePointMap$Range;I)I
+HSPLandroid/icu/util/CodePointMap$Range;->getEnd()I
+HSPLandroid/icu/util/CodePointMap$Range;->getStart()I
+HSPLandroid/icu/util/CodePointMap$Range;->getValue()I
+HSPLandroid/icu/util/CodePointMap$Range;->set(III)V
+HSPLandroid/icu/util/CodePointMap$ValueFilter;->apply(I)I
+HSPLandroid/icu/util/CodePointMap$RangeOption;->valueOf(Ljava/lang/String;)Landroid/icu/util/CodePointMap$RangeOption;
+HSPLandroid/icu/util/CodePointMap$RangeOption;->values()[Landroid/icu/util/CodePointMap$RangeOption;
+HSPLandroid/icu/util/CodePointMap;->get(I)I
+HSPLandroid/icu/util/CodePointMap;->getRange(ILandroid/icu/util/CodePointMap$RangeOption;ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/CodePointMap;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/CodePointMap;->iterator()Ljava/util/Iterator;
+HSPLandroid/icu/util/CodePointMap;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;HSPLandroid/icu/util/Currency$1;-><init>()V
HSPLandroid/icu/util/Currency$1;->createInstance(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
HSPLandroid/icu/util/Currency$1;->createInstance(Ljava/lang/String;Ljava/lang/Void;)Landroid/icu/util/Currency;
HSPLandroid/icu/util/Currency$CurrencyUsage;-><init>(Ljava/lang/String;I)V
@@ -24259,6 +24342,61 @@
HSPLandroid/icu/util/MeasureUnit;->equals(Ljava/lang/Object;)Z
HSPLandroid/icu/util/MeasureUnit;->hashCode()I
HSPLandroid/icu/util/MeasureUnit;->internalGetInstance(Ljava/lang/String;Ljava/lang/String;)Landroid/icu/util/MeasureUnit;
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->addEntry([I[CIII)V
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findEntry([III)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findEntry([I[C[I[CII)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->makeHashCode(I)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->makeHashCode([CI)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->makeHashCode([II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->modulo(II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->nextIndex(II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->extend([CIII)V
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->extend([IIII)V
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findAllSameBlock([II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findBlock([C[CI)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findBlock([C[II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findBlock([I[II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->init(II)V
+HSPLandroid/icu/util/MutableCodePointTrie$AllSameBlocks;->add(III)V
+HSPLandroid/icu/util/MutableCodePointTrie$AllSameBlocks;->findMostUsed()I
+HSPLandroid/icu/util/MutableCodePointTrie$AllSameBlocks;->findOrAdd(III)I
+HSPLandroid/icu/util/MutableCodePointTrie;->access$000([II[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->access$100([CI[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->access$200([CI[CII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->access$300([IIII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->allValuesSameAs([IIII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->allocDataBlock(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->build(Landroid/icu/util/CodePointTrie$Type;Landroid/icu/util/CodePointTrie$ValueWidth;)Landroid/icu/util/CodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->clear()V
+HSPLandroid/icu/util/MutableCodePointTrie;->compactData(I[IILandroid/icu/util/MutableCodePointTrie$MixedBlocks;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->compactIndex(ILandroid/icu/util/MutableCodePointTrie$MixedBlocks;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->compactTrie(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->compactWholeDataBlocks(ILandroid/icu/util/MutableCodePointTrie$AllSameBlocks;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->ensureHighStart(I)V
+HSPLandroid/icu/util/MutableCodePointTrie;->equalBlocks([CI[CII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->equalBlocks([CI[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->equalBlocks([II[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->fillBlock(IIII)V
+HSPLandroid/icu/util/MutableCodePointTrie;->findAllSameBlock([IIIII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->findHighStart()I
+HSPLandroid/icu/util/MutableCodePointTrie;->findSameBlock([CII[CII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->fromCodePointMap(Landroid/icu/util/CodePointMap;)Landroid/icu/util/MutableCodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->getAllSameOverlap([IIII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getDataBlock(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getOverlap([CI[CII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getOverlap([CI[III)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getOverlap([II[III)I
+HSPLandroid/icu/util/MutableCodePointTrie;->isStartOfSomeFastBlock(I[II)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->maskValues(I)V
+HSPLandroid/icu/util/MutableCodePointTrie;->maybeFilterValue(IIILandroid/icu/util/CodePointMap$ValueFilter;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->writeBlock(II)V
+HSPLandroid/icu/util/MutableCodePointTrie;->buildImmutable(Landroid/icu/util/CodePointTrie$Type;Landroid/icu/util/CodePointTrie$ValueWidth;)Landroid/icu/util/CodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->clone()Landroid/icu/util/MutableCodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->clone()Ljava/lang/Object;
+HSPLandroid/icu/util/MutableCodePointTrie;->get(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->set(II)V
+HSPLandroid/icu/util/MutableCodePointTrie;->setRange(III)V
HSPLandroid/icu/util/SimpleTimeZone;-><init>(ILjava/lang/String;IIIIIIIIIII)V
HSPLandroid/icu/util/SimpleTimeZone;->clone()Ljava/lang/Object;
HSPLandroid/icu/util/SimpleTimeZone;->cloneAsThawed()Landroid/icu/util/TimeZone;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 43e926f..0997566 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1,4 +1,6 @@
Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accessibilityservice/IAccessibilityServiceConnection;
+Landroid/accounts/AccountManager$AmsTask;-><init>(Landroid/accounts/AccountManager;Landroid/app/Activity;Landroid/os/Handler;Landroid/accounts/AccountManagerCallback;)V
+Landroid/accounts/AccountManager$Future2Task;-><init>(Landroid/accounts/AccountManager;Landroid/os/Handler;Landroid/accounts/AccountManagerCallback;)V
Landroid/accounts/IAccountAuthenticator$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/accounts/IAccountAuthenticator$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Landroid/accounts/IAccountAuthenticator$Stub;-><init>()V
@@ -30,6 +32,7 @@
Landroid/app/ActivityManagerNative;-><init>()V
Landroid/app/ActivityThread$AppBindData;-><init>()V
Landroid/app/ActivityThread$CreateServiceData;-><init>()V
+Landroid/app/ActivityThread$H;-><init>(Landroid/app/ActivityThread;)V
Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager;
Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
@@ -212,6 +215,7 @@
Landroid/app/job/IJobService;->stopJob(Landroid/app/job/JobParameters;)V
Landroid/app/PackageDeleteObserver;-><init>()V
Landroid/app/PackageInstallObserver;-><init>()V
+Landroid/app/ReceiverRestrictedContext;-><init>(Landroid/content/Context;)V
Landroid/app/ResourcesManager$ActivityResources;-><init>()V
Landroid/app/ResourcesManager;-><init>()V
Landroid/app/TaskStackListener;-><init>()V
@@ -262,6 +266,7 @@
Landroid/bluetooth/IBluetoothManagerCallback$Stub;-><init>()V
Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap;
Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V
+Landroid/content/ContentProviderProxy;->mRemote:Landroid/os/IBinder;
Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -415,9 +420,14 @@
Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V
Landroid/content/res/DrawableCache;-><init>()V
Landroid/content/UndoManager;-><init>()V
+Landroid/database/BulkCursorProxy;->mRemote:Landroid/os/IBinder;
Landroid/database/IContentObserver$Stub;-><init>()V
Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
+Landroid/database/sqlite/SQLiteConnectionPool;->$assertionsDisabled:Z
+Landroid/database/sqlite/SQLiteDatabase;->$assertionsDisabled:Z
+Landroid/filterfw/GraphEnvironment;->addReferences([Ljava/lang/Object;)V
+Landroid/hardware/camera2/utils/HashCodeHelpers;->hashCode([I)I
Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
Landroid/hardware/display/IDisplayManager;->getDisplayInfo(I)Landroid/view/DisplayInfo;
Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -431,37 +441,6 @@
Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
-Landroid/icu/impl/CurrencyData;-><init>()V
-Landroid/icu/text/ArabicShaping;-><init>(I)V
-Landroid/icu/text/ArabicShaping;->isAlefMaksouraChar(C)Z
-Landroid/icu/text/ArabicShaping;->isSeenTailFamilyChar(C)I
-Landroid/icu/text/ArabicShaping;->isTailChar(C)Z
-Landroid/icu/text/ArabicShaping;->isYehHamzaChar(C)Z
-Landroid/icu/text/ArabicShaping;->shape(Ljava/lang/String;)Ljava/lang/String;
-Landroid/icu/text/DateFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/DateIntervalFormat;-><init>()V
-Landroid/icu/text/DateTimePatternGenerator$DistanceInfo;-><init>()V
-Landroid/icu/text/DecimalFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/RuleBasedCollator;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/SpoofChecker$ScriptSet;-><init>()V
-Landroid/icu/text/SpoofChecker$ScriptSet;->and(I)V
-Landroid/icu/text/SpoofChecker$ScriptSet;->isFull()Z
-Landroid/icu/text/SpoofChecker$ScriptSet;->setAll()V
-Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames$FactoryImpl;-><init>()V
-Landroid/icu/text/Transliterator;->createFromRules(Ljava/lang/String;Ljava/lang/String;I)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;I)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->transliterate(Landroid/icu/text/Replaceable;Landroid/icu/text/Transliterator$Position;Ljava/lang/String;)V
-Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
-Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/util/PersianCalendar;-><init>(Ljava/util/Locale;)V
-Landroid/icu/util/UResourceBundle;->getBundleInstance(Ljava/lang/String;Landroid/icu/util/ULocale;)Landroid/icu/util/UResourceBundle;
-Landroid/icu/util/UResourceBundle;->getKey()Ljava/lang/String;
-Landroid/icu/util/UResourceBundle;->getString()Ljava/lang/String;
-Landroid/icu/util/UResourceBundle;->getType()I
-Landroid/icu/util/UResourceBundleIterator;->hasNext()Z
-Landroid/icu/util/UResourceBundleIterator;->next()Landroid/icu/util/UResourceBundle;
Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
Landroid/location/ICountryListener$Stub;-><init>()V
Landroid/location/IGeocodeProvider$Stub;-><init>()V
@@ -479,9 +458,11 @@
Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
+Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/LocationManager;Landroid/location/LocationListener;Landroid/os/Looper;)V
Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String;
Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String;
Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
+Landroid/media/effect/SingleFilterEffect;-><init>(Landroid/media/effect/EffectContext;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
Landroid/media/IAudioFocusDispatcher;->dispatchAudioFocusChange(ILjava/lang/String;)V
Landroid/media/IAudioRoutesObserver$Stub;-><init>()V
Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -500,6 +481,7 @@
Landroid/media/IRingtonePlayer;->play(Landroid/os/IBinder;Landroid/net/Uri;Landroid/media/AudioAttributes;FZ)V
Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
Landroid/media/MediaFile;-><init>()V
+Landroid/media/MediaScanner$MyMediaScannerClient;-><init>(Landroid/media/MediaScanner;)V
Landroid/media/projection/IMediaProjectionManager;->hasProjectionPermission(ILjava/lang/String;)Z
Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -547,6 +529,7 @@
Landroid/net/MobileLinkQualityInfo;-><init>()V
Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
Landroid/net/nsd/INsdManager;->getMessenger()Landroid/os/Messenger;
+Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession;
Landroid/net/SntpClient;-><init>()V
Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
@@ -637,6 +620,7 @@
Landroid/os/BatteryStats;->computeBatteryTimeRemaining(J)J
Landroid/os/BatteryStats;->computeBatteryUptime(JI)J
Landroid/os/BatteryStats;->computeChargeTimeRemaining(J)J
+Landroid/os/BatteryStats;->dumpLine(Ljava/io/PrintWriter;ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
Landroid/os/BatteryStats;->getBatteryUptime(J)J
Landroid/os/BatteryStats;->getGlobalWifiRunningTime(JI)J
Landroid/os/BatteryStats;->getMobileRadioActiveTime(JI)J
@@ -725,6 +709,7 @@
Landroid/os/Environment;->buildExternalStorageAppFilesDirs(Ljava/lang/String;)[Ljava/io/File;
Landroid/os/Environment;->buildExternalStorageAppMediaDirs(Ljava/lang/String;)[Ljava/io/File;
Landroid/os/Environment;->buildExternalStorageAppObbDirs(Ljava/lang/String;)[Ljava/io/File;
+Landroid/os/Environment;->buildPaths([Ljava/io/File;[Ljava/lang/String;)[Ljava/io/File;
Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File;
Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File;
Landroid/os/Environment;->initForCurrentUser()V
@@ -930,6 +915,8 @@
Landroid/os/ServiceManager;->sCache:Ljava/util/Map;
Landroid/os/ServiceManager;->sServiceManager:Landroid/os/IServiceManager;
Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/IServiceManager;
+Landroid/os/ServiceManagerProxy;->getService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/ServiceManagerProxy;->mRemote:Landroid/os/IBinder;
Landroid/os/ServiceSpecificException;-><init>(ILjava/lang/String;)V
Landroid/os/SharedMemory;->getFd()I
Landroid/os/ShellCommand;->peekNextArg()Ljava/lang/String;
@@ -1064,6 +1051,7 @@
Landroid/os/WorkSource;->updateLocked(Landroid/os/WorkSource;ZZ)Z
Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/String;)V
Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/Throwable;)V
+Landroid/preference/PreferenceGroupAdapter;->getItem(I)Landroid/preference/Preference;
Landroid/R$styleable;->ActionBar:[I
Landroid/R$styleable;->ActionBar_background:I
Landroid/R$styleable;->ActionBar_backgroundSplit:I
@@ -1337,15 +1325,22 @@
Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->get_pubkey(Ljava/lang/String;)[B
-Landroid/security/IKeystoreService;->import_key(Ljava/lang/String;[BII)I
Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->sign(Ljava/lang/String;[B)[B
Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->verify(Ljava/lang/String;[B[B)I
+Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
+Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
+Landroid/security/keymaster/KeymasterBooleanArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterDateArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterIntArgument;-><init>(II)V
+Landroid/security/keymaster/KeymasterIntArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterIntArgument;->value:I
+Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
+Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterLongArgument;->value:J
Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
@@ -1383,9 +1378,42 @@
Landroid/service/wallpaper/IWallpaperEngine;->setVisibility(Z)V
Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService;
Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
+Landroid/telecom/Log;->i(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
+Landroid/telecom/Log;->w(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
+Landroid/telephony/JapanesePhoneNumberFormatter;->format(Landroid/text/Editable;)V
+Landroid/telephony/SmsCbCmasInfo;->getCategory()I
+Landroid/telephony/SmsCbCmasInfo;->getCertainty()I
+Landroid/telephony/SmsCbCmasInfo;->getMessageClass()I
+Landroid/telephony/SmsCbCmasInfo;->getResponseType()I
+Landroid/telephony/SmsCbCmasInfo;->getSeverity()I
+Landroid/telephony/SmsCbCmasInfo;->getUrgency()I
+Landroid/telephony/SmsCbEtwsInfo;->getWarningType()I
+Landroid/telephony/SmsCbLocation;-><init>(Ljava/lang/String;)V
+Landroid/telephony/SmsCbLocation;-><init>(Ljava/lang/String;II)V
+Landroid/telephony/SmsCbLocation;->getCid()I
+Landroid/telephony/SmsCbLocation;->getLac()I
+Landroid/telephony/SmsCbLocation;->getPlmn()Ljava/lang/String;
+Landroid/telephony/SmsCbMessage;-><init>(Landroid/os/Parcel;)V
+Landroid/telephony/SmsCbMessage;->getCmasWarningInfo()Landroid/telephony/SmsCbCmasInfo;
+Landroid/telephony/SmsCbMessage;->getEtwsWarningInfo()Landroid/telephony/SmsCbEtwsInfo;
+Landroid/telephony/SmsCbMessage;->getGeographicalScope()I
+Landroid/telephony/SmsCbMessage;->getLanguageCode()Ljava/lang/String;
+Landroid/telephony/SmsCbMessage;->getLocation()Landroid/telephony/SmsCbLocation;
+Landroid/telephony/SmsCbMessage;->getMessageBody()Ljava/lang/String;
+Landroid/telephony/SmsCbMessage;->getMessageFormat()I
+Landroid/telephony/SmsCbMessage;->getSerialNumber()I
+Landroid/telephony/SmsCbMessage;->getServiceCategory()I
+Landroid/telephony/SmsCbMessage;->isCmasMessage()Z
+Landroid/telephony/SmsCbMessage;->isEmergencyMessage()Z
Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
+Landroid/test/AndroidTestCase;->getTestContext()Landroid/content/Context;
+Landroid/test/AndroidTestCase;->setTestContext(Landroid/content/Context;)V
+Landroid/test/InstrumentationTestCase;->runMethod(Ljava/lang/reflect/Method;I)V
+Landroid/test/RepetitiveTest;->numIterations()I
Landroid/util/Singleton;-><init>()V
+Landroid/util/XmlPullAttributes;-><init>(Lorg/xmlpull/v1/XmlPullParser;)V
+Landroid/util/XmlPullAttributes;->mParser:Lorg/xmlpull/v1/XmlPullParser;
Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfoResult(Landroid/view/accessibility/AccessibilityNodeInfo;I)V
Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfosResult(Ljava/util/List;I)V
Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setPerformAccessibilityActionResult(ZI)V
@@ -1443,7 +1471,9 @@
Landroid/view/IWindowSession;->setTransparentRegion(Landroid/view/IWindow;Landroid/graphics/Region;)V
Landroid/view/IWindowSession;->wallpaperCommandComplete(Landroid/os/IBinder;Landroid/os/Bundle;)V
Landroid/view/IWindowSession;->wallpaperOffsetsComplete(Landroid/os/IBinder;)V
+Landroid/view/RenderNodeAnimator;->setDuration(J)Landroid/view/RenderNodeAnimator;
Landroid/view/View$AttachInfo$InvalidateInfo;-><init>()V
+Landroid/view/View$CheckForLongPress;-><init>(Landroid/view/View;)V
Landroid/view/View$ListenerInfo;-><init>()V
Landroid/view/ViewTreeObserver$InternalInsetsInfo;-><init>()V
Landroid/webkit/CacheManager$CacheResult;-><init>()V
@@ -1453,9 +1483,102 @@
Landroid/webkit/IWebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
Landroid/webkit/IWebViewUpdateService;->getValidWebViewPackages()[Landroid/webkit/WebViewProviderInfo;
Landroid/webkit/IWebViewUpdateService;->isFallbackPackage(Ljava/lang/String;)Z
+Landroid/widget/DigitalClock$FormatChangeObserver;-><init>(Landroid/widget/DigitalClock;)V
+Landroid/widget/QuickContactBadge$QueryHandler;-><init>(Landroid/widget/QuickContactBadge;Landroid/content/ContentResolver;)V
Landroid/widget/RelativeLayout$DependencyGraph$Node;-><init>()V
Landroid/widget/ScrollBarDrawable;-><init>()V
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->clear()V
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->getRememberedPosition()I
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->inputDigit(C)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->inputDigitAndRememberPosition(C)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder;->getDescriptionForNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Ljava/util/Locale;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder;->getInstance()Lcom/android/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder;
+Lcom/android/i18n/phonenumbers/NumberParseException;->getErrorType()Lcom/android/i18n/phonenumbers/NumberParseException$ErrorType;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getDomesticCarrierCodeFormattingRule()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getFormat()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getLeadingDigitsPattern(I)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getNationalPrefixFormattingRule()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getPattern()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->leadingDigitsPatternSize()I
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getCountryCode()I
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getGeneralDesc()Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneNumberDesc;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getNationalPrefixForParsing()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getNationalPrefixTransformRule()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getPreferredExtnPrefix()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->hasNationalPrefix()Z
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->hasPreferredExtnPrefix()Z
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->intlNumberFormats()Ljava/util/List;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->numberFormats()Ljava/util/List;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadataCollection;-><init>()V
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadataCollection;->getMetadataList()Ljava/util/List;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneNumberDesc;->getNationalNumberPattern()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_DEFAULT_COUNTRY:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_NUMBER_WITHOUT_PLUS_SIGN:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_NUMBER_WITH_IDD:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_NUMBER_WITH_PLUS_SIGN:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->values()[Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->clearCountryCode()Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getCountryCode()I
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getCountryCodeSource()Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getExtension()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getNationalNumber()J
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->hasCountryCode()Z
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->hasExtension()Z
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->end()I
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->number()Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->rawString()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->start()I
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$Leniency;->POSSIBLE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$Leniency;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->EXACT_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->NOT_A_NUMBER:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->NO_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->NSN_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->SHORT_NSN_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->values()[Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->E164:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->INTERNATIONAL:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->NATIONAL:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->RFC3966:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->values()[Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->FIXED_LINE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->FIXED_LINE_OR_MOBILE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->MOBILE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->PAGER:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->PERSONAL_NUMBER:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->PREMIUM_RATE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->SHARED_COST:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->TOLL_FREE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->UAN:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->values()[Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->VOICEMAIL:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->VOIP:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;->IS_POSSIBLE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;->TOO_LONG:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->findNumbers(Ljava/lang/CharSequence;Ljava/lang/String;Lcom/android/i18n/phonenumbers/PhoneNumberUtil$Leniency;J)Ljava/lang/Iterable;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->format(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->formatInOriginalFormat(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getAsYouTypeFormatter(Ljava/lang/String;)Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getCountryCodeForRegion(Ljava/lang/String;)I
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getInstance()Lcom/android/i18n/phonenumbers/PhoneNumberUtil;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getNationalSignificantNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getNumberType(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getRegionCodeForNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isNumberMatch(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isPossibleNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Z
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isPossibleNumberWithReason(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isValidNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Z
+Lcom/android/ims/ImsCall;->deflect(Ljava/lang/String;)V
+Lcom/android/ims/ImsCall;->isMultiparty()Z
+Lcom/android/ims/ImsCall;->reject(I)V
+Lcom/android/ims/ImsCall;->terminate(I)V
Lcom/android/ims/ImsConfigListener$Stub;-><init>()V
+Lcom/android/ims/ImsEcbm;->exitEmergencyCallbackMode()V
+Lcom/android/ims/ImsManager;->getConfigInterface()Lcom/android/ims/ImsConfig;
+Lcom/android/ims/ImsManager;->getInstance(Landroid/content/Context;I)Lcom/android/ims/ImsManager;
+Lcom/android/ims/ImsManager;->isEnhanced4gLteModeSettingEnabledByUser(Landroid/content/Context;)Z
+Lcom/android/ims/ImsManager;->isNonTtyOrTtyOnVolteEnabled(Landroid/content/Context;)Z
+Lcom/android/ims/ImsManager;->isVolteEnabledByPlatform(Landroid/content/Context;)Z
+Lcom/android/ims/ImsUtInterface;->queryCallForward(ILjava/lang/String;Landroid/os/Message;)V
Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V
Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession;
Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V
@@ -1473,7 +1596,15 @@
Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyResponse(ILandroid/telecom/VideoProfile;Landroid/telecom/VideoProfile;)V
Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
Lcom/android/ims/internal/IImsVideoCallProvider;->setCallback(Lcom/android/ims/internal/IImsVideoCallCallback;)V
+Lcom/android/ims/internal/ImsVideoCallProviderWrapper;-><init>(Lcom/android/ims/internal/IImsVideoCallProvider;)V
Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
+Lcom/android/internal/app/AlertActivity;-><init>()V
+Lcom/android/internal/app/AlertActivity;->mAlert:Lcom/android/internal/app/AlertController;
+Lcom/android/internal/app/AlertActivity;->mAlertParams:Lcom/android/internal/app/AlertController$AlertParams;
+Lcom/android/internal/app/AlertActivity;->setupAlert()V
+Lcom/android/internal/app/AssistUtils;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/app/AssistUtils;->getAssistComponentForUser(I)Landroid/content/ComponentName;
+Lcom/android/internal/app/ChooserActivity;-><init>()V
Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
@@ -1508,9 +1639,35 @@
Lcom/android/internal/app/IBatteryStats;->getStatistics()[B
Lcom/android/internal/app/IBatteryStats;->isCharging()Z
Lcom/android/internal/app/IMediaContainerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IMediaContainerService;
+Lcom/android/internal/app/IntentForwarderActivity;->TAG:Ljava/lang/String;
Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
+Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;-><init>(Ljava/util/Locale;Z)V
+Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;->compare(Lcom/android/internal/app/LocaleStore$LocaleInfo;Lcom/android/internal/app/LocaleStore$LocaleInfo;)I
+Lcom/android/internal/app/LocaleHelper;->getDisplayCountry(Ljava/util/Locale;Ljava/util/Locale;)Ljava/lang/String;
+Lcom/android/internal/app/LocaleHelper;->getDisplayName(Ljava/util/Locale;Ljava/util/Locale;Z)Ljava/lang/String;
+Lcom/android/internal/app/LocaleHelper;->normalizeForSearch(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String;
+Lcom/android/internal/app/LocalePicker$LocaleInfo;->getLocale()Ljava/util/Locale;
+Lcom/android/internal/app/LocalePicker;->getLocales()Landroid/os/LocaleList;
+Lcom/android/internal/app/LocalePicker;->updateLocale(Ljava/util/Locale;)V
+Lcom/android/internal/app/LocalePicker;->updateLocales(Landroid/os/LocaleList;)V
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getFullNameInUiLanguage()Ljava/lang/String;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getFullNameNative()Ljava/lang/String;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getId()Ljava/lang/String;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getLocale()Ljava/util/Locale;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getParent()Ljava/util/Locale;
+Lcom/android/internal/app/LocaleStore;->fillCache(Landroid/content/Context;)V
+Lcom/android/internal/app/LocaleStore;->getLevelLocales(Landroid/content/Context;Ljava/util/Set;Lcom/android/internal/app/LocaleStore$LocaleInfo;Z)Ljava/util/Set;
+Lcom/android/internal/app/LocaleStore;->getLocaleInfo(Ljava/util/Locale;)Lcom/android/internal/app/LocaleStore$LocaleInfo;
+Lcom/android/internal/app/NetInitiatedActivity;->handleNIVerify(Landroid/content/Intent;)V
+Lcom/android/internal/app/ResolverActivity;-><init>()V
+Lcom/android/internal/app/ResolverActivity;->mAdapter:Lcom/android/internal/app/ResolverActivity$ResolveListAdapter;
+Lcom/android/internal/app/ResolverActivity;->mPm:Landroid/content/pm/PackageManager;
+Lcom/android/internal/app/ResolverActivity;->onCreate(Landroid/os/Bundle;Landroid/content/Intent;Ljava/lang/CharSequence;[Landroid/content/Intent;Ljava/util/List;Z)V
+Lcom/android/internal/app/WindowDecorActionBar$TabImpl;->mCallback:Landroid/app/ActionBar$TabListener;
+Lcom/android/internal/app/WindowDecorActionBar;->mTabScrollView:Lcom/android/internal/widget/ScrollingTabContainerView;
+Lcom/android/internal/app/WindowDecorActionBar;->setShowHideAnimationEnabled(Z)V
Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I
Lcom/android/internal/appwidget/IAppWidgetService;->bindAppWidgetId(Ljava/lang/String;IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
@@ -1518,17 +1675,80 @@
Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetIds(Landroid/content/ComponentName;)[I
Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetViews(Ljava/lang/String;I)Landroid/widget/RemoteViews;
Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V
+Lcom/android/internal/database/SortCursor;-><init>([Landroid/database/Cursor;Ljava/lang/String;)V
+Lcom/android/internal/database/SortCursor;->mCursor:Landroid/database/Cursor;
+Lcom/android/internal/database/SortCursor;->mCursors:[Landroid/database/Cursor;
+Lcom/android/internal/http/HttpDateTime;->parse(Ljava/lang/String;)J
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;-><init>()V
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorId:Ljava/lang/String;
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorIdEncoding:I
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->text:Ljava/lang/String;
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->textEncoding:I
+Lcom/android/internal/location/GpsNetInitiatedHandler;->decodeString(Ljava/lang/String;ZI)Ljava/lang/String;
+Lcom/android/internal/location/GpsNetInitiatedHandler;->handleNiNotification(Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;)V
+Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z
Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
Lcom/android/internal/logging/MetricsLogger;-><init>()V
Lcom/android/internal/net/LegacyVpnInfo;-><init>()V
Lcom/android/internal/net/VpnConfig;-><init>()V
+Lcom/android/internal/os/AndroidPrintStream;-><init>(ILjava/lang/String;)V
+Lcom/android/internal/os/BaseCommand;-><init>()V
+Lcom/android/internal/os/BaseCommand;->mArgs:Landroid/os/ShellCommand;
Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType;
+Lcom/android/internal/os/BinderInternal;->getContextObject()Landroid/os/IBinder;
+Lcom/android/internal/os/BinderInternal;->handleGc()V
+Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;
Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
Lcom/android/internal/os/IDropBoxManagerService;->getNextEntry(Ljava/lang/String;JLjava/lang/String;)Landroid/os/DropBoxManager$Entry;
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->name:Ljava/lang/String;
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_stime:I
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_uptime:J
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_utime:I
+Lcom/android/internal/os/ProcessCpuTracker;-><init>(Z)V
+Lcom/android/internal/os/ProcessCpuTracker;->countWorkingStats()I
+Lcom/android/internal/os/ProcessCpuTracker;->getWorkingStats(I)Lcom/android/internal/os/ProcessCpuTracker$Stats;
+Lcom/android/internal/os/ProcessCpuTracker;->update()V
+Lcom/android/internal/os/RuntimeInit;->commonInit()V
+Lcom/android/internal/os/RuntimeInit;->getApplicationObject()Landroid/os/IBinder;
+Lcom/android/internal/os/RuntimeInit;->initialized:Z
+Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V
+Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder;
+Lcom/android/internal/os/ZygoteConnection$Arguments;-><init>([Ljava/lang/String;)V
+Lcom/android/internal/os/ZygoteConnection$Arguments;->effectiveCapabilities:J
+Lcom/android/internal/os/ZygoteConnection$Arguments;->gid:I
+Lcom/android/internal/os/ZygoteConnection$Arguments;->gids:[I
+Lcom/android/internal/os/ZygoteConnection$Arguments;->permittedCapabilities:J
+Lcom/android/internal/os/ZygoteConnection$Arguments;->remainingArgs:[Ljava/lang/String;
+Lcom/android/internal/os/ZygoteConnection$Arguments;->rlimits:Ljava/util/ArrayList;
+Lcom/android/internal/os/ZygoteConnection$Arguments;->uid:I
+Lcom/android/internal/os/ZygoteConnection;->applyUidSecurityPolicy(Lcom/android/internal/os/ZygoteConnection$Arguments;Landroid/net/Credentials;)V
+Lcom/android/internal/os/ZygoteConnection;->closeSocket()V
+Lcom/android/internal/os/ZygoteConnection;->getFileDesciptor()Ljava/io/FileDescriptor;
+Lcom/android/internal/os/ZygoteConnection;->intArray2d:[[I
+Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket;
+Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream;
+Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials;
+Lcom/android/internal/os/ZygoteConnection;->readArgumentList()[Ljava/lang/String;
+Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V
+Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources;
+Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/policy/DecorView;->mLastBottomInset:I
+Lcom/android/internal/policy/DecorView;->mLastLeftInset:I
+Lcom/android/internal/policy/DecorView;->mLastRightInset:I
+Lcom/android/internal/policy/DecorView;->mWindow:Lcom/android/internal/policy/PhoneWindow;
Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
Lcom/android/internal/policy/IKeyguardService;->doKeyguardTimeout(Landroid/os/Bundle;)V
Lcom/android/internal/policy/IKeyguardService;->setKeyguardEnabled(Z)V
Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->mContext:Landroid/content/Context;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->mView:Landroid/view/View;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->onKeyDown(ILandroid/view/KeyEvent;)Z
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->onKeyUp(ILandroid/view/KeyEvent;)Z
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->startCallActivity()V
+Lcom/android/internal/policy/PhoneWindow;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/policy/PhoneWindow;->mTitle:Ljava/lang/CharSequence;
+Lcom/android/internal/preference/YesNoPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
Lcom/android/internal/R$anim;->fade_in:I
Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
@@ -1996,9 +2216,961 @@
Lcom/android/internal/statusbar/IStatusBarService;->setIconVisibility(Ljava/lang/String;Z)V
Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
Lcom/android/internal/telecom/ITelecomService;->getCallState()I
+Lcom/android/internal/telephony/BaseCommands;->mCallStateRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mCallWaitingInfoRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mCatCallSetUpRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatCcAlphaRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatEventRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatProCmdRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatSessionEndRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCdmaPrlChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mCdmaSmsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCdmaSubscriptionChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/BaseCommands;->mEmergencyCallbackModeRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mExitEmergencyCallbackModeRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mGsmBroadcastSmsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mGsmSmsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mHardwareConfigChangeRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mIccRefreshRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mIccSmsFullRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mIccStatusChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mImsNetworkStateChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mNITZTimeRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mOtaProvisionRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mPhoneRadioCapabilityChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mPhoneType:I
+Lcom/android/internal/telephony/BaseCommands;->mPreferredNetworkType:I
+Lcom/android/internal/telephony/BaseCommands;->mResendIncallMuteRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mRestrictedStateRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mRilCellInfoListRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mRingbackToneRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mRingRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSignalStrengthRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSmsOnSimRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSmsStatusRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSrvccStateRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mSsnRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mStateMonitor:Ljava/lang/Object;
+Lcom/android/internal/telephony/BaseCommands;->mSubscriptionStatusRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mUnsolOemHookRawRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mUSSDRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mVoiceRadioTechChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/Call$State;->ACTIVE:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->ALERTING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->DIALING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->DISCONNECTED:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->DISCONNECTING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->HOLDING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->IDLE:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->INCOMING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->isAlive()Z
+Lcom/android/internal/telephony/Call$State;->isRinging()Z
+Lcom/android/internal/telephony/Call$State;->values()[Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->WAITING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call;-><init>()V
+Lcom/android/internal/telephony/Call;->getConnections()Ljava/util/List;
+Lcom/android/internal/telephony/Call;->getEarliestConnection()Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/Call;->getLatestConnection()Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/Call;->getPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Call;->getState()Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call;->hangup()V
+Lcom/android/internal/telephony/Call;->isIdle()Z
+Lcom/android/internal/telephony/Call;->isMultiparty()Z
+Lcom/android/internal/telephony/Call;->mConnections:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/Call;->mState:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CallerInfoAsyncQueryHandler;-><init>(Lcom/android/internal/telephony/CallerInfoAsyncQuery;Landroid/content/Context;)V
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CookieWrapper;-><init>()V
+Lcom/android/internal/telephony/CallerInfoAsyncQuery;->release()V
+Lcom/android/internal/telephony/CallForwardInfo;-><init>()V
+Lcom/android/internal/telephony/CallForwardInfo;->number:Ljava/lang/String;
+Lcom/android/internal/telephony/CallForwardInfo;->reason:I
+Lcom/android/internal/telephony/CallForwardInfo;->serviceClass:I
+Lcom/android/internal/telephony/CallForwardInfo;->status:I
+Lcom/android/internal/telephony/CallForwardInfo;->timeSeconds:I
+Lcom/android/internal/telephony/CallForwardInfo;->toa:I
+Lcom/android/internal/telephony/CallManager;->canConference(Lcom/android/internal/telephony/Call;I)Z
+Lcom/android/internal/telephony/CallManager;->canDial(Lcom/android/internal/telephony/Phone;)Z
+Lcom/android/internal/telephony/CallManager;->conference(Lcom/android/internal/telephony/Call;)V
+Lcom/android/internal/telephony/CallManager;->getActiveFgCall(I)Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getActiveFgCallState(I)Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/CallManager;->getBackgroundCalls()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getBgCallConnections()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getBgPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getContext()Landroid/content/Context;
+Lcom/android/internal/telephony/CallManager;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getFgCallConnections()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getFgPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getFgPhone(I)Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveBgCall()Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveBgCall(I)Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveRingingCall()Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveRingingCall(I)Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getInstance()Lcom/android/internal/telephony/CallManager;
+Lcom/android/internal/telephony/CallManager;->getPhoneInCall()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getRingingCalls()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getRingingPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/CallManager;->getState(I)Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/CallManager;->hasActiveBgCall()Z
+Lcom/android/internal/telephony/CallManager;->hasActiveBgCall(I)Z
+Lcom/android/internal/telephony/CallManager;->hasActiveFgCall()Z
+Lcom/android/internal/telephony/CallManager;->hasActiveFgCall(I)Z
+Lcom/android/internal/telephony/CallManager;->hasActiveRingingCall(I)Z
+Lcom/android/internal/telephony/CallManager;->hasMoreThanOneRingingCall()Z
+Lcom/android/internal/telephony/CallManager;->hasMoreThanOneRingingCall(I)Z
+Lcom/android/internal/telephony/CallManager;->mBackgroundCalls:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mEmptyConnections:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mForegroundCalls:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mPhones:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mRingingCalls:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->registerForDisconnect(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CallManager;->registerForNewRingingConnection(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CallManager;->registerForPreciseCallStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CallManager;->registerPhone(Lcom/android/internal/telephony/Phone;)Z
+Lcom/android/internal/telephony/CallManager;->unregisterForDisconnect(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CallManager;->unregisterForNewRingingConnection(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CallManager;->unregisterForPreciseCallStateChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CallManager;->unregisterPhone(Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/CallStateException;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/telephony/CallTracker;-><init>()V
+Lcom/android/internal/telephony/CallTracker;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/CallTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/CallTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/CallTracker;->mNeedsPoll:Z
+Lcom/android/internal/telephony/CallTracker;->mNumberConverted:Z
+Lcom/android/internal/telephony/CallTracker;->mPendingOperations:I
+Lcom/android/internal/telephony/CallTracker;->registerForVoiceCallEnded(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CarrierServiceBindHelper;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/CarrierServiceBindHelper;->mHandler:Landroid/os/Handler;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->CLOSE_CHANNEL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->DISPLAY_TEXT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->fromInt(I)Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_CHANNEL_STATUS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_INKEY:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_INPUT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->LANGUAGE_NOTIFICATION:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->LAUNCH_BROWSER:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->OPEN_CHANNEL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->PLAY_TONE:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->PROVIDE_LOCAL_INFORMATION:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->RECEIVE_DATA:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->REFRESH:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SELECT_ITEM:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_DATA:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_DTMF:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_SMS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_SS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_USSD:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_CALL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_EVENT_LIST:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_IDLE_MODE_TEXT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_MENU:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->values()[Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;->callMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;->confirmMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatCmdMessage$SetupEventListSettings;->eventList:[I
+Lcom/android/internal/telephony/cat/CatCmdMessage;->getCallSettings()Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->getCmdType()Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->geTextMessage()Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->getSetEventList()Lcom/android/internal/telephony/cat/CatCmdMessage$SetupEventListSettings;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->hasIconLoadFailed()Z
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mCallSettings:Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mCmdDet:Lcom/android/internal/telephony/cat/CommandDetails;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mInput:Lcom/android/internal/telephony/cat/Input;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mMenu:Lcom/android/internal/telephony/cat/Menu;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mTextMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatLog;->d(Ljava/lang/Object;Ljava/lang/String;)V
+Lcom/android/internal/telephony/cat/CatLog;->d(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/cat/CatLog;->e(Ljava/lang/Object;Ljava/lang/String;)V
+Lcom/android/internal/telephony/cat/CatResponseMessage;->setEventDownload(I[B)V
+Lcom/android/internal/telephony/cat/CatService;->dispose()V
+Lcom/android/internal/telephony/cat/CatService;->isStkAppInstalled()Z
+Lcom/android/internal/telephony/cat/CatService;->mCmdIf:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/cat/CatService;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/cat/CatService;->mCurrntCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
+Lcom/android/internal/telephony/cat/CatService;->mHandlerThread:Landroid/os/HandlerThread;
+Lcom/android/internal/telephony/cat/CatService;->mMenuCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
+Lcom/android/internal/telephony/cat/CatService;->mMsgDecoder:Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cat/CatService;->mSlotId:I
+Lcom/android/internal/telephony/cat/CatService;->mStkAppInstalled:Z
+Lcom/android/internal/telephony/cat/CatService;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/cat/CatService;->sendTerminalResponse(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/ResultCode;ZILcom/android/internal/telephony/cat/ResponseData;)V
+Lcom/android/internal/telephony/cat/CatService;->sInstance:[Lcom/android/internal/telephony/cat/CatService;
+Lcom/android/internal/telephony/cat/CatService;->sInstanceLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/cat/CommandDetails;->commandNumber:I
+Lcom/android/internal/telephony/cat/CommandDetails;->commandQualifier:I
+Lcom/android/internal/telephony/cat/CommandDetails;->compRequired:Z
+Lcom/android/internal/telephony/cat/CommandDetails;->typeOfCommand:I
+Lcom/android/internal/telephony/cat/CommandParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;)V
+Lcom/android/internal/telephony/cat/CommandParams;->getCommandType()Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/CommandParams;->mCmdDet:Lcom/android/internal/telephony/cat/CommandDetails;
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->dispose()V
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->mIconLoader:Lcom/android/internal/telephony/cat/IconLoader;
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->searchForNextTag(Lcom/android/internal/telephony/cat/ComprehensionTlvTag;Ljava/util/Iterator;)Lcom/android/internal/telephony/cat/ComprehensionTlv;
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->searchForTag(Lcom/android/internal/telephony/cat/ComprehensionTlvTag;Ljava/util/List;)Lcom/android/internal/telephony/cat/ComprehensionTlv;
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getLength()I
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getRawValue()[B
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getTag()I
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getValueIndex()I
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ADDRESS:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ALPHA_ID:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->COMMAND_DETAILS:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->DEVICE_IDENTITIES:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ICON_ID:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->RESULT:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->SMS_TPDU:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->TEXT_ATTRIBUTE:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->TEXT_STRING:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->USSD_STRING:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->value()I
+Lcom/android/internal/telephony/cat/DeviceIdentities;->destinationId:I
+Lcom/android/internal/telephony/cat/DisplayTextParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/TextMessage;)V
+Lcom/android/internal/telephony/cat/DisplayTextParams;->mTextMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/Duration$TimeUnit;->value()I
+Lcom/android/internal/telephony/cat/Duration;->timeInterval:I
+Lcom/android/internal/telephony/cat/Duration;->timeUnit:Lcom/android/internal/telephony/cat/Duration$TimeUnit;
+Lcom/android/internal/telephony/cat/GetInputParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/Input;)V
+Lcom/android/internal/telephony/cat/IconId;->recordNumber:I
+Lcom/android/internal/telephony/cat/IconLoader;->loadIcon(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/cat/Menu;->titleAttrs:Ljava/util/List;
+Lcom/android/internal/telephony/cat/PlayToneParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/TextMessage;Lcom/android/internal/telephony/cat/Tone;Lcom/android/internal/telephony/cat/Duration;Z)V
+Lcom/android/internal/telephony/cat/ResponseData;-><init>()V
+Lcom/android/internal/telephony/cat/ResponseData;->format(Ljava/io/ByteArrayOutputStream;)V
+Lcom/android/internal/telephony/cat/ResultCode;->BACKWARD_MOVE_BY_USER:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->BEYOND_TERMINAL_CAPABILITY:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->BIP_ERROR:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->CMD_DATA_NOT_UNDERSTOOD:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->HELP_INFO_REQUIRED:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->LAUNCH_BROWSER_ERROR:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->NETWORK_CRNTLY_UNABLE_TO_PROCESS:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->NO_RESPONSE_FROM_USER:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->OK:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_ICON_NOT_DISPLAYED:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_LIMITED_SERVICE:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_MODIFIED_BY_NAA:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_NAA_NOT_ACTIVE:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_TONE_NOT_PLAYED:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_ADDITIONAL_EFS_READ:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_MISSING_INFO:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_MODIFICATION:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_PARTIAL_COMPREHENSION:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->REQUIRED_VALUES_MISSING:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->TERMINAL_CRNTLY_UNABLE_TO_PROCESS:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->UICC_SESSION_TERM_BY_USER:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->USER_NOT_ACCEPT:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->USIM_CALL_CONTROL_PERMANENT:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->value()I
+Lcom/android/internal/telephony/cat/ResultCode;->values()[Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultException;-><init>(Lcom/android/internal/telephony/cat/ResultCode;)V
+Lcom/android/internal/telephony/cat/RilMessage;-><init>(ILjava/lang/String;)V
+Lcom/android/internal/telephony/cat/RilMessage;->mData:Ljava/lang/Object;
+Lcom/android/internal/telephony/cat/RilMessage;->mId:I
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->getInstance(Landroid/os/Handler;Lcom/android/internal/telephony/uicc/IccFileHandler;I)Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCmdParamsFactory:Lcom/android/internal/telephony/cat/CommandParamsFactory;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCurrentRilMessage:Lcom/android/internal/telephony/cat/RilMessage;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mInstance:[Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mStateStart:Lcom/android/internal/telephony/cat/RilMessageDecoder$StateStart;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendCmdForExecution(Lcom/android/internal/telephony/cat/RilMessage;)V
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendStartDecodingMessageParams(Lcom/android/internal/telephony/cat/RilMessage;)V
+Lcom/android/internal/telephony/cat/SelectItemParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/Menu;Z)V
+Lcom/android/internal/telephony/cat/TextMessage;-><init>()V
+Lcom/android/internal/telephony/cat/TextMessage;->iconSelfExplanatory:Z
+Lcom/android/internal/telephony/cat/TextMessage;->text:Ljava/lang/String;
+Lcom/android/internal/telephony/cat/ValueObject;-><init>()V
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveAlphaId(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/lang/String;
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveDeviceIdentities(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Lcom/android/internal/telephony/cat/DeviceIdentities;
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveTextAttribute(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/util/List;
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveTextString(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaCallWaitingNotification;->number:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaMmiCode;->makeEmptyNull(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaMmiCode;->mSc:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaSMSDispatcher;->getFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaSMSDispatcher;->handleCdmaStatusReport(Lcom/android/internal/telephony/cdma/SmsMessage;)V
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;->getCdmaSubscriptionSource()I
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;->getInstance(Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;Landroid/os/Handler;ILjava/lang/Object;)Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;
+Lcom/android/internal/telephony/cdma/EriManager$EriDisplayInformation;->mEriIconText:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/EriManager;->getEriDisplayInformation(II)Lcom/android/internal/telephony/cdma/EriManager$EriDisplayInformation;
+Lcom/android/internal/telephony/cdma/sms/BearerData$CodingException;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/BearerData;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/BearerData;->countAsciiSeptets(Ljava/lang/CharSequence;Z)I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->decodeUserDataPayload(Lcom/android/internal/telephony/cdma/sms/UserData;Z)V
+Lcom/android/internal/telephony/cdma/sms/BearerData;->displayMode:I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->encode(Lcom/android/internal/telephony/cdma/sms/BearerData;)[B
+Lcom/android/internal/telephony/cdma/sms/BearerData;->encode7bitAscii(Ljava/lang/String;Z)[B
+Lcom/android/internal/telephony/cdma/sms/BearerData;->getBitsForNumFields(II)I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->hasUserDataHeader:Z
+Lcom/android/internal/telephony/cdma/sms/BearerData;->messageId:I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->msgCenterTimeStamp:Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp;
+Lcom/android/internal/telephony/cdma/sms/BearerData;->priority:I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->priorityIndicatorSet:Z
+Lcom/android/internal/telephony/cdma/sms/BearerData;->userData:Lcom/android/internal/telephony/cdma/sms/UserData;
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->digitMode:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberMode:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberOfDigits:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberPlan:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->parse(Ljava/lang/String;)Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->bearerData:[B
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->serviceCategory:I
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->teleService:I
+Lcom/android/internal/telephony/cdma/sms/UserData;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/UserData;->charToAscii:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/cdma/sms/UserData;->msgEncoding:I
+Lcom/android/internal/telephony/cdma/sms/UserData;->msgEncodingSet:Z
+Lcom/android/internal/telephony/cdma/sms/UserData;->numFields:I
+Lcom/android/internal/telephony/cdma/sms/UserData;->payload:[B
+Lcom/android/internal/telephony/cdma/sms/UserData;->payloadStr:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/sms/UserData;->userDataHeader:Lcom/android/internal/telephony/SmsHeader;
+Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;-><init>()V
+Lcom/android/internal/telephony/cdma/SmsMessage;-><init>()V
+Lcom/android/internal/telephony/cdma/SmsMessage;->calculateLength(Ljava/lang/CharSequence;ZZ)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
+Lcom/android/internal/telephony/cdma/SmsMessage;->createFromEfRecord(I[B)Lcom/android/internal/telephony/cdma/SmsMessage;
+Lcom/android/internal/telephony/cdma/SmsMessage;->createFromPdu([B)Lcom/android/internal/telephony/cdma/SmsMessage;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getIncomingSmsFingerprint()[B
+Lcom/android/internal/telephony/cdma/SmsMessage;->getMessageType()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->getNextMessageId()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->getNumOfVoicemails()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Lcom/android/internal/telephony/cdma/sms/UserData;Z)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Lcom/android/internal/telephony/cdma/sms/UserData;ZI)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;I[BZ)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/android/internal/telephony/SmsHeader;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/android/internal/telephony/SmsHeader;I)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getTeleService()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->isStatusReportMessage()Z
+Lcom/android/internal/telephony/cdma/SmsMessage;->mBearerData:Lcom/android/internal/telephony/cdma/sms/BearerData;
+Lcom/android/internal/telephony/cdma/SmsMessage;->mEnvelope:Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;
+Lcom/android/internal/telephony/cdma/SmsMessage;->parseSms()V
+Lcom/android/internal/telephony/cdma/SmsMessage;->privateGetSubmitPdu(Ljava/lang/String;ZLcom/android/internal/telephony/cdma/sms/UserData;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/CommandException$Error;->GENERIC_FAILURE:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->PASSWORD_INCORRECT:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->RADIO_NOT_AVAILABLE:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->REQUEST_NOT_SUPPORTED:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->SIM_PUK2:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->SMS_FAIL_RETRY:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException;-><init>(Lcom/android/internal/telephony/CommandException$Error;)V
+Lcom/android/internal/telephony/CommandException;->fromRilErrno(I)Lcom/android/internal/telephony/CommandException;
+Lcom/android/internal/telephony/CommandException;->getCommandError()Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException;->mError:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandsInterface;->acceptCall(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->acknowledgeLastIncomingCdmaSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->acknowledgeLastIncomingGsmSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->changeBarringPassword(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->deleteSmsOnRuim(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->deleteSmsOnSim(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->dial(Ljava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->dial(Ljava/lang/String;ILcom/android/internal/telephony/UUSInfo;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->exitEmergencyCallbackMode(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getBasebandVersion(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getCdmaBroadcastConfig(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getCDMASubscription(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getDataCallList(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getIccCardStatus(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getIMEISV(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getIMSI(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getLastDataCallFailCause(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getLastPdpFailCause(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getNetworkSelectionMode(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getOperator(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getPDPContextList(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getPreferredNetworkType(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getSignalStrength(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getSmscAddress(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getVoiceRegistrationState(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->handleCallSetupRequestFromSim(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->iccIO(IILjava/lang/String;IIILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->iccIOForApp(IILjava/lang/String;IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryCallForwardStatus(IILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryCallWaiting(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryFacilityLock(Ljava/lang/String;Ljava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryTTYMode(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForCdmaOtaProvision(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForCellInfoList(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForImsNetworkStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForNotAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForOffOrNotAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForOn(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForRadioStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForRilConnected(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->reportSmsMemoryStatus(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->reportStkServiceIsRunning(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->requestIccSimAuthentication(ILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->requestShutdown(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->sendDtmf(CLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->sendEnvelope(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->sendTerminalResponse(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setCallForward(IIILjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setCallWaiting(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setCdmaBroadcastActivation(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setDataAllowed(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setEmergencyCallbackMode(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setFacilityLock(Ljava/lang/String;ZLjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setNetworkSelectionModeAutomatic(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setNetworkSelectionModeManual(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCallRing(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatCallSetUp(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatCcAlphaNotify(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatEvent(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatProactiveCmd(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatSessionEnd(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnIccSmsFull(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnNewGsmBroadcastSms(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnNITZTime(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSignalStrengthUpdate(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSmsOnSim(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSmsStatus(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSuppServiceNotification(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setPhoneType(I)V
+Lcom/android/internal/telephony/CommandsInterface;->setPreferredNetworkType(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setRadioPower(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setSmscAddress(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setTTYMode(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setUiccSubscription(IIIILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->supplyIccPin(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->switchWaitingOrHoldingAndActive(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForAvailable(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForCdmaOtaProvision(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForOffOrNotAvailable(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForOn(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForRilConnected(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForVoiceRadioTechChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->writeSmsToRuim(ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->writeSmsToSim(ILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/Connection$PostDialState;->CANCELLED:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->COMPLETE:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->NOT_STARTED:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->STARTED:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->WAIT:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->WILD:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection;-><init>(I)V
+Lcom/android/internal/telephony/Connection;->getAddress()Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->getCall()Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/Connection;->getConnectTime()J
+Lcom/android/internal/telephony/Connection;->getCreateTime()J
+Lcom/android/internal/telephony/Connection;->getDisconnectCause()I
+Lcom/android/internal/telephony/Connection;->getDisconnectTime()J
+Lcom/android/internal/telephony/Connection;->getDurationMillis()J
+Lcom/android/internal/telephony/Connection;->getState()Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Connection;->getUserData()Ljava/lang/Object;
+Lcom/android/internal/telephony/Connection;->hangup()V
+Lcom/android/internal/telephony/Connection;->isAlive()Z
+Lcom/android/internal/telephony/Connection;->isIncoming()Z
+Lcom/android/internal/telephony/Connection;->LOG_TAG:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mAddress:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mCnapName:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mCnapNamePresentation:I
+Lcom/android/internal/telephony/Connection;->mDialString:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mDuration:J
+Lcom/android/internal/telephony/Connection;->mIsIncoming:Z
+Lcom/android/internal/telephony/Connection;->mNumberPresentation:I
+Lcom/android/internal/telephony/Connection;->setVideoState(I)V
+Lcom/android/internal/telephony/dataconnection/ApnContext;->getApnType()Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->getReason()Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->getState()Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isConnectable()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isDisconnected()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isEnabled()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isReady()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/ApnContext;->mApnType:Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->mRefCount:I
+Lcom/android/internal/telephony/dataconnection/ApnContext;->mRefCountLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->setState(Lcom/android/internal/telephony/DctConstants$State;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;->mApnContext:Lcom/android/internal/telephony/dataconnection/ApnContext;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->clearSettings()V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->dumpToLog()V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->initConnection(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)Z
+Lcom/android/internal/telephony/dataconnection/DataConnection;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mActivatingState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActivatingState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mActiveState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActiveState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mApnContexts:Ljava/util/HashMap;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mConnectionParams:Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDataRegState:I
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDcFailCause:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDct:Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectingErrorCreatingConnection:Lcom/android/internal/telephony/dataconnection/DataConnection$DcDisconnectionErrorCreatingConnection;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectingState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcDisconnectingState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectParams:Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mId:I
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mInactiveState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcInactiveState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mLinkProperties:Landroid/net/LinkProperties;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mNetworkInfo:Landroid/net/NetworkInfo;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mRilRat:I
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DcFailCause;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfConnected(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfDisconnectDcRetrying(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyConnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;Lcom/android/internal/telephony/dataconnection/DcFailCause;Z)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;Z)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->onConnect(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->tearDownData(Ljava/lang/Object;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->updateTcpBufferSizes(I)V
+Lcom/android/internal/telephony/dataconnection/DcController;->lr(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcController;->mDcListActiveByCid:Ljava/util/HashMap;
+Lcom/android/internal/telephony/dataconnection/DcController;->mDct:Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/dataconnection/DcController;->mDcTesterDeactivateAll:Lcom/android/internal/telephony/dataconnection/DcTesterDeactivateAll;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ACTIVATION_REJECT_GGSN:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ACTIVATION_REJECT_UNSPECIFIED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->APN_TYPE_CONFLICT:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->INSUFFICIENT_RESOURCES:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->MISSING_UNKNOWN_APN:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->NSAPI_IN_USE:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_IPV4_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_IPV6_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_SINGLE_BEARER_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->OPERATOR_BARRED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->PROTOCOL_ERRORS:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_NOT_SUBSCRIBED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_NOT_SUPPORTED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_OUT_OF_ORDER:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->UNKNOWN_PDP_ADDRESS_TYPE:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->USER_AUTHENTICATION:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcTracker$RecoveryAction;->isAggressiveRecovery(I)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cancelReconnectAlarm(Lcom/android/internal/telephony/dataconnection/ApnContext;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(ZLjava/lang/String;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpConnection(ZLcom/android/internal/telephony/dataconnection/ApnContext;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->createAllApnList()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->getActiveApnTypes()[Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->getOverallState()Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->getUiccRecords(I)Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->isConnected()Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->isDisconnected()Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->isOnlySingleDcAllowed(I)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mAllApnSettings:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mApnContexts:Ljava/util/concurrent/ConcurrentHashMap;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mAttached:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mAutoAttachOnCreation:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mDataConnectionTracker:Landroid/os/Handler;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mDisconnectPendingCount:I
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mIsPsRestricted:Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mIsScreenOn:Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mNetStatPollEnabled:Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mNetStatPollPeriod:I
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mPrioritySortedApnContexts:Ljava/util/PriorityQueue;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mProvisioningSpinner:Landroid/app/ProgressDialog;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mState:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyDataConnection(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyOffApnsOfAvailability(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentDataStallAlarm(Landroid/content/Intent;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentProvisioningApnAlarm(Landroid/content/Intent;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onCleanUpAllConnections(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubIdChanged()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->registerForAllDataDisconnected(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->registerSettingsObserver()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->resetPollStats()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->restartDataStallAlarm()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setInitialAttachApn()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setInternalDataEnabled(ZLandroid/os/Message;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setPreferredApn(I)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setRadio(Z)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setupDataOnConnectableApns(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->startDataStallAlarm(Z)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->startNetStatPoll()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->stopDataStallAlarm()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->stopNetStatPoll()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->unregisterForAllDataDisconnected(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->updateRecords()V
+Lcom/android/internal/telephony/DctConstants$Activity;->DATAIN:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->DATAINANDOUT:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->DATAOUT:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->DORMANT:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->values()[Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$State;->CONNECTED:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->CONNECTING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->DISCONNECTING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->FAILED:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->IDLE:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->RETRYING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->SCANNING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->values()[Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DefaultPhoneNotifier;->mRegistry:Lcom/android/internal/telephony/ITelephonyRegistry;
+Lcom/android/internal/telephony/DriverCall$State;->ACTIVE:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->ALERTING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->DIALING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->HOLDING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->INCOMING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->values()[Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->WAITING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall;-><init>()V
+Lcom/android/internal/telephony/DriverCall;->index:I
+Lcom/android/internal/telephony/DriverCall;->isMT:Z
+Lcom/android/internal/telephony/DriverCall;->isVoice:Z
+Lcom/android/internal/telephony/DriverCall;->name:Ljava/lang/String;
+Lcom/android/internal/telephony/DriverCall;->number:Ljava/lang/String;
+Lcom/android/internal/telephony/DriverCall;->numberPresentation:I
+Lcom/android/internal/telephony/DriverCall;->state:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;-><init>(Lcom/android/internal/telephony/gsm/SmsCbHeader;Landroid/telephony/SmsCbLocation;)V
+Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;->matchesLocation(Ljava/lang/String;II)Z
+Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler;->mSmsCbPageMap:Ljava/util/HashMap;
+Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;->acknowledgeLastIncomingSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/gsm/GsmMmiCode;-><init>(Lcom/android/internal/telephony/GsmCdmaPhone;Lcom/android/internal/telephony/uicc/UiccCardApplication;)V
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->getCLIRMode()I
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->getScString()Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isActivate()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isDeactivate()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isErasure()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isInterrogate()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isRegister()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isServiceCodeCallBarring(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isServiceCodeCallForwarding(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isTemporaryModeCLIR()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->makeEmptyNull(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mDialingNumber:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSc:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSia:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSib:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSic:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->newFromDialString(Ljava/lang/String;Lcom/android/internal/telephony/GsmCdmaPhone;Lcom/android/internal/telephony/uicc/UiccCardApplication;)Lcom/android/internal/telephony/gsm/GsmMmiCode;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->processCode()V
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->siToServiceClass(Ljava/lang/String;)I
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->sPatternSuppService:Ljava/util/regex/Pattern;
+Lcom/android/internal/telephony/gsm/GsmSmsAddress;-><init>([BII)V
+Lcom/android/internal/telephony/gsm/GsmSmsAddress;->isCphsVoiceMessageClear()Z
+Lcom/android/internal/telephony/gsm/GsmSmsAddress;->isCphsVoiceMessageSet()Z
+Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->getFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->mGsmInboundSmsHandler:Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;
+Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/gsm/SimTlv;-><init>([BII)V
+Lcom/android/internal/telephony/gsm/SimTlv;->getData()[B
+Lcom/android/internal/telephony/gsm/SimTlv;->getTag()I
+Lcom/android/internal/telephony/gsm/SimTlv;->isValidObject()Z
+Lcom/android/internal/telephony/gsm/SimTlv;->mHasValidTlvObject:Z
+Lcom/android/internal/telephony/gsm/SimTlv;->nextObject()Z
+Lcom/android/internal/telephony/gsm/SmsCbHeader;-><init>([B)V
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getGeographicalScope()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getNumberOfPages()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getPageIndex()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getSerialNumber()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getServiceCategory()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->mMessageIdentifier:I
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;-><init>([B)V
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getByte()I
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getUserData()[B
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getUserDataUCS2(I)Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mCur:I
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mPdu:[B
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mUserDataSeptetPadding:I
+Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;-><init>()V
+Lcom/android/internal/telephony/gsm/SmsMessage;-><init>()V
+Lcom/android/internal/telephony/gsm/SmsMessage;->calculateLength(Ljava/lang/CharSequence;Z)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
+Lcom/android/internal/telephony/gsm/SmsMessage;->createFromEfRecord(I[B)Lcom/android/internal/telephony/gsm/SmsMessage;
+Lcom/android/internal/telephony/gsm/SmsMessage;->createFromPdu([B)Lcom/android/internal/telephony/gsm/SmsMessage;
+Lcom/android/internal/telephony/gsm/SmsMessage;->encodeUCS2(Ljava/lang/String;[B)[B
+Lcom/android/internal/telephony/gsm/SmsMessage;->getStatus()I
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[B)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[BIII)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[BIIII)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPduHead(Ljava/lang/String;Ljava/lang/String;BZLcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;)Ljava/io/ByteArrayOutputStream;
+Lcom/android/internal/telephony/gsm/SmsMessage;->isMWIClearMessage()Z
+Lcom/android/internal/telephony/gsm/SmsMessage;->isMwiDontStore()Z
+Lcom/android/internal/telephony/gsm/SmsMessage;->isMWISetMessage()Z
+Lcom/android/internal/telephony/gsm/SmsMessage;->isStatusReportMessage()Z
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->loadEfFilesFromUsim()Ljava/util/ArrayList;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mPhoneBookRecords:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->reset()V
Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V
+Lcom/android/internal/telephony/GsmCdmaCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->clearDisconnected()V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->dialThreeWay(Ljava/lang/String;)Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->disableDataCallInEmergencyCall(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->fakeHoldForegroundBeforeDial()V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->getPhone()Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->handleEcmTimer(I)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->isPhoneTypeGsm()Z
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mBackgroundCall:Lcom/android/internal/telephony/GsmCdmaCall;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mForegroundCall:Lcom/android/internal/telephony/GsmCdmaCall;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mPendingMO:Lcom/android/internal/telephony/GsmCdmaConnection;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mRingingCall:Lcom/android/internal/telephony/GsmCdmaCall;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mState:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->obtainCompleteMessage()Landroid/os/Message;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->obtainCompleteMessage(I)Landroid/os/Message;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->setMute(Z)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->switchWaitingOrHoldingAndActive()V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->updatePhoneState()V
+Lcom/android/internal/telephony/GsmCdmaConnection$MyHandler;-><init>(Lcom/android/internal/telephony/GsmCdmaConnection;Landroid/os/Looper;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->acquireWakeLock()V
+Lcom/android/internal/telephony/GsmCdmaConnection;->createWakeLock(Landroid/content/Context;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->disconnectCauseFromCode(I)I
+Lcom/android/internal/telephony/GsmCdmaConnection;->fetchDtmfToneDelay(Lcom/android/internal/telephony/GsmCdmaPhone;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->findNextPCharOrNonPOrNonWCharIndex(Ljava/lang/String;I)I
+Lcom/android/internal/telephony/GsmCdmaConnection;->findPOrWCharToAppend(Ljava/lang/String;II)C
+Lcom/android/internal/telephony/GsmCdmaConnection;->formatDialString(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaConnection;->getState()Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/GsmCdmaConnection;->isPause(C)Z
+Lcom/android/internal/telephony/GsmCdmaConnection;->isPhoneTypeGsm()Z
+Lcom/android/internal/telephony/GsmCdmaConnection;->isWait(C)Z
+Lcom/android/internal/telephony/GsmCdmaConnection;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->maskDialString(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaConnection;->mIndex:I
+Lcom/android/internal/telephony/GsmCdmaConnection;->mOwner:Lcom/android/internal/telephony/GsmCdmaCallTracker;
+Lcom/android/internal/telephony/GsmCdmaConnection;->onConnectedInOrOut()V
+Lcom/android/internal/telephony/GsmCdmaConnection;->updateParent(Lcom/android/internal/telephony/GsmCdmaCall;Lcom/android/internal/telephony/GsmCdmaCall;)V
+Lcom/android/internal/telephony/GsmCdmaPhone$Cfu;-><init>(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->exitEmergencyCallbackMode()V
+Lcom/android/internal/telephony/GsmCdmaPhone;->getCallTracker()Lcom/android/internal/telephony/CallTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getCdmaEriText()Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getEsn()Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getLine1Number()Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getPhoneType()I
+Lcom/android/internal/telephony/GsmCdmaPhone;->getServiceState()Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->handleInCallMmiCommands(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isCfEnable(I)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isEriFileLoaded()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isInCall()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isManualSelProhibitedInGlobalMode()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isPhoneTypeGsm()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isValidCommandInterfaceCFAction(I)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isValidCommandInterfaceCFReason(I)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->mCT:Lcom/android/internal/telephony/GsmCdmaCallTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mEcmExitRespRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mEriManager:Lcom/android/internal/telephony/cdma/EriManager;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mIccSmsInterfaceManager:Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mIsimUiccRecords:Lcom/android/internal/telephony/uicc/IsimUiccRecords;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mPendingMMIs:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mSST:Lcom/android/internal/telephony/ServiceStateTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;->notifyPreciseCallStateChanged()V
+Lcom/android/internal/telephony/GsmCdmaPhone;->notifyServiceStateChanged(Landroid/telephony/ServiceState;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->syncClirSetting()V
Lcom/android/internal/telephony/ICarrierConfigLoader;->getConfigForSubId(ILjava/lang/String;)Landroid/os/PersistableBundle;
+Lcom/android/internal/telephony/IccCard;->getState()Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCard;->registerForNetworkLocked(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/IccCard;->supplyNetworkDepersonalization(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/IccCard;->supplyPin(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/IccCard;->supplyPuk(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/IccCardConstants$State;->ABSENT:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->CARD_IO_ERROR:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->NETWORK_LOCKED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->NOT_READY:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->PERM_DISABLED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->PIN_REQUIRED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->PUK_REQUIRED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->READY:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->UNKNOWN:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->values()[Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->checkThread()V
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->DBG:Z
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mBaseHandler:Landroid/os/Handler;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mCurrentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mIs3gCard:Z
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mRecords:Ljava/util/List;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mRecordSize:[I
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mSuccess:Z
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->updateEfForIccType(I)I
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->waitForResult(Ljava/util/concurrent/atomic/AtomicBoolean;)V
+Lcom/android/internal/telephony/IccProvider;-><init>()V
+Lcom/android/internal/telephony/IccProvider;->ADDRESS_BOOK_COLUMN_NAMES:[Ljava/lang/String;
+Lcom/android/internal/telephony/IccProvider;->DBG:Z
+Lcom/android/internal/telephony/IccProvider;->loadRecord(Lcom/android/internal/telephony/uicc/AdnRecord;Landroid/database/MatrixCursor;I)V
+Lcom/android/internal/telephony/IccProvider;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->copyMessageToIccEf(Ljava/lang/String;I[B[B)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->disableCdmaBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->disableGsmBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->enableCdmaBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->enableGsmBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->enforceReceiveAndSend(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->filterDestAddress(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->getAllMessagesFromIccEf(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->getImsSmsFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->getPremiumSmsPermission(Ljava/lang/String;)I
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->injectSmsPdu([BLjava/lang/String;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->isImsSmsSupported()Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mAppOps:Landroid/app/AppOpsManager;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mCellBroadcastRangeManager:Lcom/android/internal/telephony/IccSmsInterfaceManager$CellBroadcastRangeManager;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mHandler:Landroid/os/Handler;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mSms:Ljava/util/List;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mSuccess:Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendData(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendStoredMultipartText(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendStoredText(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->setCdmaBroadcastConfig([Lcom/android/internal/telephony/cdma/CdmaSmsBroadcastConfigInfo;)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->setCellBroadcastConfig([Lcom/android/internal/telephony/gsm/SmsBroadcastConfigInfo;)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->setPremiumSmsPermission(Ljava/lang/String;I)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->updateMessageOnIccEf(Ljava/lang/String;II[B)Z
+Lcom/android/internal/telephony/IIccPhoneBook$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Lcom/android/internal/telephony/IIccPhoneBook$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IIccPhoneBook;
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEf(I)Ljava/util/List;
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEfForSubscriber(II)Ljava/util/List;
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSize(I)[I
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSizeForSubscriber(II)[I
+Lcom/android/internal/telephony/IIccPhoneBook;->updateAdnRecordsInEfBySearch(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
+Lcom/android/internal/telephony/imsphone/ImsExternalCall;-><init>(Lcom/android/internal/telephony/Phone;Lcom/android/internal/telephony/imsphone/ImsExternalConnection;)V
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalCallStateListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalConnectionListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V
+Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->rebuildCapabilities()V
+Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->setActive()V
+Lcom/android/internal/telephony/imsphone/ImsPhone$Cf;-><init>(Ljava/lang/String;ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getActionFromCFAction(I)I
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getBackgroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallForwardingOption(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallWaiting(Landroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getConditionFromCFReason(I)I
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getForegroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getRingingCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getServiceState()Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->handleEnterEmergencyCallbackMode()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->handleExitEmergencyCallbackMode()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->handleInCallMmiCommands(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isCfEnable(I)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isUtEnabled()Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isValidCommandInterfaceCFAction(I)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isValidCommandInterfaceCFReason(I)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isVolteEnabled()Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->mCT:Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->mPendingMMIs:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->mSS:Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyCallForwardingIndicator()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyPreciseCallStateChanged()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyUnknownConnection(Lcom/android/internal/telephony/Connection;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->onMMIDone(Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->sendErrorResponse(Landroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->sendErrorResponse(Landroid/os/Message;Ljava/lang/Throwable;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setCallForwardingOption(IILjava/lang/String;IILandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setCallWaiting(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setImsRegistered(Z)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setServiceState(I)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->attach(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getConnections()Ljava/util/List;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getImsCall()Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->hangup()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->merge(Lcom/android/internal/telephony/imsphone/ImsPhoneCall;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->onHangupLocal()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->addConnection(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->clearDisconnected()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->dial(Ljava/lang/String;ILandroid/os/Bundle;)Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->dialPendingMO()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->findConnection(Lcom/android/ims/ImsCall;)Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getEcbmInterface()Lcom/android/ims/ImsEcbm;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getUtInterface()Lcom/android/ims/ImsUtInterface;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->handleEcmTimer(I)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mAllowEmergencyVideoCalls:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mBackgroundCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mCallExpectedToResume:Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mConnections:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mForegroundCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mHandoverCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsCallListener:Lcom/android/ims/ImsCall$Listener;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsManager:Lcom/android/ims/ImsManager;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mOnHoldToneId:I
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mOnHoldToneStarted:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPendingMO:Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPendingUssd:Landroid/os/Message;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPhone:Lcom/android/internal/telephony/imsphone/ImsPhone;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mRingingCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mSwitchingFgAndBgCalls:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mSyncHold:Ljava/lang/Object;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mUssdSession:Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;I)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;IZ)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->removeConnection(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->setVideoCallProvider(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Lcom/android/ims/ImsCall;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->switchAfterConferenceSuccess()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->updatePhoneState()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection$MyHandler;-><init>(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Landroid/os/Looper;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->acquireWakeLock()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->createWakeLock(Landroid/content/Context;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->getCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->getOwner()Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->isMultiparty()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mDisconnected:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mImsCall:Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mOwner:Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mParent:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->onDisconnect()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->update(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;)Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getCLIRMode()I
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getDialingNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getErrorMessage(Landroid/os/AsyncResult;)Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getScString()Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isActivate()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isDeactivate()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isEmptyOrNull(Ljava/lang/CharSequence;)Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isErasure()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isRegister()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isSupportedOverImsPhone()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isTemporaryModeCLIR()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->mPhone:Lcom/android/internal/telephony/imsphone/ImsPhone;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->newFromDialString(Ljava/lang/String;Lcom/android/internal/telephony/imsphone/ImsPhone;)Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->processCode()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->serviceClassToCFString(I)Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;-><init>(Lcom/android/internal/telephony/InboundSmsHandler;Lcom/android/internal/telephony/InboundSmsTracker;)V
+Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;->mDeleteWhere:Ljava/lang/String;
+Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;->mDeleteWhereArgs:[Ljava/lang/String;
+Lcom/android/internal/telephony/InboundSmsHandler;->acknowledgeLastIncomingSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->deleteFromRawTable(Ljava/lang/String;[Ljava/lang/String;I)V
+Lcom/android/internal/telephony/InboundSmsHandler;->dispatchIntent(Landroid/content/Intent;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/UserHandle;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->dispatchNormalMessage(Lcom/android/internal/telephony/SmsMessageBase;)I
+Lcom/android/internal/telephony/InboundSmsHandler;->getPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/InboundSmsHandler;->handleInjectSms(Landroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->handleNewSms(Landroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->handleSmsWhitelisting(Landroid/content/ComponentName;)Landroid/os/Bundle;
+Lcom/android/internal/telephony/InboundSmsHandler;->isSkipNotifyFlagSet(I)Z
+Lcom/android/internal/telephony/InboundSmsHandler;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->mCellBroadcastHandler:Lcom/android/internal/telephony/CellBroadcastHandler;
+Lcom/android/internal/telephony/InboundSmsHandler;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/InboundSmsHandler;->mDeliveringState:Lcom/android/internal/telephony/InboundSmsHandler$DeliveringState;
+Lcom/android/internal/telephony/InboundSmsHandler;->mDeviceIdleController:Landroid/os/IDeviceIdleController;
+Lcom/android/internal/telephony/InboundSmsHandler;->mIdleState:Lcom/android/internal/telephony/InboundSmsHandler$IdleState;
+Lcom/android/internal/telephony/InboundSmsHandler;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/InboundSmsHandler;->mResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/InboundSmsHandler;->mUserManager:Landroid/os/UserManager;
+Lcom/android/internal/telephony/InboundSmsHandler;->mWaitingState:Lcom/android/internal/telephony/InboundSmsHandler$WaitingState;
+Lcom/android/internal/telephony/InboundSmsHandler;->mWakeLock:Landroid/os/PowerManager$WakeLock;
+Lcom/android/internal/telephony/InboundSmsHandler;->mWapPush:Lcom/android/internal/telephony/WapPushOverSms;
+Lcom/android/internal/telephony/InboundSmsHandler;->processMessagePart(Lcom/android/internal/telephony/InboundSmsTracker;)Z
+Lcom/android/internal/telephony/InboundSmsHandler;->showNewMessageNotification()V
+Lcom/android/internal/telephony/InboundSmsHandler;->writeInboxMessage(Landroid/content/Intent;)Landroid/net/Uri;
+Lcom/android/internal/telephony/InboundSmsTracker;->getFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/InboundSmsTracker;->getIndexOffset()I
+Lcom/android/internal/telephony/IntRangeManager;->mRanges:Ljava/util/ArrayList;
Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener;
Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
@@ -2060,16 +3232,808 @@
Lcom/android/internal/telephony/IWapPushManager;->addPackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
Lcom/android/internal/telephony/IWapPushManager;->deletePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
Lcom/android/internal/telephony/IWapPushManager;->updatePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
+Lcom/android/internal/telephony/MccTable$MccEntry;->mIso:Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->countryCodeForMcc(I)Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->defaultLanguageForMcc(I)Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->defaultTimeZoneForMcc(I)Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->entryForMcc(I)Lcom/android/internal/telephony/MccTable$MccEntry;
+Lcom/android/internal/telephony/MccTable;->getLocaleForLanguageCountry(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
+Lcom/android/internal/telephony/MccTable;->smallestDigitsMccForMnc(I)I
+Lcom/android/internal/telephony/MmiCode$State;->CANCELLED:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode$State;->COMPLETE:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode$State;->FAILED:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode$State;->PENDING:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode;->getPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Phone;->dispose()V
+Lcom/android/internal/telephony/Phone;->exitEmergencyCallbackMode()V
+Lcom/android/internal/telephony/Phone;->getActiveApnTypes()[Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getCallTracker()Lcom/android/internal/telephony/CallTracker;
+Lcom/android/internal/telephony/Phone;->getCellLocation()Landroid/telephony/CellLocation;
+Lcom/android/internal/telephony/Phone;->getContext()Landroid/content/Context;
+Lcom/android/internal/telephony/Phone;->getDataConnectionState()Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/Phone;->getIccCard()Lcom/android/internal/telephony/IccCard;
+Lcom/android/internal/telephony/Phone;->getIccFileHandler()Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/Phone;->getIccSerialNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getIccSmsInterfaceManager()Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/Phone;->getImsPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Phone;->getIsimRecords()Lcom/android/internal/telephony/uicc/IsimRecords;
+Lcom/android/internal/telephony/Phone;->getMsisdn()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getNai()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getPhoneId()I
+Lcom/android/internal/telephony/Phone;->getPhoneName()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getPhoneType()I
+Lcom/android/internal/telephony/Phone;->getServiceStateTracker()Lcom/android/internal/telephony/ServiceStateTracker;
+Lcom/android/internal/telephony/Phone;->getSmscAddress(Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/Phone;->getSubId()I
+Lcom/android/internal/telephony/Phone;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getUiccCard()Lcom/android/internal/telephony/uicc/UiccCard;
+Lcom/android/internal/telephony/Phone;->getVideoState(Lcom/android/internal/telephony/Call;)I
+Lcom/android/internal/telephony/Phone;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->invokeOemRilRequestStrings([Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->isCspPlmnEnabled()Z
+Lcom/android/internal/telephony/Phone;->isUtEnabled()Z
+Lcom/android/internal/telephony/Phone;->isVideoEnabled()Z
+Lcom/android/internal/telephony/Phone;->isVolteEnabled()Z
+Lcom/android/internal/telephony/Phone;->isWifiCallingEnabled()Z
+Lcom/android/internal/telephony/Phone;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/Phone;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/Phone;->mDcTracker:Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/Phone;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference;
+Lcom/android/internal/telephony/Phone;->mImsPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Phone;->mMmiRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/Phone;->mNotifier:Lcom/android/internal/telephony/PhoneNotifier;
+Lcom/android/internal/telephony/Phone;->mPhoneId:I
+Lcom/android/internal/telephony/Phone;->mSmsStorageMonitor:Lcom/android/internal/telephony/SmsStorageMonitor;
+Lcom/android/internal/telephony/Phone;->mUiccApplication:Ljava/util/concurrent/atomic/AtomicReference;
+Lcom/android/internal/telephony/Phone;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/Phone;->needsOtaServiceProvisioning()Z
+Lcom/android/internal/telephony/Phone;->notifyOtaspChanged(I)V
+Lcom/android/internal/telephony/Phone;->registerForDisconnect(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForEcmTimerReset(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForIncomingRing(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForMmiComplete(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForMmiInitiate(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForNewRingingConnection(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForPreciseCallStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForRingbackTone(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForServiceStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForSimRecordsLoaded(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForUnknownConnection(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->selectNetworkManually(Lcom/android/internal/telephony/OperatorInfo;ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->setNetworkSelectionModeAutomatic(Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->setOnPostDialCharacter(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->setPreferredNetworkType(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->setSmscAddress(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->unregisterForDisconnect(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForEcmTimerReset(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForIncomingRing(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForMmiComplete(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForMmiInitiate(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForNewRingingConnection(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForPreciseCallStateChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForRingbackTone(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForServiceStateChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForSimRecordsLoaded(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForUnknownConnection(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unsetOnEcbModeExitResponse(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTING:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->DISCONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->SUSPENDED:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->values()[Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$State;->IDLE:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants$State;->OFFHOOK:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants$State;->RINGING:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants$State;->values()[Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_ALLOWED:I
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_PAYPHONE:I
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_RESTRICTED:I
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_UNKNOWN:I
+Lcom/android/internal/telephony/PhoneFactory;->calculatePreferredNetworkType(Landroid/content/Context;I)I
+Lcom/android/internal/telephony/PhoneFactory;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneFactory;->getDefaultSubscription()I
+Lcom/android/internal/telephony/PhoneFactory;->getPhone(I)Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneFactory;->getPhones()[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneFactory;->makeDefaultPhone(Landroid/content/Context;)V
+Lcom/android/internal/telephony/PhoneFactory;->sCommandsInterface:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/PhoneFactory;->sContext:Landroid/content/Context;
+Lcom/android/internal/telephony/PhoneFactory;->sMadeDefaults:Z
+Lcom/android/internal/telephony/PhoneFactory;->sPhoneNotifier:Lcom/android/internal/telephony/PhoneNotifier;
+Lcom/android/internal/telephony/PhoneInternalInterface$DataActivityState;->NONE:Lcom/android/internal/telephony/PhoneInternalInterface$DataActivityState;
+Lcom/android/internal/telephony/PhoneInternalInterface;->PREFERRED_NT_MODE:I
+Lcom/android/internal/telephony/PhoneNotifier;->notifyMessageWaitingChanged(Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/PhoneNotifier;->notifySignalStrength(Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->getSignalStrengthDbm()I
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->mSignalStrength:Landroid/telephony/SignalStrength;
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->mWants:I
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->notifyServiceState(I)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->notifySignalStrength(I)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->registerIntent()V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->unregisterIntent()V
+Lcom/android/internal/telephony/PhoneSubInfoController;->getDefaultSubscription()I
+Lcom/android/internal/telephony/PhoneSubInfoController;->getPhone(I)Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneSubInfoController;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/PhoneSubInfoController;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/PhoneSubInfoController;->mPhone:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneSwitcher;->activate(I)V
+Lcom/android/internal/telephony/PhoneSwitcher;->deactivate(I)V
+Lcom/android/internal/telephony/PhoneSwitcher;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/PhoneSwitcher;->mMaxActivePhones:I
+Lcom/android/internal/telephony/PhoneSwitcher;->mNumPhones:I
+Lcom/android/internal/telephony/PhoneSwitcher;->mPhones:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/ProxyController;->completeRadioCapabilityTransaction()V
+Lcom/android/internal/telephony/ProxyController;->getInstance()Lcom/android/internal/telephony/ProxyController;
+Lcom/android/internal/telephony/ProxyController;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ProxyController;->mOldRadioAccessFamily:[I
+Lcom/android/internal/telephony/ProxyController;->mRadioCapabilitySessionId:I
+Lcom/android/internal/telephony/ProxyController;->mSetRadioAccessFamilyStatus:[I
+Lcom/android/internal/telephony/ProxyController;->mUniqueIdGenerator:Ljava/util/concurrent/atomic/AtomicInteger;
+Lcom/android/internal/telephony/ProxyController;->registerForAllDataDisconnected(ILandroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/ProxyController;->sendRadioCapabilityRequest(IIIILjava/lang/String;II)V
+Lcom/android/internal/telephony/ProxyController;->sProxyController:Lcom/android/internal/telephony/ProxyController;
+Lcom/android/internal/telephony/RadioCapability;->getRadioAccessFamily()I
+Lcom/android/internal/telephony/RetryManager;->configure(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/RetryManager;->getRetryTimer()I
+Lcom/android/internal/telephony/RetryManager;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/RetryManager;->mApnType:Ljava/lang/String;
+Lcom/android/internal/telephony/RetryManager;->mFailFastInterApnDelay:J
+Lcom/android/internal/telephony/RetryManager;->mInterApnDelay:J
+Lcom/android/internal/telephony/RetryManager;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/RIL;-><init>(Landroid/content/Context;II)V
+Lcom/android/internal/telephony/RIL;-><init>(Landroid/content/Context;IILjava/lang/Integer;)V
+Lcom/android/internal/telephony/RIL;->acquireWakeLock(Lcom/android/internal/telephony/RILRequest;I)V
+Lcom/android/internal/telephony/RIL;->clearRequestList(IZ)V
+Lcom/android/internal/telephony/RIL;->clearWakeLock(I)Z
+Lcom/android/internal/telephony/RIL;->decrementWakeLock(Lcom/android/internal/telephony/RILRequest;)V
+Lcom/android/internal/telephony/RIL;->findAndRemoveRequestFromList(I)Lcom/android/internal/telephony/RILRequest;
+Lcom/android/internal/telephony/RIL;->getResponseForTimedOutRILRequest(Lcom/android/internal/telephony/RILRequest;)Ljava/lang/Object;
+Lcom/android/internal/telephony/RIL;->hangupForegroundResumeBackground(Landroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->hangupWaitingOrBackground(Landroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->makeStaticRadioCapability()Lcom/android/internal/telephony/RadioCapability;
+Lcom/android/internal/telephony/RIL;->mRequestList:Landroid/util/SparseArray;
+Lcom/android/internal/telephony/RIL;->mTestingEmergencyCall:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/RIL;->mWakeLock:Landroid/os/PowerManager$WakeLock;
+Lcom/android/internal/telephony/RIL;->notifyRegistrantsCdmaInfoRec(Lcom/android/internal/telephony/cdma/CdmaInformationRecords;)V
+Lcom/android/internal/telephony/RIL;->notifyRegistrantsRilConnectionChanged(I)V
+Lcom/android/internal/telephony/RIL;->requestToString(I)Ljava/lang/String;
+Lcom/android/internal/telephony/RIL;->responseToString(I)Ljava/lang/String;
+Lcom/android/internal/telephony/RIL;->retToString(ILjava/lang/Object;)Ljava/lang/String;
+Lcom/android/internal/telephony/RIL;->riljLog(Ljava/lang/String;)V
+Lcom/android/internal/telephony/RIL;->setRadioPower(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->unsljLog(I)V
+Lcom/android/internal/telephony/RIL;->unsljLogMore(ILjava/lang/String;)V
+Lcom/android/internal/telephony/RIL;->unsljLogRet(ILjava/lang/Object;)V
+Lcom/android/internal/telephony/RIL;->unsljLogvRet(ILjava/lang/Object;)V
+Lcom/android/internal/telephony/RILConstants;->PREFERRED_NETWORK_MODE:I
+Lcom/android/internal/telephony/RILRequest;->mRequest:I
+Lcom/android/internal/telephony/RILRequest;->mResult:Landroid/os/Message;
+Lcom/android/internal/telephony/RILRequest;->mSerial:I
+Lcom/android/internal/telephony/RILRequest;->obtain(ILandroid/os/Message;)Lcom/android/internal/telephony/RILRequest;
+Lcom/android/internal/telephony/RILRequest;->onError(ILjava/lang/Object;)V
+Lcom/android/internal/telephony/RILRequest;->release()V
+Lcom/android/internal/telephony/RILRequest;->serialString()Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->fixUnknownMcc(Ljava/lang/String;I)Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->getCurrentDataConnectionState()I
+Lcom/android/internal/telephony/ServiceStateTracker;->getDesiredPowerState()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->getPhoneId()I
+Lcom/android/internal/telephony/ServiceStateTracker;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->isConcurrentVoiceAndDataAllowed()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isGprsConsistent(II)Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isImsRegistered()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isInHomeSidNid(II)Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isInvalidOperatorNumeric(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/ServiceStateTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->mAttachedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCr:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurDataSpn:Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurPlmn:Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurShowPlmn:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurShowSpn:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurSpn:Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOffRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOnRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDefaultRoamingIndicator:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mDesiredPowerState:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mDetachedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDeviceShuttingDown:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mEmergencyOnly:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/ServiceStateTracker;->mIntentReceiver:Landroid/content/BroadcastReceiver;
+Lcom/android/internal/telephony/ServiceStateTracker;->mIsSubscriptionFromRuim:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mMaxDataCalls:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mNetworkAttachedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mNewMaxDataCalls:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mNewReasonDataDenied:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mNewSS:Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/ServiceStateTracker;->mOnSubscriptionsChangedListener:Lcom/android/internal/telephony/ServiceStateTracker$SstSubscriptionsChangedListener;
+Lcom/android/internal/telephony/ServiceStateTracker;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/ServiceStateTracker;->mPreferredNetworkType:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mReasonDataDenied:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mReportedGprsNoReg:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mRoamingIndicator:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mSignalStrength:Landroid/telephony/SignalStrength;
+Lcom/android/internal/telephony/ServiceStateTracker;->mSpnUpdatePending:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mSS:Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/ServiceStateTracker;->mStartedGprsRegCheck:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mSubId:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mSubscriptionController:Lcom/android/internal/telephony/SubscriptionController;
+Lcom/android/internal/telephony/ServiceStateTracker;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
+Lcom/android/internal/telephony/ServiceStateTracker;->mUiccApplcation:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/ServiceStateTracker;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOffRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOnRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->notifyDataRegStateRilRadioTechnologyChanged()V
+Lcom/android/internal/telephony/ServiceStateTracker;->notifySignalStrength()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->pollState()V
+Lcom/android/internal/telephony/ServiceStateTracker;->powerOffRadioSafely(Lcom/android/internal/telephony/dataconnection/DcTracker;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->reRegisterNetwork(Landroid/os/Message;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->resetServiceStateInIwlanMode()V
+Lcom/android/internal/telephony/ServiceStateTracker;->setOperatorIdd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->setRoamingType(Landroid/telephony/ServiceState;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->setSignalStrengthDefaultValues()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updateOtaspState()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updatePhoneObject()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updateRoamingState()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updateSpnDisplay()V
+Lcom/android/internal/telephony/ServiceStateTracker;->useDataRegStateForDataOnlyDevices()V
+Lcom/android/internal/telephony/sip/SipPhone$SipCall;->hold()V
+Lcom/android/internal/telephony/sip/SipPhone$SipCall;->switchWith(Lcom/android/internal/telephony/sip/SipPhone$SipCall;)V
+Lcom/android/internal/telephony/sip/SipPhone$SipCall;->unhold()V
+Lcom/android/internal/telephony/sip/SipPhone;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/sip/SipPhone;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/sip/SipPhone;->mBackgroundCall:Lcom/android/internal/telephony/sip/SipPhone$SipCall;
+Lcom/android/internal/telephony/sip/SipPhone;->mForegroundCall:Lcom/android/internal/telephony/sip/SipPhone$SipCall;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->DBG:Z
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCDMA:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCommon:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableGSM:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->translate(Ljava/lang/CharSequence;)Ljava/lang/String;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->useCdmaFormatForMoSms()Z
+Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;->mApplicationName:Ljava/lang/String;
+Lcom/android/internal/telephony/SmsApplication;->configurePreferredActivity(Landroid/content/pm/PackageManager;Landroid/content/ComponentName;I)V
+Lcom/android/internal/telephony/SmsApplication;->getApplicationCollection(Landroid/content/Context;)Ljava/util/Collection;
+Lcom/android/internal/telephony/SmsApplication;->getDefaultMmsApplication(Landroid/content/Context;Z)Landroid/content/ComponentName;
+Lcom/android/internal/telephony/SmsApplication;->getDefaultRespondViaMessageApplication(Landroid/content/Context;Z)Landroid/content/ComponentName;
+Lcom/android/internal/telephony/SmsApplication;->getDefaultSmsApplication(Landroid/content/Context;Z)Landroid/content/ComponentName;
+Lcom/android/internal/telephony/SmsApplication;->getSmsApplicationData(Ljava/lang/String;Landroid/content/Context;)Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;
+Lcom/android/internal/telephony/SmsApplication;->isDefaultSmsApplication(Landroid/content/Context;Ljava/lang/String;)Z
+Lcom/android/internal/telephony/SmsApplication;->setDefaultApplication(Ljava/lang/String;Landroid/content/Context;)V
+Lcom/android/internal/telephony/SmsApplication;->shouldWriteMessageForPackage(Ljava/lang/String;Landroid/content/Context;)Z
+Lcom/android/internal/telephony/SmsBroadcastUndelivered;-><init>(Landroid/content/Context;Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler;)V
+Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mNegativeButton:Landroid/widget/Button;
+Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mPositiveButton:Landroid/widget/Button;
+Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mRememberUndoInstruction:Landroid/widget/TextView;
+Lcom/android/internal/telephony/SMSDispatcher$DataSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Ljava/util/ArrayList;[Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;->sendSmsByCarrierApp(Ljava/lang/String;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;)V
+Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsSender;)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->isMultipart()Z
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mAppInfo:Landroid/content/pm/PackageInfo;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mData:Ljava/util/HashMap;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mDeliveryIntent:Landroid/app/PendingIntent;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mDestAddress:Ljava/lang/String;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mMessageRef:I
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mMessageUri:Landroid/net/Uri;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mPersistMessage:Z
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mSentIntent:Landroid/app/PendingIntent;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mTimestamp:J
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->onFailed(Landroid/content/Context;II)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->onSent(Landroid/content/Context;)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->updateSentMessageStatus(Landroid/content/Context;I)V
+Lcom/android/internal/telephony/SMSDispatcher$TextSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->calculateLength(Ljava/lang/CharSequence;Z)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
+Lcom/android/internal/telephony/SMSDispatcher;->checkCallerIsPhoneOrCarrierApp()V
+Lcom/android/internal/telephony/SMSDispatcher;->deliveryPendingList:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/SMSDispatcher;->dispose()V
+Lcom/android/internal/telephony/SMSDispatcher;->getCarrierAppPackageName()Ljava/lang/String;
+Lcom/android/internal/telephony/SMSDispatcher;->getMultipartMessageText(Ljava/util/ArrayList;)Ljava/lang/String;
+Lcom/android/internal/telephony/SMSDispatcher;->getNextConcatenatedRef()I
+Lcom/android/internal/telephony/SMSDispatcher;->getSubId()I
+Lcom/android/internal/telephony/SMSDispatcher;->handleConfirmShortCode(ZLcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/SMSDispatcher;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/SMSDispatcher;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/SMSDispatcher;->mResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/SMSDispatcher;->mTelephonyManager:Landroid/telephony/TelephonyManager;
+Lcom/android/internal/telephony/SMSDispatcher;->processSendSmsResponse(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;II)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendData(Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendMultipartSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendSubmitPdu(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V
Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V
Lcom/android/internal/telephony/SmsMessageBase;-><init>()V
+Lcom/android/internal/telephony/SmsResponse;-><init>(ILjava/lang/String;I)V
+Lcom/android/internal/telephony/SmsResponse;->mAckPdu:Ljava/lang/String;
+Lcom/android/internal/telephony/SmsResponse;->mErrorCode:I
+Lcom/android/internal/telephony/SmsResponse;->mMessageRef:I
+Lcom/android/internal/telephony/SmsStorageMonitor;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/SmsUsageMonitor;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/telephony/SmsUsageMonitor;->check(Ljava/lang/String;I)Z
+Lcom/android/internal/telephony/SubscriptionController;->broadcastDefaultDataSubIdChanged(I)V
+Lcom/android/internal/telephony/SubscriptionController;->colorArr:[I
+Lcom/android/internal/telephony/SubscriptionController;->enforceModifyPhoneState(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->getActiveSubInfoCount(Ljava/lang/String;)I
+Lcom/android/internal/telephony/SubscriptionController;->getActiveSubscriptionInfo(ILjava/lang/String;)Landroid/telephony/SubscriptionInfo;
+Lcom/android/internal/telephony/SubscriptionController;->getActiveSubscriptionInfoList(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultDataSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultSmsSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultVoiceSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDummySubIds(I)[I
+Lcom/android/internal/telephony/SubscriptionController;->getInstance()Lcom/android/internal/telephony/SubscriptionController;
+Lcom/android/internal/telephony/SubscriptionController;->getPhoneId(I)I
+Lcom/android/internal/telephony/SubscriptionController;->getSubId(I)[I
+Lcom/android/internal/telephony/SubscriptionController;->getSubIdUsingPhoneId(I)I
+Lcom/android/internal/telephony/SubscriptionController;->getSubInfo(Ljava/lang/String;Ljava/lang/Object;)Ljava/util/List;
+Lcom/android/internal/telephony/SubscriptionController;->getSubInfoRecord(Landroid/database/Cursor;)Landroid/telephony/SubscriptionInfo;
+Lcom/android/internal/telephony/SubscriptionController;->isActiveSubId(I)Z
+Lcom/android/internal/telephony/SubscriptionController;->isSubInfoReady()Z
+Lcom/android/internal/telephony/SubscriptionController;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->logdl(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/SubscriptionController;->mDefaultPhoneId:I
+Lcom/android/internal/telephony/SubscriptionController;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/SubscriptionController;->notifySubscriptionInfoChanged()V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultDataSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultFallbackSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultSmsSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultVoiceSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setPlmnSpn(IZLjava/lang/String;ZLjava/lang/String;)Z
+Lcom/android/internal/telephony/SubscriptionController;->updateAllDataConnectionTrackers()V
+Lcom/android/internal/telephony/SubscriptionController;->validateSubId(I)V
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->broadcastSimStateChanged(ILjava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->isAllIccIdQueryDone()Z
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mCurrentlyActiveUserId:I
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mIccId:[Ljava/lang/String;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mInsertSimState:[I
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPackageManager:Landroid/content/pm/IPackageManager;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPhone:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->PROJECT_SIM_NUM:I
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->updateSubscriptionInfoByIccId()V
+Lcom/android/internal/telephony/TelephonyCapabilities;->supportsAdn(I)Z
+Lcom/android/internal/telephony/TelephonyProperties;->PROPERTY_ICC_OPERATOR_NUMERIC:Ljava/lang/String;
+Lcom/android/internal/telephony/test/InterpreterEx;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->acceptCall(Landroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->dial(Ljava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->dial(Ljava/lang/String;ILcom/android/internal/telephony/UUSInfo;Landroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->mDcSuccess:Z
+Lcom/android/internal/telephony/test/SimulatedCommands;->resultFail(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->resultSuccess(Landroid/os/Message;Ljava/lang/Object;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->simulatedCallState:Lcom/android/internal/telephony/test/SimulatedGsmCallState;
+Lcom/android/internal/telephony/test/SimulatedCommands;->unimplemented(Landroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;->getInstance()Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;
+Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;->setCallForward(IIILjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->conference()Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->onChld(CC)Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseActiveAcceptHeldOrWaiting()Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseHeldOrUDUB()Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->separateCall(I)Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->switchActiveAndHeldOrWaiting()Z
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(IILjava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(II[B)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>([B)V
+Lcom/android/internal/telephony/uicc/AdnRecord;->buildAdnString(I)[B
+Lcom/android/internal/telephony/uicc/AdnRecord;->CREATOR:Landroid/os/Parcelable$Creator;
+Lcom/android/internal/telephony/uicc/AdnRecord;->getEmails()[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->getNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->isEmpty()Z
+Lcom/android/internal/telephony/uicc/AdnRecord;->mAlphaTag:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->mEfid:I
+Lcom/android/internal/telephony/uicc/AdnRecord;->mEmails:[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->mExtRecord:I
+Lcom/android/internal/telephony/uicc/AdnRecord;->mNumber:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->mRecordNumber:I
+Lcom/android/internal/telephony/uicc/AdnRecord;->setEmails([Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->extensionEfForEf(I)I
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->getRecordsIfLoaded(I)Ljava/util/ArrayList;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mAdnLikeWaiters:Landroid/util/SparseArray;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mUserWriteResponse:Landroid/util/SparseArray;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mUsimPhoneBookManager:Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->reset()V
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->sendErrorResponse(Landroid/os/Message;Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->updateAdnByIndex(ILcom/android/internal/telephony/uicc/AdnRecord;ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;-><init>(Lcom/android/internal/telephony/uicc/IccFileHandler;)V
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->getEFPath(I)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->loadFromEF(IIILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->updateEF(Lcom/android/internal/telephony/uicc/AdnRecord;IIILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_DETECTED:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_PIN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_READY:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_SUBSCRIPTION_PERSO:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_CSIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_ISIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_RUIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_SIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_USIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK_SUBSET:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_SERVICE_PROVIDER:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;-><init>()V
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;->AppTypeFromRILInt(I)Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;->app_type:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_ABSENT:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_ERROR:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_PRESENT:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->isCardPresent()Z
+Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_DISABLED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_ENABLED_BLOCKED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_ENABLED_PERM_BLOCKED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mApplications:[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mCardState:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mCdmaSubscriptionAppIndex:I
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mGsmUmtsSubscriptionAppIndex:I
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mImsSubscriptionAppIndex:I
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mUniversalPinState:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;-><init>(IILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;->mRecordSize:I
+Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;->results:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFLinearRecordSize(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFLinearRecordSize(ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFPath(I)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixed(IILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixed(ILjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->mAid:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFLinearFixed(II[BLjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFLinearFixed(ILjava/lang/String;I[BLjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFTransparent(I[BLandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccIoResult;-><init>(IILjava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IccIoResult;-><init>(II[B)V
+Lcom/android/internal/telephony/uicc/IccIoResult;->payload:[B
+Lcom/android/internal/telephony/uicc/IccIoResult;->success()Z
+Lcom/android/internal/telephony/uicc/IccIoResult;->sw1:I
+Lcom/android/internal/telephony/uicc/IccIoResult;->sw2:I
+Lcom/android/internal/telephony/uicc/IccRecords;->auth_rsp:Lcom/android/internal/telephony/uicc/IccIoResult;
+Lcom/android/internal/telephony/uicc/IccRecords;->getGid1()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getIccId()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getIccSimChallengeResponse(ILjava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getIMSI()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getMsisdnNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getOperatorNumeric()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getRecordsLoaded()Z
+Lcom/android/internal/telephony/uicc/IccRecords;->getServiceProviderName()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getUsimServiceTable()Lcom/android/internal/telephony/uicc/UsimServiceTable;
+Lcom/android/internal/telephony/uicc/IccRecords;->handleRefresh(Lcom/android/internal/telephony/uicc/IccRefreshResponse;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
+Lcom/android/internal/telephony/uicc/IccRecords;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/IccRecords;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/uicc/IccRecords;->mDestroyed:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/uicc/IccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/IccRecords;->mGid1:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mIccId:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mImsi:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mIsVoiceMailFixed:Z
+Lcom/android/internal/telephony/uicc/IccRecords;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/IccRecords;->mMncLength:I
+Lcom/android/internal/telephony/uicc/IccRecords;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/IccRecords;->mRecordsEventsRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/uicc/IccRecords;->mRecordsToLoad:I
+Lcom/android/internal/telephony/uicc/IccRecords;->mSpn:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mTelephonyManager:Landroid/telephony/TelephonyManager;
+Lcom/android/internal/telephony/uicc/IccRecords;->mVoiceMailNum:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForNetworkSelectionModeAutomatic(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForNewSms(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForRecordsEvents(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForRecordsLoaded(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->setMsisdnNumber(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->setVoiceCallForwardingFlag(IZLjava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForNetworkSelectionModeAutomatic(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForNewSms(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForRecordsEvents(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForRecordsLoaded(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;-><init>()V
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;->aid:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;->efId:I
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;->refreshResult:I
+Lcom/android/internal/telephony/uicc/IccServiceTable;->getTag()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccServiceTable;->mServiceTable:[B
+Lcom/android/internal/telephony/uicc/IccUtils;->adnStringFieldToString([BII)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->bcdToString([BII)Ljava/lang/String;
Lcom/android/internal/telephony/uicc/IccUtils;->bytesToHexString([B)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->cdmaBcdByteToInt(B)I
+Lcom/android/internal/telephony/uicc/IccUtils;->cdmaBcdToString([BII)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->gsmBcdByteToInt(B)I
+Lcom/android/internal/telephony/uicc/IccUtils;->hexCharToInt(C)I
+Lcom/android/internal/telephony/uicc/IccUtils;->hexStringToBytes(Ljava/lang/String;)[B
+Lcom/android/internal/telephony/uicc/IccUtils;->networkNameToString([BII)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->parseToBnW([BI)Landroid/graphics/Bitmap;
+Lcom/android/internal/telephony/uicc/IccUtils;->parseToRGB([BIZ)Landroid/graphics/Bitmap;
+Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimDomain()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimImpi()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimImpu()[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->isimTlvToString([B)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimDomain:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpi:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimIst:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/RuimRecords;->adjstMinDigits(I)I
+Lcom/android/internal/telephony/uicc/RuimRecords;->fetchRuimRecords()V
+Lcom/android/internal/telephony/uicc/RuimRecords;->getAssetLanguages(Landroid/content/Context;)[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->getCsimSpnDisplayCondition()Z
+Lcom/android/internal/telephony/uicc/RuimRecords;->getMdn()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->getMdnNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->getRUIMOperatorNumeric()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/RuimRecords;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/RuimRecords;->mEFli:[B
+Lcom/android/internal/telephony/uicc/RuimRecords;->mEFpl:[B
+Lcom/android/internal/telephony/uicc/RuimRecords;->mMin:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->mNai:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->onGetCSimEprlDone(Landroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->INIT:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_3GPP:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_CPHS:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_SHORT_CPHS:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords;->fetchSimRecords()V
+Lcom/android/internal/telephony/uicc/SIMRecords;->getExtFromEf(I)I
+Lcom/android/internal/telephony/uicc/SIMRecords;->getMsisdnNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/SIMRecords;->getOperatorNumeric()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/SIMRecords;->getSpnFsm(ZLandroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->getVoiceMailNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/SIMRecords;->isCphsMailboxEnabled()Z
+Lcom/android/internal/telephony/uicc/SIMRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->logv(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCff:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCfis:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCPHS_MWI:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfLi:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfMWIS:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfPl:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mSpnDisplayCondition:I
+Lcom/android/internal/telephony/uicc/SIMRecords;->mUsimServiceTable:Lcom/android/internal/telephony/uicc/UsimServiceTable;
+Lcom/android/internal/telephony/uicc/SIMRecords;->mVmConfig:Lcom/android/internal/telephony/uicc/VoiceMailConstants;
+Lcom/android/internal/telephony/uicc/SIMRecords;->setVoiceCallForwardingFlag(IZLjava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCard;->getApplication(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccCard;->getApplicationByType(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccCard;->getApplicationIndex(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccCard;->getCardState()Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/UiccCard;->getCarrierPackageNamesForIntent(Landroid/content/pm/PackageManager;Landroid/content/Intent;)Ljava/util/List;
+Lcom/android/internal/telephony/uicc/UiccCard;->getIccId()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCard;->getNumApplications()I
+Lcom/android/internal/telephony/uicc/UiccCard;->getOperatorBrandOverride()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCard;->isApplicationOnIcc(Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;)Z
+Lcom/android/internal/telephony/uicc/UiccCard;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCard;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCard;->mCardState:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/UiccCard;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/UiccCard;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/uicc/UiccCard;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/UiccCard;->mPhoneId:I
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->dispose()V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAid()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAuthContext()I
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getIccFileHandler()Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getIccRecords()Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPersoSubState()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPhoneId()I
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPin1State()Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getState()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getType()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAid:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAppState:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAppType:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mDestroyed:Z
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mPersoSubState:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mPin1State:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->registerForReady(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->unregisterForReady(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->update(Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;)V
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules$TLV;->length:Ljava/lang/Integer;
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules$TLV;->value:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules;->mLoadedCallback:Landroid/os/Message;
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules;->mState:Ljava/util/concurrent/atomic/AtomicInteger;
+Lcom/android/internal/telephony/uicc/UiccController;->getIccFileHandler(II)Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/UiccController;->getIccRecords(II)Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/uicc/UiccController;->getInstance()Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/uicc/UiccController;->getUiccCard(I)Lcom/android/internal/telephony/uicc/UiccCard;
+Lcom/android/internal/telephony/uicc/UiccController;->getUiccCardApplication(II)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccController;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccController;->mCis:[Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/UiccController;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/uicc/UiccController;->mInstance:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/uicc/UiccController;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/UiccController;->registerForIccChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->ALLOWED_CSG_LISTS_AND_INDICATIONS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->CFI_STATUS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->CSG_DISPLAY_CONTROL:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->FDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MBDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MSISDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MWI_STATUS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->OPERATOR_CSG_LISTS_AND_INDICATIONS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->OPERATOR_PLMN_LIST:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->PLMN_NETWORK_NAME:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_OVER_IP:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_SERVICE_PARAMS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_STORAGE:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SPN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable;->isAvailable(Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;)Z
+Lcom/android/internal/telephony/uicc/VoiceMailConstants;-><init>()V
+Lcom/android/internal/telephony/UiccPhoneBookController;-><init>([Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/UiccPhoneBookController;->getDefaultSubscription()I
+Lcom/android/internal/telephony/UiccPhoneBookController;->getIccPhoneBookInterfaceManager(I)Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;
+Lcom/android/internal/telephony/UiccPhoneBookController;->mPhone:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/UiccSmsController;->copyMessageToIccEfForSubscriber(ILjava/lang/String;I[B[B)Z
+Lcom/android/internal/telephony/UiccSmsController;->disableCellBroadcastForSubscriber(III)Z
+Lcom/android/internal/telephony/UiccSmsController;->disableCellBroadcastRangeForSubscriber(IIII)Z
+Lcom/android/internal/telephony/UiccSmsController;->enableCellBroadcastForSubscriber(III)Z
+Lcom/android/internal/telephony/UiccSmsController;->enableCellBroadcastRangeForSubscriber(IIII)Z
+Lcom/android/internal/telephony/UiccSmsController;->getAllMessagesFromIccEfForSubscriber(ILjava/lang/String;)Ljava/util/List;
+Lcom/android/internal/telephony/UiccSmsController;->getIccSmsInterfaceManager(I)Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/UiccSmsController;->getImsSmsFormatForSubscriber(I)Ljava/lang/String;
+Lcom/android/internal/telephony/UiccSmsController;->getPreferredSmsSubscription()I
+Lcom/android/internal/telephony/UiccSmsController;->isImsSmsSupportedForSubscriber(I)Z
+Lcom/android/internal/telephony/UiccSmsController;->sendDataForSubscriber(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/UiccSmsController;->sendErrorInPendingIntent(Landroid/app/PendingIntent;I)V
+Lcom/android/internal/telephony/UiccSmsController;->sendErrorInPendingIntents(Ljava/util/List;I)V
+Lcom/android/internal/telephony/UiccSmsController;->updateMessageOnIccEfForSubscriber(ILjava/lang/String;II[B)Z
+Lcom/android/internal/telephony/UUSInfo;->getDcs()I
+Lcom/android/internal/telephony/UUSInfo;->getType()I
+Lcom/android/internal/telephony/UUSInfo;->getUserData()[B
+Lcom/android/internal/telephony/WakeLockStateMachine;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/WakeLockStateMachine;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/WakeLockStateMachine;->mIdleState:Lcom/android/internal/telephony/WakeLockStateMachine$IdleState;
+Lcom/android/internal/telephony/WakeLockStateMachine;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/WapPushOverSms;->dispatchWapPdu([BLandroid/content/BroadcastReceiver;Lcom/android/internal/telephony/InboundSmsHandler;)I
+Lcom/android/internal/telephony/WapPushOverSms;->getDeliveryOrReadReportThreadId(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)J
+Lcom/android/internal/telephony/WapPushOverSms;->isDuplicateNotification(Landroid/content/Context;Lcom/google/android/mms/pdu/NotificationInd;)Z
+Lcom/android/internal/telephony/WapPushOverSms;->isWapPushForMms([BLcom/android/internal/telephony/InboundSmsHandler;)Z
+Lcom/android/internal/telephony/WapPushOverSms;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/WapPushOverSms;->mDeviceIdleController:Landroid/os/IDeviceIdleController;
+Lcom/android/internal/telephony/WapPushOverSms;->mWapPushManager:Lcom/android/internal/telephony/IWapPushManager;
+Lcom/android/internal/telephony/WspTypeDecoder;-><init>([B)V
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeContentType(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeIntegerValue(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeShortInteger(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeTextString(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeUintvarInteger(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeValueLength(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeXWapApplicationId(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->getContentParameters()Ljava/util/HashMap;
+Lcom/android/internal/telephony/WspTypeDecoder;->getDecodedDataLength()I
+Lcom/android/internal/telephony/WspTypeDecoder;->getValue32()J
+Lcom/android/internal/telephony/WspTypeDecoder;->getValueString()Ljava/lang/String;
+Lcom/android/internal/telephony/WspTypeDecoder;->mWspData:[B
+Lcom/android/internal/telephony/WspTypeDecoder;->seekXWapApplicationId(II)Z
Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/util/ArrayUtils;->appendElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->appendInt([II)[I
+Lcom/android/internal/util/ArrayUtils;->contains([II)Z
+Lcom/android/internal/util/ArrayUtils;->contains([Ljava/lang/Object;Ljava/lang/Object;)Z
+Lcom/android/internal/util/ArrayUtils;->emptyArray(Ljava/lang/Class;)[Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->indexOf([Ljava/lang/Object;Ljava/lang/Object;)I
+Lcom/android/internal/util/ArrayUtils;->isEmpty([Ljava/lang/Object;)Z
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedArray(Ljava/lang/Class;I)[Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedIntArray(I)[I
+Lcom/android/internal/util/ArrayUtils;->removeElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
+Lcom/android/internal/util/BitwiseInputStream;-><init>([B)V
+Lcom/android/internal/util/BitwiseInputStream;->available()I
+Lcom/android/internal/util/BitwiseInputStream;->read(I)I
+Lcom/android/internal/util/BitwiseInputStream;->readByteArray(I)[B
+Lcom/android/internal/util/BitwiseInputStream;->skip(I)V
+Lcom/android/internal/util/BitwiseOutputStream;-><init>(I)V
+Lcom/android/internal/util/BitwiseOutputStream;->toByteArray()[B
+Lcom/android/internal/util/BitwiseOutputStream;->write(II)V
+Lcom/android/internal/util/BitwiseOutputStream;->writeByteArray(I[B)V
+Lcom/android/internal/util/CharSequences;->compareToIgnoreCase(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)I
+Lcom/android/internal/util/CharSequences;->equals(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Z
+Lcom/android/internal/util/FastMath;->round(F)I
+Lcom/android/internal/util/FastXmlSerializer;-><init>()V
+Lcom/android/internal/util/GrowingArrayUtils;->append([III)[I
+Lcom/android/internal/util/GrowingArrayUtils;->append([Ljava/lang/Object;ILjava/lang/Object;)[Ljava/lang/Object;
+Lcom/android/internal/util/HexDump;->hexStringToByteArray(Ljava/lang/String;)[B
+Lcom/android/internal/util/HexDump;->toHexString(I)Ljava/lang/String;
+Lcom/android/internal/util/HexDump;->toHexString([B)Ljava/lang/String;
+Lcom/android/internal/util/HexDump;->toHexString([BII)Ljava/lang/String;
Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
+Lcom/android/internal/util/IState;->getName()Ljava/lang/String;
+Lcom/android/internal/util/MemInfoReader;-><init>()V
+Lcom/android/internal/util/MemInfoReader;->getCachedSize()J
+Lcom/android/internal/util/MemInfoReader;->getFreeSize()J
+Lcom/android/internal/util/MemInfoReader;->getRawInfo()[J
+Lcom/android/internal/util/MemInfoReader;->getTotalSize()J
+Lcom/android/internal/util/MemInfoReader;->readMemInfo()V
+Lcom/android/internal/util/Preconditions;->checkArgument(Z)V
+Lcom/android/internal/util/Preconditions;->checkArgument(ZLjava/lang/Object;)V
+Lcom/android/internal/util/Preconditions;->checkArgumentInRange(IIILjava/lang/String;)I
+Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/Preconditions;->checkState(Z)V
+Lcom/android/internal/util/Preconditions;->checkState(ZLjava/lang/String;)V
+Lcom/android/internal/util/State;-><init>()V
+Lcom/android/internal/util/State;->enter()V
+Lcom/android/internal/util/State;->exit()V
+Lcom/android/internal/util/State;->getName()Ljava/lang/String;
+Lcom/android/internal/util/State;->processMessage(Landroid/os/Message;)Z
+Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;Landroid/os/Handler;)V
+Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;Landroid/os/Looper;)V
+Lcom/android/internal/util/StateMachine;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
+Lcom/android/internal/util/StateMachine;->obtainMessage(III)Landroid/os/Message;
+Lcom/android/internal/util/StateMachine;->obtainMessage(IIILjava/lang/Object;)Landroid/os/Message;
+Lcom/android/internal/util/StateMachine;->sendMessage(I)V
+Lcom/android/internal/util/StateMachine;->sendMessage(II)V
+Lcom/android/internal/util/StateMachine;->sendMessage(IIILjava/lang/Object;)V
+Lcom/android/internal/util/StateMachine;->sendMessage(ILjava/lang/Object;)V
+Lcom/android/internal/util/StateMachine;->sendMessage(Landroid/os/Message;)V
+Lcom/android/internal/view/ActionBarPolicy;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/ActionBarPolicy;->get(Landroid/content/Context;)Lcom/android/internal/view/ActionBarPolicy;
+Lcom/android/internal/view/ActionBarPolicy;->getEmbeddedMenuWidthLimit()I
+Lcom/android/internal/view/ActionBarPolicy;->getMaxActionButtons()I
+Lcom/android/internal/view/ActionBarPolicy;->getStackedTabMaxWidth()I
+Lcom/android/internal/view/ActionBarPolicy;->getTabContainerHeight()I
+Lcom/android/internal/view/ActionBarPolicy;->hasEmbeddedTabs()Z
+Lcom/android/internal/view/ActionBarPolicy;->mContext:Landroid/content/Context;
+Lcom/android/internal/view/ActionBarPolicy;->showsOverflowMenuButton()Z
Lcom/android/internal/view/BaseIWindow;-><init>()V
Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession;
+Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;->dispose()V
+Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;->getInstance()Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;
+Lcom/android/internal/view/menu/ActionMenu;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/menu/ActionMenuItem;-><init>(Landroid/content/Context;IIIILjava/lang/CharSequence;)V
+Lcom/android/internal/view/menu/ContextMenuBuilder;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/menu/IconMenuItemView;->getTextAppropriateLayoutParams()Lcom/android/internal/view/menu/IconMenuView$LayoutParams;
+Lcom/android/internal/view/menu/IconMenuItemView;->setIconMenuView(Lcom/android/internal/view/menu/IconMenuView;)V
+Lcom/android/internal/view/menu/IconMenuItemView;->setItemInvoker(Lcom/android/internal/view/menu/MenuBuilder$ItemInvoker;)V
+Lcom/android/internal/view/menu/IconMenuView$SavedState;-><init>(Landroid/os/Parcel;)V
+Lcom/android/internal/view/menu/IconMenuView;->createMoreItemView()Lcom/android/internal/view/menu/IconMenuItemView;
+Lcom/android/internal/view/menu/IconMenuView;->getNumActualItemsShown()I
+Lcom/android/internal/view/menu/IconMenuView;->mItemBackground:Landroid/graphics/drawable/Drawable;
+Lcom/android/internal/view/menu/IconMenuView;->mMaxItems:I
+Lcom/android/internal/view/menu/IconMenuView;->mMenu:Lcom/android/internal/view/menu/MenuBuilder;
+Lcom/android/internal/view/menu/MenuDialogHelper;-><init>(Lcom/android/internal/view/menu/MenuBuilder;)V
+Lcom/android/internal/view/menu/MenuDialogHelper;->dismiss()V
+Lcom/android/internal/view/menu/MenuDialogHelper;->show(Landroid/os/IBinder;)V
+Lcom/android/internal/view/WindowManagerPolicyThread;->getLooper()Landroid/os/Looper;
+Lcom/android/internal/widget/AbsActionBarView;->dismissPopupMenus()V
+Lcom/android/internal/widget/ActionBarContextView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/ActionBarOverlayLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/ActionBarOverlayLayout;->setWindowCallback(Landroid/view/Window$Callback;)V
+Lcom/android/internal/widget/EditableInputConnection;-><init>(Landroid/widget/TextView;)V
Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
Lcom/android/internal/widget/ILockSettings;->getBoolean(Ljava/lang/String;ZI)Z
Lcom/android/internal/widget/ILockSettings;->getLong(Ljava/lang/String;JI)J
@@ -2088,17 +4052,109 @@
Lcom/android/internal/widget/IRemoteViewsFactory;->hasStableIds()Z
Lcom/android/internal/widget/IRemoteViewsFactory;->isCreated()Z
Lcom/android/internal/widget/IRemoteViewsFactory;->onDataSetChanged()V
+Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;->setDefaultTouchRecepient(Landroid/view/View;)V
+Lcom/android/internal/widget/LockPatternChecker;->checkPassword(Lcom/android/internal/widget/LockPatternUtils;Ljava/lang/String;ILcom/android/internal/widget/LockPatternChecker$OnCheckCallback;)Landroid/os/AsyncTask;
+Lcom/android/internal/widget/LockPatternUtils$RequestThrottledException;-><init>(I)V
+Lcom/android/internal/widget/LockPatternUtils$RequestThrottledException;->getTimeoutMs()I
+Lcom/android/internal/widget/LockPatternUtils;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/widget/LockPatternUtils;->checkPassword(Ljava/lang/String;I)Z
+Lcom/android/internal/widget/LockPatternUtils;->getActivePasswordQuality(I)I
+Lcom/android/internal/widget/LockPatternUtils;->getDevicePolicyManager()Landroid/app/admin/DevicePolicyManager;
+Lcom/android/internal/widget/LockPatternUtils;->getKeyguardStoredPasswordQuality(I)I
+Lcom/android/internal/widget/LockPatternUtils;->getLockSettings()Lcom/android/internal/widget/ILockSettings;
+Lcom/android/internal/widget/LockPatternUtils;->getOwnerInfo(I)Ljava/lang/String;
+Lcom/android/internal/widget/LockPatternUtils;->getPowerButtonInstantlyLocks(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->getString(Ljava/lang/String;I)Ljava/lang/String;
+Lcom/android/internal/widget/LockPatternUtils;->isDeviceEncryptionEnabled()Z
+Lcom/android/internal/widget/LockPatternUtils;->isLockPasswordEnabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isLockPatternEnabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isLockScreenDisabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isSecure(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isTactileFeedbackEnabled()Z
+Lcom/android/internal/widget/LockPatternUtils;->isVisiblePatternEnabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->mContentResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/widget/LockPatternUtils;->mContext:Landroid/content/Context;
+Lcom/android/internal/widget/LockPatternUtils;->patternToHash(Ljava/util/List;)[B
+Lcom/android/internal/widget/LockPatternUtils;->patternToString(Ljava/util/List;)Ljava/lang/String;
+Lcom/android/internal/widget/LockPatternUtils;->reportFailedPasswordAttempt(I)V
+Lcom/android/internal/widget/LockPatternUtils;->reportSuccessfulPasswordAttempt(I)V
+Lcom/android/internal/widget/LockPatternUtils;->saveLockPassword(Ljava/lang/String;Ljava/lang/String;II)V
+Lcom/android/internal/widget/LockPatternUtils;->setLockoutAttemptDeadline(II)J
+Lcom/android/internal/widget/LockPatternUtils;->setLong(Ljava/lang/String;JI)V
+Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfo(Ljava/lang/String;I)V
+Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfoEnabled(ZI)V
+Lcom/android/internal/widget/LockPatternUtils;->setString(Ljava/lang/String;Ljava/lang/String;I)V
+Lcom/android/internal/widget/LockPatternView$Cell;->column:I
+Lcom/android/internal/widget/LockPatternView$Cell;->row:I
+Lcom/android/internal/widget/LockPatternView$DisplayMode;->Animate:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView$DisplayMode;->Correct:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView$DisplayMode;->Wrong:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView$SavedState;-><init>(Landroid/os/Parcel;)V
+Lcom/android/internal/widget/LockPatternView$SavedState;-><init>(Landroid/os/Parcelable;Ljava/lang/String;IZZZ)V
+Lcom/android/internal/widget/LockPatternView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/LockPatternView;->clearPattern()V
+Lcom/android/internal/widget/LockPatternView;->disableInput()V
+Lcom/android/internal/widget/LockPatternView;->enableInput()V
+Lcom/android/internal/widget/LockPatternView;->getCellStates()[[Lcom/android/internal/widget/LockPatternView$CellState;
+Lcom/android/internal/widget/LockPatternView;->mInStealthMode:Z
+Lcom/android/internal/widget/LockPatternView;->mPaint:Landroid/graphics/Paint;
+Lcom/android/internal/widget/LockPatternView;->mPathPaint:Landroid/graphics/Paint;
+Lcom/android/internal/widget/LockPatternView;->mPattern:Ljava/util/ArrayList;
+Lcom/android/internal/widget/LockPatternView;->mPatternDisplayMode:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView;->mPatternInProgress:Z
+Lcom/android/internal/widget/LockPatternView;->mSquareHeight:F
+Lcom/android/internal/widget/LockPatternView;->mSquareWidth:F
+Lcom/android/internal/widget/LockPatternView;->notifyPatternDetected()V
+Lcom/android/internal/widget/LockPatternView;->setDisplayMode(Lcom/android/internal/widget/LockPatternView$DisplayMode;)V
+Lcom/android/internal/widget/LockPatternView;->setInStealthMode(Z)V
+Lcom/android/internal/widget/LockPatternView;->setOnPatternListener(Lcom/android/internal/widget/LockPatternView$OnPatternListener;)V
+Lcom/android/internal/widget/LockPatternView;->setTactileFeedbackEnabled(Z)V
+Lcom/android/internal/widget/PointerLocationView$PointerState;-><init>()V
+Lcom/android/internal/widget/PointerLocationView$PointerState;->mCurDown:Z
+Lcom/android/internal/widget/PointerLocationView;->mCurDown:Z
+Lcom/android/internal/widget/PointerLocationView;->mCurNumPointers:I
+Lcom/android/internal/widget/PointerLocationView;->mMaxNumPointers:I
+Lcom/android/internal/widget/PointerLocationView;->mPointers:Ljava/util/ArrayList;
+Lcom/android/internal/widget/PointerLocationView;->mPrintCoords:Z
+Lcom/android/internal/widget/PreferenceImageView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/RecyclerView$RecycledViewPool$ScrapData;->mScrapHeap:Ljava/util/ArrayList;
Lcom/android/internal/widget/ScrollBarUtils;->getThumbLength(IIII)I
+Lcom/android/internal/widget/SlidingTab$Slider;->tab:Landroid/widget/ImageView;
+Lcom/android/internal/widget/SlidingTab$Slider;->text:Landroid/widget/TextView;
+Lcom/android/internal/widget/SlidingTab;->mAnimationDoneListener:Landroid/view/animation/Animation$AnimationListener;
+Lcom/android/internal/widget/SlidingTab;->mLeftSlider:Lcom/android/internal/widget/SlidingTab$Slider;
+Lcom/android/internal/widget/SlidingTab;->mRightSlider:Lcom/android/internal/widget/SlidingTab$Slider;
+Lcom/android/internal/widget/SlidingTab;->onAnimationDone()V
+Lcom/android/internal/widget/SlidingTab;->resetView()V
+Lcom/android/internal/widget/SlidingTab;->setHoldAfterTrigger(ZZ)V
+Lcom/android/internal/widget/SlidingTab;->setLeftHintText(I)V
+Lcom/android/internal/widget/SlidingTab;->setLeftTabResources(IIII)V
+Lcom/android/internal/widget/SlidingTab;->setOnTriggerListener(Lcom/android/internal/widget/SlidingTab$OnTriggerListener;)V
+Lcom/android/internal/widget/SlidingTab;->setRightHintText(I)V
+Lcom/android/internal/widget/SlidingTab;->setRightTabResources(IIII)V
+Lcom/android/internal/widget/TextViewInputDisabler;-><init>(Landroid/widget/TextView;)V
+Lcom/android/internal/widget/TextViewInputDisabler;->setInputEnabled(Z)V
+Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageScrolled(IFI)V
+Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageScrollStateChanged(I)V
+Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageSelected(I)V
+Lcom/android/internal/widget/ViewPager;->getCurrentItem()I
Lcom/android/okhttp/Connection;->getSocket()Ljava/net/Socket;
Lcom/android/okhttp/ConnectionPool;->connections:Ljava/util/Deque;
Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I
Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/HttpHandler;-><init>()V
+Lcom/android/okhttp/HttpsHandler;-><init>()V
Lcom/android/okhttp/HttpUrl$Builder;->build()Lcom/android/okhttp/HttpUrl;
Lcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String;
Lcom/android/okhttp/HttpUrl;->newBuilder()Lcom/android/okhttp/HttpUrl$Builder;
Lcom/android/okhttp/HttpUrl;->parse(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
Lcom/android/okhttp/HttpUrl;->query()Ljava/lang/String;
+Lcom/android/okhttp/internal/http/HeaderParser;->skipUntil(Ljava/lang/String;ILjava/lang/String;)I
+Lcom/android/okhttp/internal/http/HeaderParser;->skipWhitespace(Ljava/lang/String;I)I
+Lcom/android/okhttp/internal/http/HttpDate;->format(Ljava/util/Date;)Ljava/lang/String;
+Lcom/android/okhttp/internal/http/HttpDate;->parse(Ljava/lang/String;)Ljava/util/Date;
Lcom/android/okhttp/internal/http/HttpEngine;->getConnection()Lcom/android/okhttp/Connection;
Lcom/android/okhttp/internal/http/HttpEngine;->hasResponse()Z
Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream;
@@ -2111,6 +4167,29 @@
Lcom/android/okhttp/internal/http/HttpEngine;->userResponse:Lcom/android/okhttp/Response;
Lcom/android/okhttp/internal/http/HttpEngine;->writingRequestHeaders()V
Lcom/android/okhttp/internal/http/RouteSelector;->hasNext()Z
+Lcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->delegate:Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->client:Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->httpEngine:Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/Internal;-><init>()V
+Lcom/android/okhttp/internal/Internal;->addLenient(Lcom/android/okhttp/Headers$Builder;Ljava/lang/String;)V
+Lcom/android/okhttp/internal/Internal;->addLenient(Lcom/android/okhttp/Headers$Builder;Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/okhttp/internal/Internal;->apply(Lcom/android/okhttp/ConnectionSpec;Ljavax/net/ssl/SSLSocket;Z)V
+Lcom/android/okhttp/internal/Internal;->callEngineGetStreamAllocation(Lcom/android/okhttp/Call;)Lcom/android/okhttp/internal/http/StreamAllocation;
+Lcom/android/okhttp/internal/Internal;->callEnqueue(Lcom/android/okhttp/Call;Lcom/android/okhttp/Callback;Z)V
+Lcom/android/okhttp/internal/Internal;->connectionBecameIdle(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/internal/io/RealConnection;)Z
+Lcom/android/okhttp/internal/Internal;->get(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/http/StreamAllocation;)Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/Internal;->getHttpUrlChecked(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/internal/Internal;->instance:Lcom/android/okhttp/internal/Internal;
+Lcom/android/okhttp/internal/Internal;->internalCache(Lcom/android/okhttp/OkHttpClient;)Lcom/android/okhttp/internal/InternalCache;
+Lcom/android/okhttp/internal/Internal;->put(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/internal/io/RealConnection;)V
+Lcom/android/okhttp/internal/Internal;->routeDatabase(Lcom/android/okhttp/ConnectionPool;)Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/internal/Internal;->setCache(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/internal/InternalCache;)V
+Lcom/android/okhttp/internal/Platform;->get()Lcom/android/okhttp/internal/Platform;
+Lcom/android/okhttp/internal/Platform;->logW(Ljava/lang/String;)V
+Lcom/android/okhttp/internal/Util;->closeAll(Ljava/io/Closeable;Ljava/io/Closeable;)V
+Lcom/android/okhttp/internal/Util;->closeQuietly(Ljava/io/Closeable;)V
+Lcom/android/okhttp/internal/Util;->EMPTY_BYTE_ARRAY:[B
+Lcom/android/okhttp/internal/Util;->UTF_8:Ljava/nio/charset/Charset;
Lcom/android/okhttp/OkHttpClient;-><init>()V
Lcom/android/okhttp/OkHttpClient;->connectionPool:Lcom/android/okhttp/ConnectionPool;
Lcom/android/okhttp/OkHttpClient;->DEFAULT_PROTOCOLS:Ljava/util/List;
@@ -2131,11 +4210,62 @@
Lcom/android/okhttp/Response;->message:Ljava/lang/String;
Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
+Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;-><init>()V
+Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;->add(Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
+Lcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>(Ljava/io/InputStream;)V
+Lcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>([B)V
+Lcom/android/org/bouncycastle/asn1/ASN1InputStream;->readObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
+Lcom/android/org/bouncycastle/asn1/ASN1Integer;-><init>(Ljava/math/BigInteger;)V
+Lcom/android/org/bouncycastle/asn1/DERBitString;-><init>([B)V
+Lcom/android/org/bouncycastle/asn1/DEREncodableVector;-><init>()V
+Lcom/android/org/bouncycastle/asn1/DERInteger;-><init>(J)V
+Lcom/android/org/bouncycastle/asn1/DERInteger;-><init>(Ljava/math/BigInteger;)V
+Lcom/android/org/bouncycastle/asn1/DERNull;->INSTANCE:Lcom/android/org/bouncycastle/asn1/DERNull;
+Lcom/android/org/bouncycastle/asn1/DERObjectIdentifier;-><init>(Ljava/lang/String;)V
+Lcom/android/org/bouncycastle/asn1/DEROctetString;-><init>([B)V
+Lcom/android/org/bouncycastle/asn1/DEROutputStream;-><init>(Ljava/io/OutputStream;)V
+Lcom/android/org/bouncycastle/asn1/DERSequence;-><init>()V
+Lcom/android/org/bouncycastle/asn1/DERSequence;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
+Lcom/android/org/bouncycastle/asn1/DERSet;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
+Lcom/android/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers;->sha256WithRSAEncryption:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;)V
+Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
+Lcom/android/org/bouncycastle/asn1/x509/Certificate;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/Certificate;
+Lcom/android/org/bouncycastle/asn1/x509/DigestInfo;-><init>(Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;[B)V
+Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;
+Lcom/android/org/bouncycastle/asn1/x509/Time;-><init>(Ljava/util/Date;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;-><init>()V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->generateTBSCertificate()Lcom/android/org/bouncycastle/asn1/x509/TBSCertificate;
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setEndDate(Lcom/android/org/bouncycastle/asn1/x509/Time;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setIssuer(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSerialNumber(Lcom/android/org/bouncycastle/asn1/ASN1Integer;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSignature(Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setStartDate(Lcom/android/org/bouncycastle/asn1/x509/Time;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSubject(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
+Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSubjectPublicKeyInfo(Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;)V
+Lcom/android/org/bouncycastle/asn1/x509/X509Name;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1Sequence;)V
+Lcom/android/org/bouncycastle/asn1/x509/X509Name;-><init>(Ljava/lang/String;)V
+Lcom/android/org/bouncycastle/asn1/x509/X509Name;->CN:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+Lcom/android/org/bouncycastle/asn1/x509/X509Name;->getOIDs()Ljava/util/Vector;
+Lcom/android/org/bouncycastle/asn1/x509/X509Name;->getValues()Ljava/util/Vector;
+Lcom/android/org/bouncycastle/asn1/x9/X9ObjectIdentifiers;->ecdsa_with_SHA256:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider;-><init>()V
+Lcom/android/org/bouncycastle/jce/provider/X509CertificateObject;-><init>(Lcom/android/org/bouncycastle/asn1/x509/Certificate;)V
+Lcom/android/org/bouncycastle/jce/X509Principal;-><init>([B)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;-><init>()V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->generate(Ljava/security/PrivateKey;)Ljava/security/cert/X509Certificate;
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setIssuerDN(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setIssuerDN(Ljavax/security/auth/x500/X500Principal;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setNotAfter(Ljava/util/Date;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setNotBefore(Ljava/util/Date;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setPublicKey(Ljava/security/PublicKey;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSerialNumber(Ljava/math/BigInteger;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSignatureAlgorithm(Ljava/lang/String;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSubjectDN(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
+Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSubjectDN(Ljavax/security/auth/x500/X500Principal;)V
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocol()Ljava/lang/String;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getChannelId()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHandshakeApplicationProtocol()Ljava/lang/String;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostname()Ljava/lang/String;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostnameOrIP()Ljava/lang/String;
Lcom/android/org/conscrypt/AbstractConscryptSocket;->getNpnSelectedProtocol()[B
@@ -2150,14 +4280,73 @@
Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V
Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V
Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
+Lcom/android/org/conscrypt/ClientSessionContext;->getSession(Ljava/lang/String;I)Lcom/android/org/conscrypt/NativeSslSession;
+Lcom/android/org/conscrypt/ClientSessionContext;->setPersistentCache(Lcom/android/org/conscrypt/SSLClientSessionCache;)V
Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
+Lcom/android/org/conscrypt/FileClientSessionCache$Impl;->getSessionData(Ljava/lang/String;I)[B
+Lcom/android/org/conscrypt/FileClientSessionCache;->usingDirectory(Ljava/io/File;)Lcom/android/org/conscrypt/SSLClientSessionCache;
+Lcom/android/org/conscrypt/NativeCrypto;->ASN1_seq_pack_X509([J)[B
+Lcom/android/org/conscrypt/NativeCrypto;->ASN1_seq_unpack_X509_bio(J)[J
+Lcom/android/org/conscrypt/NativeCrypto;->ASN1_TIME_to_Calendar(JLjava/util/Calendar;)V
+Lcom/android/org/conscrypt/NativeCrypto;->BIO_free_all(J)V
+Lcom/android/org/conscrypt/NativeCrypto;->create_BIO_InputStream(Lcom/android/org/conscrypt/OpenSSLBIOInputStream;Z)J
+Lcom/android/org/conscrypt/NativeCrypto;->create_BIO_OutputStream(Ljava/io/OutputStream;)J
+Lcom/android/org/conscrypt/NativeCrypto;->d2i_PKCS7_bio(JI)[J
+Lcom/android/org/conscrypt/NativeCrypto;->d2i_SSL_SESSION([B)J
+Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509([B)J
+Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509_bio(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509_CRL_bio(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->EC_GROUP_clear_free(J)V
+Lcom/android/org/conscrypt/NativeCrypto;->EC_GROUP_new_by_curve_name(Ljava/lang/String;)J
+Lcom/android/org/conscrypt/NativeCrypto;->EC_POINT_clear_free(J)V
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_CIPHER_CTX_new()J
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_CIPHER_iv_length(J)I
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_get_cipherbyname(Ljava/lang/String;)J
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_get_digestbyname(Ljava/lang/String;)J
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_CTX_create()J
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_CTX_destroy(J)V
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_size(J)I
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_PKEY_free(J)V
+Lcom/android/org/conscrypt/NativeCrypto;->EVP_PKEY_new_RSA([B[B[B[B[B[B[B[B)J
+Lcom/android/org/conscrypt/NativeCrypto;->get_X509_REVOKED_ext_oids(JI)[Ljava/lang/String;
+Lcom/android/org/conscrypt/NativeCrypto;->get_X509_REVOKED_revocationDate(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->i2d_PKCS7([J)[B
+Lcom/android/org/conscrypt/NativeCrypto;->i2d_SSL_SESSION(J)[B
+Lcom/android/org/conscrypt/NativeCrypto;->i2d_X509_REVOKED(J)[B
+Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_PKCS7(JI)[J
+Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_X509(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_X509_CRL(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->RAND_bytes([B)V
+Lcom/android/org/conscrypt/NativeCrypto;->RSA_generate_key_ex(I[B)J
+Lcom/android/org/conscrypt/NativeCrypto;->SSL_CTX_new()J
+Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_cipher(J)Ljava/lang/String;
+Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_free(J)V
+Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_get_time(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_get_version(J)Ljava/lang/String;
+Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_session_id(J)[B
+Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_dup(J)J
+Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_ext(JLjava/lang/String;)J
+Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_ext_oid(JLjava/lang/String;)[B
+Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_serialNumber(J)[B
+Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_print(JJ)V
+Lcom/android/org/conscrypt/NativeCrypto;->X509_supported_extension(J)I
+Lcom/android/org/conscrypt/OpenSSLBIOInputStream;-><init>(Ljava/io/InputStream;Z)V
+Lcom/android/org/conscrypt/OpenSSLBIOInputStream;->getBioContext()J
+Lcom/android/org/conscrypt/OpenSSLBIOInputStream;->release()V
+Lcom/android/org/conscrypt/OpenSSLContextImpl$TLSv12;-><init>()V
+Lcom/android/org/conscrypt/OpenSSLContextImpl;-><init>()V
+Lcom/android/org/conscrypt/OpenSSLContextImpl;->engineGetClientSessionContext()Lcom/android/org/conscrypt/ClientSessionContext;
+Lcom/android/org/conscrypt/OpenSSLContextImpl;->getPreferred()Lcom/android/org/conscrypt/OpenSSLContextImpl;
Lcom/android/org/conscrypt/OpenSSLKey;-><init>(J)V
Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey;)Lcom/android/org/conscrypt/OpenSSLKey;
Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
+Lcom/android/org/conscrypt/OpenSSLKeyHolder;->getOpenSSLKey()Lcom/android/org/conscrypt/OpenSSLKey;
Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
Lcom/android/org/conscrypt/OpenSSLRandom;-><init>()V
+Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;-><init>()V
+Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;->sslParameters:Lcom/android/org/conscrypt/SSLParametersImpl;
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
@@ -2175,32 +4364,83 @@
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
Lcom/android/org/conscrypt/OpenSSLX509Certificate;->fromX509PemInputStream(Ljava/io/InputStream;)Lcom/android/org/conscrypt/OpenSSLX509Certificate;
Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
+Lcom/android/org/conscrypt/SSLParametersImpl;->getDefault()Lcom/android/org/conscrypt/SSLParametersImpl;
+Lcom/android/org/conscrypt/SSLParametersImpl;->getDefaultX509TrustManager()Ljavax/net/ssl/X509TrustManager;
+Lcom/android/org/conscrypt/SSLParametersImpl;->getX509TrustManager()Ljavax/net/ssl/X509TrustManager;
+Lcom/android/org/conscrypt/SSLParametersImpl;->setEnabledProtocols([Ljava/lang/String;)V
+Lcom/android/org/conscrypt/SSLParametersImpl;->x509TrustManager:Ljavax/net/ssl/X509TrustManager;
Lcom/android/org/conscrypt/TrustedCertificateStore;-><init>()V
Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+Lcom/android/org/conscrypt/X509PublicKey;-><init>(Ljava/lang/String;[B)V
+Lcom/android/server/net/BaseNetworkObserver;-><init>()V
+Lcom/android/server/net/NetlinkTracker;-><init>(Ljava/lang/String;Lcom/android/server/net/NetlinkTracker$Callback;)V
+Lcom/android/server/net/NetlinkTracker;->clearLinkProperties()V
+Lcom/android/server/net/NetlinkTracker;->getLinkProperties()Landroid/net/LinkProperties;
+Lcom/android/server/ResettableTimeout$T;-><init>(Lcom/android/server/ResettableTimeout;)V
+Lcom/android/server/ResettableTimeout;->mLock:Landroid/os/ConditionVariable;
+Lcom/android/server/ResettableTimeout;->mOffAt:J
+Lcom/google/android/collect/Lists;->newArrayList([Ljava/lang/Object;)Ljava/util/ArrayList;
+Lcom/google/android/collect/Sets;->newArraySet()Landroid/util/ArraySet;
+Lcom/google/android/collect/Sets;->newArraySet([Ljava/lang/Object;)Landroid/util/ArraySet;
+Lcom/google/android/collect/Sets;->newHashSet()Ljava/util/HashSet;
+Lcom/google/android/collect/Sets;->newHashSet([Ljava/lang/Object;)Ljava/util/HashSet;
+Lcom/google/android/collect/Sets;->newSortedSet()Ljava/util/SortedSet;
+Lcom/google/android/gles_jni/EGLImpl;-><init>()V
+Lcom/google/android/gles_jni/GLImpl;-><init>()V
Lcom/google/android/mms/ContentType;->getAudioTypes()Ljava/util/ArrayList;
Lcom/google/android/mms/ContentType;->getImageTypes()Ljava/util/ArrayList;
Lcom/google/android/mms/ContentType;->getVideoTypes()Ljava/util/ArrayList;
Lcom/google/android/mms/ContentType;->isAudioType(Ljava/lang/String;)Z
Lcom/google/android/mms/ContentType;->isDrmType(Ljava/lang/String;)Z
Lcom/google/android/mms/ContentType;->isImageType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedAudioType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedImageType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedVideoType(Ljava/lang/String;)Z
Lcom/google/android/mms/ContentType;->isTextType(Ljava/lang/String;)Z
Lcom/google/android/mms/ContentType;->isVideoType(Ljava/lang/String;)Z
+Lcom/google/android/mms/InvalidHeaderValueException;-><init>(Ljava/lang/String;)V
Lcom/google/android/mms/MmsException;-><init>()V
Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;)V
+Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/Throwable;)V
Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(I[B)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;->setReportAllowed(I)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;->setTransactionId([B)V
+Lcom/google/android/mms/pdu/Base64;->decodeBase64([B)[B
+Lcom/google/android/mms/pdu/CharacterSets;->getMibEnumValue(Ljava/lang/String;)I
Lcom/google/android/mms/pdu/CharacterSets;->getMimeName(I)Ljava/lang/String;
+Lcom/google/android/mms/pdu/DeliveryInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/DeliveryInd;->getDate()J
Lcom/google/android/mms/pdu/DeliveryInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/DeliveryInd;->getStatus()I
+Lcom/google/android/mms/pdu/DeliveryInd;->getTo()[Lcom/google/android/mms/pdu/EncodedStringValue;
Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(I[B)V
Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(Ljava/lang/String;)V
Lcom/google/android/mms/pdu/EncodedStringValue;-><init>([B)V
+Lcom/google/android/mms/pdu/EncodedStringValue;->appendTextString([B)V
Lcom/google/android/mms/pdu/EncodedStringValue;->concat([Lcom/google/android/mms/pdu/EncodedStringValue;)Ljava/lang/String;
+Lcom/google/android/mms/pdu/EncodedStringValue;->copy(Lcom/google/android/mms/pdu/EncodedStringValue;)Lcom/google/android/mms/pdu/EncodedStringValue;
Lcom/google/android/mms/pdu/EncodedStringValue;->encodeStrings([Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/EncodedStringValue;->extract(Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/EncodedStringValue;->getCharacterSet()I
Lcom/google/android/mms/pdu/EncodedStringValue;->getString()Ljava/lang/String;
+Lcom/google/android/mms/pdu/EncodedStringValue;->getTextString()[B
+Lcom/google/android/mms/pdu/EncodedStringValue;->setCharacterSet(I)V
+Lcom/google/android/mms/pdu/EncodedStringValue;->setTextString([B)V
+Lcom/google/android/mms/pdu/GenericPdu;-><init>()V
+Lcom/google/android/mms/pdu/GenericPdu;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
Lcom/google/android/mms/pdu/GenericPdu;->getMessageType()I
+Lcom/google/android/mms/pdu/GenericPdu;->getPduHeaders()Lcom/google/android/mms/pdu/PduHeaders;
+Lcom/google/android/mms/pdu/GenericPdu;->mPduHeaders:Lcom/google/android/mms/pdu/PduHeaders;
Lcom/google/android/mms/pdu/GenericPdu;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/GenericPdu;->setMessageType(I)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;-><init>()V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->addTo(Lcom/google/android/mms/pdu/EncodedStringValue;)V
Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getBody()Lcom/google/android/mms/pdu/PduBody;
Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getDate()J
Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getPriority()I
@@ -2210,15 +4450,31 @@
Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setDate(J)V
Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setPriority(I)V
Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;-><init>()V
+Lcom/google/android/mms/pdu/NotificationInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/NotificationInd;->getContentClass()I
Lcom/google/android/mms/pdu/NotificationInd;->getContentLocation()[B
+Lcom/google/android/mms/pdu/NotificationInd;->getDeliveryReport()I
Lcom/google/android/mms/pdu/NotificationInd;->getExpiry()J
Lcom/google/android/mms/pdu/NotificationInd;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
Lcom/google/android/mms/pdu/NotificationInd;->getMessageClass()[B
Lcom/google/android/mms/pdu/NotificationInd;->getMessageSize()J
Lcom/google/android/mms/pdu/NotificationInd;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue;
Lcom/google/android/mms/pdu/NotificationInd;->getTransactionId()[B
+Lcom/google/android/mms/pdu/NotificationInd;->setContentClass(I)V
Lcom/google/android/mms/pdu/NotificationInd;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/NotificationInd;->setDeliveryReport(I)V
+Lcom/google/android/mms/pdu/NotificationInd;->setExpiry(J)V
+Lcom/google/android/mms/pdu/NotificationInd;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;->setMessageClass([B)V
+Lcom/google/android/mms/pdu/NotificationInd;->setMessageSize(J)V
+Lcom/google/android/mms/pdu/NotificationInd;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;->setTransactionId([B)V
Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(I[BI)V
+Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/NotifyRespInd;->setReportAllowed(I)V
+Lcom/google/android/mms/pdu/NotifyRespInd;->setStatus(I)V
+Lcom/google/android/mms/pdu/NotifyRespInd;->setTransactionId([B)V
Lcom/google/android/mms/pdu/PduBody;-><init>()V
Lcom/google/android/mms/pdu/PduBody;->addPart(ILcom/google/android/mms/pdu/PduPart;)V
Lcom/google/android/mms/pdu/PduBody;->addPart(Lcom/google/android/mms/pdu/PduPart;)Z
@@ -2227,62 +4483,1114 @@
Lcom/google/android/mms/pdu/PduBody;->getPartByContentLocation(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
Lcom/google/android/mms/pdu/PduBody;->getPartByFileName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
Lcom/google/android/mms/pdu/PduBody;->getPartByName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartIndex(Lcom/google/android/mms/pdu/PduPart;)I
Lcom/google/android/mms/pdu/PduBody;->getPartsNum()I
+Lcom/google/android/mms/pdu/PduBody;->removePart(I)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->copy()V
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->mark()Lcom/google/android/mms/pdu/PduComposer$PositionMarker;
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->newbuf()V
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->pop()V
+Lcom/google/android/mms/pdu/PduComposer$PositionMarker;->getLength()I
Lcom/google/android/mms/pdu/PduComposer;-><init>(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendEncodedString(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendHeader(I)I
+Lcom/google/android/mms/pdu/PduComposer;->appendLongInteger(J)V
+Lcom/google/android/mms/pdu/PduComposer;->appendOctet(I)V
+Lcom/google/android/mms/pdu/PduComposer;->appendQuotedString(Ljava/lang/String;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendQuotedString([B)V
+Lcom/google/android/mms/pdu/PduComposer;->appendShortInteger(I)V
+Lcom/google/android/mms/pdu/PduComposer;->appendTextString(Ljava/lang/String;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendTextString([B)V
+Lcom/google/android/mms/pdu/PduComposer;->appendUintvarInteger(J)V
+Lcom/google/android/mms/pdu/PduComposer;->appendValueLength(J)V
+Lcom/google/android/mms/pdu/PduComposer;->arraycopy([BII)V
Lcom/google/android/mms/pdu/PduComposer;->make()[B
+Lcom/google/android/mms/pdu/PduComposer;->mContentTypeMap:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduComposer;->mMessage:Ljava/io/ByteArrayOutputStream;
+Lcom/google/android/mms/pdu/PduComposer;->mPdu:Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduComposer;->mPduHeader:Lcom/google/android/mms/pdu/PduHeaders;
+Lcom/google/android/mms/pdu/PduComposer;->mPosition:I
+Lcom/google/android/mms/pdu/PduComposer;->mResolver:Landroid/content/ContentResolver;
+Lcom/google/android/mms/pdu/PduComposer;->mStack:Lcom/google/android/mms/pdu/PduComposer$BufferStack;
+Lcom/google/android/mms/pdu/PduContentTypes;->contentTypes:[Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduHeaders;-><init>()V
+Lcom/google/android/mms/pdu/PduHeaders;->appendEncodedStringValue(Lcom/google/android/mms/pdu/EncodedStringValue;I)V
+Lcom/google/android/mms/pdu/PduHeaders;->getEncodedStringValue(I)Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/PduHeaders;->getEncodedStringValues(I)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/PduHeaders;->getLongInteger(I)J
+Lcom/google/android/mms/pdu/PduHeaders;->getOctet(I)I
+Lcom/google/android/mms/pdu/PduHeaders;->getTextString(I)[B
+Lcom/google/android/mms/pdu/PduHeaders;->setEncodedStringValue(Lcom/google/android/mms/pdu/EncodedStringValue;I)V
+Lcom/google/android/mms/pdu/PduHeaders;->setLongInteger(JI)V
+Lcom/google/android/mms/pdu/PduHeaders;->setOctet(II)V
+Lcom/google/android/mms/pdu/PduParser;->$assertionsDisabled:Z
+Lcom/google/android/mms/pdu/PduParser;-><init>([BZ)V
+Lcom/google/android/mms/pdu/PduParser;->checkPartPosition(Lcom/google/android/mms/pdu/PduPart;)I
+Lcom/google/android/mms/pdu/PduParser;->log(Ljava/lang/String;)V
Lcom/google/android/mms/pdu/PduParser;->parse()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduParser;->parseContentType(Ljava/io/ByteArrayInputStream;Ljava/util/HashMap;)[B
+Lcom/google/android/mms/pdu/PduParser;->parsePartHeaders(Ljava/io/ByteArrayInputStream;Lcom/google/android/mms/pdu/PduPart;I)Z
+Lcom/google/android/mms/pdu/PduParser;->parseShortInteger(Ljava/io/ByteArrayInputStream;)I
+Lcom/google/android/mms/pdu/PduParser;->parseUnsignedInt(Ljava/io/ByteArrayInputStream;)I
+Lcom/google/android/mms/pdu/PduParser;->parseValueLength(Ljava/io/ByteArrayInputStream;)I
+Lcom/google/android/mms/pdu/PduParser;->parseWapString(Ljava/io/ByteArrayInputStream;I)[B
Lcom/google/android/mms/pdu/PduPart;-><init>()V
Lcom/google/android/mms/pdu/PduPart;->generateLocation()Ljava/lang/String;
Lcom/google/android/mms/pdu/PduPart;->getCharset()I
+Lcom/google/android/mms/pdu/PduPart;->getContentDisposition()[B
+Lcom/google/android/mms/pdu/PduPart;->getContentId()[B
Lcom/google/android/mms/pdu/PduPart;->getContentLocation()[B
+Lcom/google/android/mms/pdu/PduPart;->getContentTransferEncoding()[B
Lcom/google/android/mms/pdu/PduPart;->getContentType()[B
Lcom/google/android/mms/pdu/PduPart;->getData()[B
+Lcom/google/android/mms/pdu/PduPart;->getDataLength()I
Lcom/google/android/mms/pdu/PduPart;->getDataUri()Landroid/net/Uri;
Lcom/google/android/mms/pdu/PduPart;->getFilename()[B
Lcom/google/android/mms/pdu/PduPart;->getName()[B
Lcom/google/android/mms/pdu/PduPart;->setCharset(I)V
+Lcom/google/android/mms/pdu/PduPart;->setContentDisposition([B)V
Lcom/google/android/mms/pdu/PduPart;->setContentId([B)V
Lcom/google/android/mms/pdu/PduPart;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/PduPart;->setContentTransferEncoding([B)V
Lcom/google/android/mms/pdu/PduPart;->setContentType([B)V
Lcom/google/android/mms/pdu/PduPart;->setData([B)V
Lcom/google/android/mms/pdu/PduPart;->setDataUri(Landroid/net/Uri;)V
+Lcom/google/android/mms/pdu/PduPart;->setFilename([B)V
+Lcom/google/android/mms/pdu/PduPart;->setName([B)V
+Lcom/google/android/mms/pdu/PduPersister;->ADDRESS_FIELDS:[I
+Lcom/google/android/mms/pdu/PduPersister;->CHARSET_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->ENCODED_STRING_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->getByteArrayFromPartColumn(Landroid/database/Cursor;I)[B
Lcom/google/android/mms/pdu/PduPersister;->getBytes(Ljava/lang/String;)[B
+Lcom/google/android/mms/pdu/PduPersister;->getIntegerFromPartColumn(Landroid/database/Cursor;I)Ljava/lang/Integer;
+Lcom/google/android/mms/pdu/PduPersister;->getPartContentType(Lcom/google/android/mms/pdu/PduPart;)Ljava/lang/String;
Lcom/google/android/mms/pdu/PduPersister;->getPduPersister(Landroid/content/Context;)Lcom/google/android/mms/pdu/PduPersister;
Lcom/google/android/mms/pdu/PduPersister;->getPendingMessages(J)Landroid/database/Cursor;
Lcom/google/android/mms/pdu/PduPersister;->load(Landroid/net/Uri;)Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduPersister;->loadRecipients(ILjava/util/HashSet;Ljava/util/HashMap;Z)V
+Lcom/google/android/mms/pdu/PduPersister;->LONG_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->mContentResolver:Landroid/content/ContentResolver;
+Lcom/google/android/mms/pdu/PduPersister;->mContext:Landroid/content/Context;
+Lcom/google/android/mms/pdu/PduPersister;->MESSAGE_BOX_MAP:Ljava/util/HashMap;
Lcom/google/android/mms/pdu/PduPersister;->move(Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->mTelephonyManager:Landroid/telephony/TelephonyManager;
+Lcom/google/android/mms/pdu/PduPersister;->OCTET_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->PART_PROJECTION:[Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPersister;->PDU_CACHE_INSTANCE:Lcom/google/android/mms/util/PduCache;
Lcom/google/android/mms/pdu/PduPersister;->persist(Lcom/google/android/mms/pdu/GenericPdu;Landroid/net/Uri;ZZLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->persistAddress(JI[Lcom/google/android/mms/pdu/EncodedStringValue;)V
Lcom/google/android/mms/pdu/PduPersister;->persistPart(Lcom/google/android/mms/pdu/PduPart;JLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->TEXT_STRING_COLUMN_NAME_MAP:Ljava/util/HashMap;
Lcom/google/android/mms/pdu/PduPersister;->toIsoString([B)Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPersister;->updateAddress(JI[Lcom/google/android/mms/pdu/EncodedStringValue;)V
Lcom/google/android/mms/pdu/PduPersister;->updateHeaders(Landroid/net/Uri;Lcom/google/android/mms/pdu/SendReq;)V
Lcom/google/android/mms/pdu/PduPersister;->updateParts(Landroid/net/Uri;Lcom/google/android/mms/pdu/PduBody;Ljava/util/HashMap;)V
+Lcom/google/android/mms/pdu/QuotedPrintable;->decodeQuotedPrintable([B)[B
+Lcom/google/android/mms/pdu/ReadOrigInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
Lcom/google/android/mms/pdu/ReadOrigInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/ReadOrigInd;->getReadStatus()I
Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/EncodedStringValue;[BII[Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/ReadRecInd;->getMessageId()[B
Lcom/google/android/mms/pdu/ReadRecInd;->setDate(J)V
+Lcom/google/android/mms/pdu/RetrieveConf;-><init>()V
+Lcom/google/android/mms/pdu/RetrieveConf;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->addCc(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->getCc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/RetrieveConf;->getContentType()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->getDeliveryReport()I
Lcom/google/android/mms/pdu/RetrieveConf;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/RetrieveConf;->getMessageClass()[B
Lcom/google/android/mms/pdu/RetrieveConf;->getMessageId()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->getReadReport()I
+Lcom/google/android/mms/pdu/RetrieveConf;->getRetrieveStatus()I
+Lcom/google/android/mms/pdu/RetrieveConf;->getRetrieveText()Lcom/google/android/mms/pdu/EncodedStringValue;
Lcom/google/android/mms/pdu/RetrieveConf;->getTransactionId()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->setContentType([B)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setDeliveryReport(I)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setMessageClass([B)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setMessageId([B)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setReadReport(I)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setRetrieveStatus(I)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setRetrieveText(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setTransactionId([B)V
+Lcom/google/android/mms/pdu/SendConf;-><init>()V
+Lcom/google/android/mms/pdu/SendConf;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
Lcom/google/android/mms/pdu/SendConf;->getMessageId()[B
Lcom/google/android/mms/pdu/SendConf;->getResponseStatus()I
Lcom/google/android/mms/pdu/SendConf;->getTransactionId()[B
Lcom/google/android/mms/pdu/SendReq;-><init>()V
+Lcom/google/android/mms/pdu/SendReq;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/SendReq;->addBcc(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->addCc(Lcom/google/android/mms/pdu/EncodedStringValue;)V
Lcom/google/android/mms/pdu/SendReq;->getBcc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/SendReq;->getCc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/SendReq;->getContentType()[B
+Lcom/google/android/mms/pdu/SendReq;->getDeliveryReport()I
+Lcom/google/android/mms/pdu/SendReq;->getExpiry()J
+Lcom/google/android/mms/pdu/SendReq;->getMessageClass()[B
+Lcom/google/android/mms/pdu/SendReq;->getMessageSize()J
+Lcom/google/android/mms/pdu/SendReq;->getReadReport()I
Lcom/google/android/mms/pdu/SendReq;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendReq;->setBcc([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->setCc([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->setContentType([B)V
Lcom/google/android/mms/pdu/SendReq;->setDeliveryReport(I)V
Lcom/google/android/mms/pdu/SendReq;->setExpiry(J)V
Lcom/google/android/mms/pdu/SendReq;->setMessageClass([B)V
Lcom/google/android/mms/pdu/SendReq;->setMessageSize(J)V
Lcom/google/android/mms/pdu/SendReq;->setReadReport(I)V
Lcom/google/android/mms/pdu/SendReq;->setTo([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->setTransactionId([B)V
+Lcom/google/android/mms/util/AbstractCache;-><init>()V
Lcom/google/android/mms/util/AbstractCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/google/android/mms/util/AbstractCache;->purge(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/google/android/mms/util/AbstractCache;->purgeAll()V
+Lcom/google/android/mms/util/AbstractCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Z
+Lcom/google/android/mms/util/DownloadDrmHelper;->isDrmConvertNeeded(Ljava/lang/String;)Z
+Lcom/google/android/mms/util/DownloadDrmHelper;->modifyDrmFwLockFileExtension(Ljava/lang/String;)Ljava/lang/String;
+Lcom/google/android/mms/util/DrmConvertSession;->close(Ljava/lang/String;)I
+Lcom/google/android/mms/util/DrmConvertSession;->convert([BI)[B
+Lcom/google/android/mms/util/DrmConvertSession;->open(Landroid/content/Context;Ljava/lang/String;)Lcom/google/android/mms/util/DrmConvertSession;
+Lcom/google/android/mms/util/PduCache;-><init>()V
Lcom/google/android/mms/util/PduCache;->getInstance()Lcom/google/android/mms/util/PduCache;
Lcom/google/android/mms/util/PduCache;->isUpdating(Landroid/net/Uri;)Z
Lcom/google/android/mms/util/PduCache;->purge(Landroid/net/Uri;)Lcom/google/android/mms/util/PduCacheEntry;
Lcom/google/android/mms/util/PduCache;->purgeAll()V
+Lcom/google/android/mms/util/PduCacheEntry;-><init>(Lcom/google/android/mms/pdu/GenericPdu;IJ)V
+Lcom/google/android/mms/util/PduCacheEntry;->getMessageBox()I
Lcom/google/android/mms/util/PduCacheEntry;->getPdu()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/util/PduCacheEntry;->getThreadId()J
+Lcom/google/android/mms/util/SqliteWrapper;->checkSQLiteException(Landroid/content/Context;Landroid/database/sqlite/SQLiteException;)V
+Lcom/google/android/mms/util/SqliteWrapper;->delete(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
+Lcom/google/android/mms/util/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
+Lcom/google/android/mms/util/SqliteWrapper;->requery(Landroid/content/Context;Landroid/database/Cursor;)Z
+Lcom/google/android/mms/util/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->ACRONYM:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->FLICKR:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->FORMAT:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->GOOGLE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->HTML:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->LINK:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->MUSIC:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->PHOTO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->SMILEY:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->YOUTUBE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/sun/nio/file/ExtendedWatchEventModifier;->FILE_TREE:Lcom/sun/nio/file/ExtendedWatchEventModifier;
+Lgov/nist/core/Debug;->printStackTrace(Ljava/lang/Exception;)V
+Lgov/nist/core/GenericObject;-><init>()V
+Lgov/nist/core/GenericObject;->dbgPrint()V
+Lgov/nist/core/GenericObject;->debugDump(I)Ljava/lang/String;
+Lgov/nist/core/GenericObject;->encode()Ljava/lang/String;
+Lgov/nist/core/GenericObject;->getMatcher()Lgov/nist/core/Match;
+Lgov/nist/core/GenericObject;->indentation:I
+Lgov/nist/core/GenericObject;->isMySubclass(Ljava/lang/Class;)Z
+Lgov/nist/core/GenericObject;->match(Ljava/lang/Object;)Z
+Lgov/nist/core/GenericObject;->matchExpression:Lgov/nist/core/Match;
+Lgov/nist/core/GenericObject;->merge(Ljava/lang/Object;)V
+Lgov/nist/core/GenericObject;->sprint(Ljava/lang/String;)V
+Lgov/nist/core/GenericObject;->stringRepresentation:Ljava/lang/String;
+Lgov/nist/core/GenericObjectList;-><init>()V
+Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;)V
+Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
+Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lgov/nist/core/GenericObjectList;->concatenate(Lgov/nist/core/GenericObjectList;)V
+Lgov/nist/core/GenericObjectList;->concatenate(Lgov/nist/core/GenericObjectList;Z)V
+Lgov/nist/core/GenericObjectList;->debugDump(I)Ljava/lang/String;
+Lgov/nist/core/GenericObjectList;->first()Lgov/nist/core/GenericObject;
+Lgov/nist/core/GenericObjectList;->getIndentation()Ljava/lang/String;
+Lgov/nist/core/GenericObjectList;->indentation:I
+Lgov/nist/core/GenericObjectList;->isMySubclass(Ljava/lang/Class;)Z
+Lgov/nist/core/GenericObjectList;->match(Ljava/lang/Object;)Z
+Lgov/nist/core/GenericObjectList;->myClass:Ljava/lang/Class;
+Lgov/nist/core/GenericObjectList;->next()Lgov/nist/core/GenericObject;
+Lgov/nist/core/GenericObjectList;->next(Ljava/util/ListIterator;)Lgov/nist/core/GenericObject;
+Lgov/nist/core/GenericObjectList;->setMyClass(Ljava/lang/Class;)V
+Lgov/nist/core/GenericObjectList;->stringRep:Ljava/lang/String;
+Lgov/nist/core/Host;-><init>()V
+Lgov/nist/core/Host;-><init>(Ljava/lang/String;)V
+Lgov/nist/core/Host;->encode()Ljava/lang/String;
+Lgov/nist/core/Host;->getAddress()Ljava/lang/String;
+Lgov/nist/core/Host;->getHostname()Ljava/lang/String;
+Lgov/nist/core/Host;->isIPv6Reference(Ljava/lang/String;)Z
+Lgov/nist/core/Host;->setAddress(Ljava/lang/String;)V
+Lgov/nist/core/Host;->setHostname(Ljava/lang/String;)V
+Lgov/nist/core/HostNameParser;-><init>(Lgov/nist/core/LexerCore;)V
+Lgov/nist/core/HostNameParser;-><init>(Ljava/lang/String;)V
+Lgov/nist/core/HostNameParser;->host()Lgov/nist/core/Host;
+Lgov/nist/core/HostNameParser;->hostPort(Z)Lgov/nist/core/HostPort;
+Lgov/nist/core/HostPort;-><init>()V
+Lgov/nist/core/HostPort;->encode()Ljava/lang/String;
+Lgov/nist/core/HostPort;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Lgov/nist/core/HostPort;->getHost()Lgov/nist/core/Host;
+Lgov/nist/core/HostPort;->getInetAddress()Ljava/net/InetAddress;
+Lgov/nist/core/HostPort;->getPort()I
+Lgov/nist/core/HostPort;->hasPort()Z
+Lgov/nist/core/HostPort;->removePort()V
+Lgov/nist/core/HostPort;->setHost(Lgov/nist/core/Host;)V
+Lgov/nist/core/HostPort;->setPort(I)V
+Lgov/nist/core/InternalErrorHandler;->handleException(Ljava/lang/Exception;)V
+Lgov/nist/core/InternalErrorHandler;->handleException(Ljava/lang/String;)V
+Lgov/nist/core/LexerCore;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lgov/nist/core/LexerCore;->byteStringNoSemicolon()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->byteStringNoSlash()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->charAsString(I)Ljava/lang/String;
+Lgov/nist/core/LexerCore;->comment()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->createParseException()Ljava/text/ParseException;
+Lgov/nist/core/LexerCore;->currentLexer:Ljava/util/Hashtable;
+Lgov/nist/core/LexerCore;->getBuffer()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->getNextId()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->getNextToken()Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->getPtr()I
+Lgov/nist/core/LexerCore;->getRest()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->getString(C)Ljava/lang/String;
+Lgov/nist/core/LexerCore;->isTokenChar(C)Z
+Lgov/nist/core/LexerCore;->lexerTables:Ljava/util/Hashtable;
+Lgov/nist/core/LexerCore;->markInputPosition()I
+Lgov/nist/core/LexerCore;->match(I)Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->number()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->peekNextToken()Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->peekNextToken(I)[Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->quotedString()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->rewindInputPosition(I)V
+Lgov/nist/core/LexerCore;->selectLexer(Ljava/lang/String;)V
+Lgov/nist/core/LexerCore;->SPorHT()V
+Lgov/nist/core/LexerCore;->startsId()Z
+Lgov/nist/core/LexerCore;->ttoken()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->ttokenSafe()Ljava/lang/String;
+Lgov/nist/core/Match;->match(Ljava/lang/String;)Z
+Lgov/nist/core/NameValue;-><init>()V
+Lgov/nist/core/NameValue;-><init>(Ljava/lang/String;Ljava/lang/Object;)V
+Lgov/nist/core/NameValue;-><init>(Ljava/lang/String;Ljava/lang/Object;Z)V
+Lgov/nist/core/NameValue;->encode()Ljava/lang/String;
+Lgov/nist/core/NameValue;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Lgov/nist/core/NameValue;->getName()Ljava/lang/String;
+Lgov/nist/core/NameValue;->getValueAsObject()Ljava/lang/Object;
+Lgov/nist/core/NameValue;->setName(Ljava/lang/String;)V
+Lgov/nist/core/NameValue;->setQuotedValue()V
+Lgov/nist/core/NameValue;->setSeparator(Ljava/lang/String;)V
+Lgov/nist/core/NameValue;->setValueAsObject(Ljava/lang/Object;)V
+Lgov/nist/core/NameValueList;-><init>()V
+Lgov/nist/core/NameValueList;-><init>(Z)V
+Lgov/nist/core/NameValueList;->delete(Ljava/lang/String;)Z
+Lgov/nist/core/NameValueList;->encode()Ljava/lang/String;
+Lgov/nist/core/NameValueList;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Lgov/nist/core/NameValueList;->getNames()Ljava/util/Iterator;
+Lgov/nist/core/NameValueList;->getNameValue(Ljava/lang/String;)Lgov/nist/core/NameValue;
+Lgov/nist/core/NameValueList;->getParameter(Ljava/lang/String;)Ljava/lang/String;
+Lgov/nist/core/NameValueList;->getValue(Ljava/lang/String;)Ljava/lang/Object;
+Lgov/nist/core/NameValueList;->hasNameValue(Ljava/lang/String;)Z
+Lgov/nist/core/NameValueList;->iterator()Ljava/util/Iterator;
+Lgov/nist/core/NameValueList;->set(Lgov/nist/core/NameValue;)V
+Lgov/nist/core/NameValueList;->set(Ljava/lang/String;Ljava/lang/Object;)V
+Lgov/nist/core/NameValueList;->setSeparator(Ljava/lang/String;)V
+Lgov/nist/core/net/DefaultNetworkLayer;->SINGLETON:Lgov/nist/core/net/DefaultNetworkLayer;
+Lgov/nist/core/net/NetworkLayer;->createDatagramSocket()Ljava/net/DatagramSocket;
+Lgov/nist/core/net/NetworkLayer;->createDatagramSocket(ILjava/net/InetAddress;)Ljava/net/DatagramSocket;
+Lgov/nist/core/net/NetworkLayer;->createServerSocket(IILjava/net/InetAddress;)Ljava/net/ServerSocket;
+Lgov/nist/core/net/NetworkLayer;->createSocket(Ljava/net/InetAddress;I)Ljava/net/Socket;
+Lgov/nist/core/net/NetworkLayer;->createSSLServerSocket(IILjava/net/InetAddress;)Ljavax/net/ssl/SSLServerSocket;
+Lgov/nist/core/net/NetworkLayer;->createSSLSocket(Ljava/net/InetAddress;I)Ljavax/net/ssl/SSLSocket;
+Lgov/nist/core/ParserCore;-><init>()V
+Lgov/nist/core/ParserCore;->lexer:Lgov/nist/core/LexerCore;
+Lgov/nist/core/StringTokenizer;->ptr:I
+Lgov/nist/core/ThreadAuditor$ThreadHandle;->getPingIntervalInMillisecs()J
+Lgov/nist/core/ThreadAuditor$ThreadHandle;->ping()V
+Lgov/nist/core/ThreadAuditor;-><init>()V
+Lgov/nist/core/ThreadAuditor;->addCurrentThread()Lgov/nist/core/ThreadAuditor$ThreadHandle;
+Lgov/nist/core/ThreadAuditor;->getPingIntervalInMillisecs()J
+Lgov/nist/core/ThreadAuditor;->isEnabled()Z
+Lgov/nist/core/ThreadAuditor;->setPingIntervalInMillisecs(J)V
+Lgov/nist/core/Token;-><init>()V
+Lgov/nist/core/Token;->getTokenType()I
+Lgov/nist/core/Token;->getTokenValue()Ljava/lang/String;
+Lgov/nist/javax/sip/address/GenericURI;-><init>()V
+Lgov/nist/javax/sip/address/GenericURI;->encode()Ljava/lang/String;
+Lgov/nist/javax/sip/address/GenericURI;->getScheme()Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->getHost()Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->getParameter(Ljava/lang/String;)Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->getPort()I
+Lgov/nist/javax/sip/address/SipUri;->getUser()Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->removeParameter(Ljava/lang/String;)V
+Lgov/nist/javax/sip/address/SipUri;->setParameter(Ljava/lang/String;Ljava/lang/String;)V
+Lgov/nist/javax/sip/address/SipUri;->setUserParam(Ljava/lang/String;)V
+Lgov/nist/javax/sip/parser/URLParser;-><init>(Ljava/lang/String;)V
+Lgov/nist/javax/sip/parser/URLParser;->sipURL(Z)Lgov/nist/javax/sip/address/SipUri;
+Ljava/lang/DexCache;->dexFile:J
+Ljava/lang/invoke/SerializedLambda;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
+Ljava/lang/invoke/SerializedLambda;->getCapturedArg(I)Ljava/lang/Object;
+Ljava/lang/invoke/SerializedLambda;->getCapturedArgCount()I
+Ljava/lang/invoke/SerializedLambda;->getCapturingClass()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceClass()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceMethodName()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceMethodSignature()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getImplClass()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getImplMethodKind()I
+Ljava/lang/invoke/SerializedLambda;->getImplMethodName()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getImplMethodSignature()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getInstantiatedMethodType()Ljava/lang/String;
+Ljava/lang/UNIXProcess;->pid:I
+Ljava/net/AddressCache$AddressCacheEntry;-><init>(Ljava/lang/Object;)V
+Ljava/net/AddressCache$AddressCacheEntry;->expiryNanos:J
+Ljava/net/AddressCache$AddressCacheEntry;->value:Ljava/lang/Object;
+Ljava/net/AddressCache$AddressCacheKey;->mHostname:Ljava/lang/String;
+Ljava/net/AddressCache;->cache:Llibcore/util/BasicLruCache;
+Ljava/net/Inet6AddressImpl;->addressCache:Ljava/net/AddressCache;
+Ljava/net/PlainSocketImpl;-><init>()V
+Ljava/nio/DirectByteBuffer;->cleaner()Lsun/misc/Cleaner;
+Ljava/nio/file/FileTreeWalker;->followLinks:Z
+Ljava/nio/file/FileTreeWalker;->linkOptions:[Ljava/nio/file/LinkOption;
+Ljava/nio/file/FileTreeWalker;->maxDepth:I
+Ljava/util/zip/ZipFile$ZipEntryIterator;->nextElement()Ljava/util/zip/ZipEntry;
+Ljunit/framework/TestCase;->fName:Ljava/lang/String;
+Ljunit/framework/TestSuite;->isPublicTestMethod(Ljava/lang/reflect/Method;)Z
+Ljunit/framework/TestSuite;->isTestMethod(Ljava/lang/reflect/Method;)Z
+Llibcore/icu/DateIntervalFormat;->formatDateRange(JJILjava/lang/String;)Ljava/lang/String;
+Llibcore/icu/ICU;->CACHED_PATTERNS:Llibcore/util/BasicLruCache;
+Llibcore/icu/ICU;->getBestDateTimePattern(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String;
+Llibcore/icu/ICU;->getBestDateTimePatternNative(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Llibcore/icu/ICU;->getDateFormatOrder(Ljava/lang/String;)[C
+Llibcore/icu/LocaleData;->firstDayOfWeek:Ljava/lang/Integer;
+Llibcore/icu/LocaleData;->get(Ljava/util/Locale;)Llibcore/icu/LocaleData;
+Llibcore/icu/LocaleData;->longStandAloneWeekdayNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->mapInvalidAndNullLocales(Ljava/util/Locale;)Ljava/util/Locale;
+Llibcore/icu/LocaleData;->minimalDaysInFirstWeek:Ljava/lang/Integer;
+Llibcore/icu/LocaleData;->shortMonthNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->shortStandAloneMonthNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->shortStandAloneWeekdayNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->timeFormat_Hm:Ljava/lang/String;
+Llibcore/icu/LocaleData;->timeFormat_hm:Ljava/lang/String;
+Llibcore/icu/LocaleData;->today:Ljava/lang/String;
+Llibcore/icu/LocaleData;->tomorrow:Ljava/lang/String;
+Llibcore/icu/LocaleData;->zeroDigit:C
+Llibcore/icu/TimeZoneNames;->forLocale(Ljava/util/Locale;)[Ljava/lang/String;
+Llibcore/io/AsynchronousCloseMonitor;->signalBlockedThreads(Ljava/io/FileDescriptor;)V
+Llibcore/io/BlockGuardOs;-><init>(Llibcore/io/Os;)V
+Llibcore/io/BlockGuardOs;->chmod(Ljava/lang/String;I)V
+Llibcore/io/BlockGuardOs;->chown(Ljava/lang/String;II)V
+Llibcore/io/BlockGuardOs;->close(Ljava/io/FileDescriptor;)V
+Llibcore/io/BlockGuardOs;->fchmod(Ljava/io/FileDescriptor;I)V
+Llibcore/io/BlockGuardOs;->fchown(Ljava/io/FileDescriptor;II)V
+Llibcore/io/BlockGuardOs;->fdatasync(Ljava/io/FileDescriptor;)V
+Llibcore/io/BlockGuardOs;->fstat(Ljava/io/FileDescriptor;)Landroid/system/StructStat;
+Llibcore/io/BlockGuardOs;->fstatvfs(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;
+Llibcore/io/BlockGuardOs;->lchown(Ljava/lang/String;II)V
+Llibcore/io/BlockGuardOs;->link(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->lseek(Ljava/io/FileDescriptor;JI)J
+Llibcore/io/BlockGuardOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/BlockGuardOs;->mkdir(Ljava/lang/String;I)V
+Llibcore/io/BlockGuardOs;->mkfifo(Ljava/lang/String;I)V
+Llibcore/io/BlockGuardOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;
+Llibcore/io/BlockGuardOs;->posix_fallocate(Ljava/io/FileDescriptor;JJ)V
+Llibcore/io/BlockGuardOs;->pread(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;J)I
+Llibcore/io/BlockGuardOs;->pread(Ljava/io/FileDescriptor;[BIIJ)I
+Llibcore/io/BlockGuardOs;->pwrite(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;J)I
+Llibcore/io/BlockGuardOs;->pwrite(Ljava/io/FileDescriptor;[BIIJ)I
+Llibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
+Llibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;[BII)I
+Llibcore/io/BlockGuardOs;->readlink(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/BlockGuardOs;->readv(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I
+Llibcore/io/BlockGuardOs;->realpath(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/BlockGuardOs;->remove(Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/BlockGuardOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;
+Llibcore/io/BlockGuardOs;->symlink(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
+Llibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;[BII)I
+Llibcore/io/BlockGuardOs;->writev(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I
+Llibcore/io/BufferIterator;->readByte()B
+Llibcore/io/BufferIterator;->readByteArray([BII)V
+Llibcore/io/BufferIterator;->readInt()I
+Llibcore/io/BufferIterator;->readIntArray([III)V
+Llibcore/io/BufferIterator;->seek(I)V
+Llibcore/io/BufferIterator;->skip(I)V
+Llibcore/io/DropBox;->addText(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;-><init>(Llibcore/io/Os;)V
+Llibcore/io/ForwardingOs;->access(Ljava/lang/String;I)Z
+Llibcore/io/ForwardingOs;->chmod(Ljava/lang/String;I)V
+Llibcore/io/ForwardingOs;->chown(Ljava/lang/String;II)V
+Llibcore/io/ForwardingOs;->getenv(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/ForwardingOs;->lchown(Ljava/lang/String;II)V
+Llibcore/io/ForwardingOs;->link(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/ForwardingOs;->mkdir(Ljava/lang/String;I)V
+Llibcore/io/ForwardingOs;->mkfifo(Ljava/lang/String;I)V
+Llibcore/io/ForwardingOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;
+Llibcore/io/ForwardingOs;->os:Llibcore/io/Os;
+Llibcore/io/ForwardingOs;->readlink(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/ForwardingOs;->remove(Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->removexattr(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->setenv(Ljava/lang/String;Ljava/lang/String;Z)V
+Llibcore/io/ForwardingOs;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
+Llibcore/io/ForwardingOs;->setxattr(Ljava/lang/String;Ljava/lang/String;[BI)V
+Llibcore/io/ForwardingOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/ForwardingOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;
+Llibcore/io/ForwardingOs;->symlink(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->sysconf(I)J
+Llibcore/io/ForwardingOs;->unlink(Ljava/lang/String;)V
+Llibcore/io/IoBridge;->isConnected(Ljava/io/FileDescriptor;Ljava/net/InetAddress;III)Z
+Llibcore/io/IoUtils;->closeQuietly(Ljava/io/FileDescriptor;)V
+Llibcore/io/IoUtils;->closeQuietly(Ljava/lang/AutoCloseable;)V
+Llibcore/io/IoUtils;->closeQuietly(Ljava/net/Socket;)V
+Llibcore/io/IoUtils;->readFileAsByteArray(Ljava/lang/String;)[B
+Llibcore/io/IoUtils;->readFileAsString(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/IoUtils;->setBlocking(Ljava/io/FileDescriptor;Z)V
+Llibcore/io/MemoryMappedFile;->bigEndianIterator()Llibcore/io/BufferIterator;
+Llibcore/io/MemoryMappedFile;->mmapRO(Ljava/lang/String;)Llibcore/io/MemoryMappedFile;
+Llibcore/io/Os;->chmod(Ljava/lang/String;I)V
+Llibcore/io/Os;->close(Ljava/io/FileDescriptor;)V
+Llibcore/io/Os;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V
+Llibcore/io/Os;->gai_strerror(I)Ljava/lang/String;
+Llibcore/io/Os;->remove(Ljava/lang/String;)V
+Llibcore/io/Os;->setenv(Ljava/lang/String;Ljava/lang/String;Z)V
+Llibcore/io/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
+Llibcore/io/Os;->stat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/Os;->strerror(I)Ljava/lang/String;
+Llibcore/io/Os;->sysconf(I)J
+Llibcore/io/Streams;->readAsciiLine(Ljava/io/InputStream;)Ljava/lang/String;
+Llibcore/io/Streams;->readFully(Ljava/io/InputStream;)[B
+Llibcore/io/Streams;->readFully(Ljava/io/InputStream;[B)V
+Llibcore/io/Streams;->readSingleByte(Ljava/io/InputStream;)I
+Llibcore/io/Streams;->skipAll(Ljava/io/InputStream;)V
+Llibcore/io/Streams;->writeSingleByte(Ljava/io/OutputStream;I)V
+Llibcore/net/event/NetworkEventDispatcher;->addListener(Llibcore/net/event/NetworkEventListener;)V
+Llibcore/net/event/NetworkEventDispatcher;->getInstance()Llibcore/net/event/NetworkEventDispatcher;
+Llibcore/net/event/NetworkEventListener;-><init>()V
+Llibcore/net/http/HttpDate;->format(Ljava/util/Date;)Ljava/lang/String;
+Llibcore/net/http/HttpDate;->parse(Ljava/lang/String;)Ljava/util/Date;
+Llibcore/net/MimeUtils;->guessExtensionFromMimeType(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/net/MimeUtils;->guessMimeTypeFromExtension(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/net/NetworkSecurityPolicy;->isCleartextTrafficPermitted()Z
+Llibcore/util/BasicLruCache;-><init>(I)V
+Llibcore/util/BasicLruCache;->evictAll()V
+Llibcore/util/BasicLruCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Llibcore/util/BasicLruCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Llibcore/util/EmptyArray;->BYTE:[B
+Llibcore/util/EmptyArray;->INT:[I
+Llibcore/util/EmptyArray;->OBJECT:[Ljava/lang/Object;
+Llibcore/util/ZoneInfoDB$TzData;-><init>()V
+Lorg/apache/harmony/dalvik/ddmc/Chunk;-><init>(ILjava/nio/ByteBuffer;)V
+Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;->CHUNK_ORDER:Ljava/nio/ByteOrder;
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;->broadcast(I)V
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;->sendChunk(Lorg/apache/harmony/dalvik/ddmc/Chunk;)V
+Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;->getThreadStats()[B
+Lorg/apache/harmony/xml/dom/ElementImpl;->localName:Ljava/lang/String;
+Lorg/apache/harmony/xml/ExpatAttributes;-><init>()V
+Lorg/apache/harmony/xml/ExpatParser$EntityParser;->depth:I
+Lorg/apache/harmony/xml/ExpatParser;-><init>(Ljava/lang/String;Lorg/apache/harmony/xml/ExpatReader;ZLjava/lang/String;Ljava/lang/String;)V
+Lorg/apache/harmony/xml/ExpatParser;->append([BII)V
+Lorg/apache/harmony/xml/ExpatParser;->append([CII)V
+Lorg/apache/harmony/xml/ExpatParser;->attributes:Lorg/apache/harmony/xml/ExpatAttributes;
+Lorg/apache/harmony/xml/ExpatParser;->cloneAttributes()Lorg/xml/sax/Attributes;
+Lorg/apache/harmony/xml/ExpatParser;->finish()V
+Lorg/apache/harmony/xml/ExpatParser;->xmlReader:Lorg/apache/harmony/xml/ExpatReader;
+Lorg/apache/harmony/xml/ExpatReader;-><init>()V
+Lorg/apache/harmony/xml/ExpatReader;->contentHandler:Lorg/xml/sax/ContentHandler;
+Lorg/apache/xalan/extensions/ExpressionContext;->getContextNode()Lorg/w3c/dom/Node;
+Lorg/apache/xalan/extensions/ExpressionContext;->getErrorListener()Ljavax/xml/transform/ErrorListener;
+Lorg/apache/xalan/extensions/ExpressionContext;->getVariableOrParam(Lorg/apache/xml/utils/QName;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xalan/extensions/ExpressionContext;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xalan/extensions/ExtensionHandler;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xalan/extensions/ExtensionHandler;->callFunction(Ljava/lang/String;Ljava/util/Vector;Ljava/lang/Object;Lorg/apache/xalan/extensions/ExpressionContext;)Ljava/lang/Object;
+Lorg/apache/xalan/extensions/ExtensionHandler;->getClassForName(Ljava/lang/String;)Ljava/lang/Class;
+Lorg/apache/xalan/extensions/ObjectFactory$ConfigurationError;-><init>(Ljava/lang/String;Ljava/lang/Exception;)V
+Lorg/apache/xalan/extensions/ObjectFactory;->findClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xalan/extensions/ObjectFactory;->findProviderClass(Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/lang/Class;
+Lorg/apache/xalan/processor/TransformerFactoryImpl;-><init>()V
+Lorg/apache/xalan/res/XSLMessages;->createMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
+Lorg/apache/xalan/res/XSLTErrorResources;-><init>()V
+Lorg/apache/xalan/serialize/SerializerUtils;->outputResultTreeFragment(Lorg/apache/xml/serializer/SerializationHandler;Lorg/apache/xpath/objects/XObject;Lorg/apache/xpath/XPathContext;)V
+Lorg/apache/xalan/templates/AVT;->evaluate(Lorg/apache/xpath/XPathContext;ILorg/apache/xml/utils/PrefixResolver;)Ljava/lang/String;
+Lorg/apache/xalan/templates/ElemElement;->execute(Lorg/apache/xalan/transformer/TransformerImpl;)V
+Lorg/apache/xalan/templates/ElemExsltFunction;->execute(Lorg/apache/xalan/transformer/TransformerImpl;[Lorg/apache/xpath/objects/XObject;)V
+Lorg/apache/xalan/templates/ElemExtensionCall;->getAttribute(Ljava/lang/String;Lorg/w3c/dom/Node;Lorg/apache/xalan/transformer/TransformerImpl;)Ljava/lang/String;
+Lorg/apache/xalan/templates/ElemLiteralResult;->getLiteralResultAttribute(Ljava/lang/String;)Lorg/apache/xalan/templates/AVT;
+Lorg/apache/xalan/templates/ElemTemplate;->getMatch()Lorg/apache/xpath/XPath;
+Lorg/apache/xalan/templates/ElemTemplate;->getName()Lorg/apache/xml/utils/QName;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getFirstChildElem()Lorg/apache/xalan/templates/ElemTemplateElement;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getNextSiblingElem()Lorg/apache/xalan/templates/ElemTemplateElement;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getParentElem()Lorg/apache/xalan/templates/ElemTemplateElement;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getStylesheetRoot()Lorg/apache/xalan/templates/StylesheetRoot;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getXSLToken()I
+Lorg/apache/xalan/templates/ElemTextLiteral;->getChars()[C
+Lorg/apache/xalan/templates/KeyDeclaration;->getName()Lorg/apache/xml/utils/QName;
+Lorg/apache/xalan/templates/KeyDeclaration;->getUse()Lorg/apache/xpath/XPath;
+Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultRootRule()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultRule()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultTextRule()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/templates/StylesheetRoot;->getTemplateComposed(Lorg/apache/xml/utils/QName;)Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/transformer/ClonerToResultTree;->cloneToResultTree(IILorg/apache/xml/dtm/DTM;Lorg/apache/xml/serializer/SerializationHandler;Z)V
+Lorg/apache/xalan/transformer/DecimalToRoman;-><init>(JLjava/lang/String;JLjava/lang/String;)V
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_postLetter:Ljava/lang/String;
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_postValue:J
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_preLetter:Ljava/lang/String;
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_preValue:J
+Lorg/apache/xalan/transformer/MsgMgr;->error(Ljavax/xml/transform/SourceLocator;Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;Ljava/lang/String;)V
+Lorg/apache/xalan/transformer/TransformerImpl;->createSerializationHandler(Ljavax/xml/transform/Result;Lorg/apache/xalan/templates/OutputProperties;)Lorg/apache/xml/serializer/SerializationHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->executeChildTemplates(Lorg/apache/xalan/templates/ElemTemplateElement;Lorg/w3c/dom/Node;Lorg/apache/xml/utils/QName;Lorg/xml/sax/ContentHandler;)V
+Lorg/apache/xalan/transformer/TransformerImpl;->executeChildTemplates(Lorg/apache/xalan/templates/ElemTemplateElement;Z)V
+Lorg/apache/xalan/transformer/TransformerImpl;->getCountersTable()Lorg/apache/xalan/transformer/CountersTable;
+Lorg/apache/xalan/transformer/TransformerImpl;->getCurrentTemplateElements()Lorg/apache/xml/utils/ObjectStack;
+Lorg/apache/xalan/transformer/TransformerImpl;->getCurrentTemplateElementsCount()I
+Lorg/apache/xalan/transformer/TransformerImpl;->getMatchedNode()I
+Lorg/apache/xalan/transformer/TransformerImpl;->getMatchedTemplate()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/transformer/TransformerImpl;->getMode()Lorg/apache/xml/utils/QName;
+Lorg/apache/xalan/transformer/TransformerImpl;->getMsgMgr()Lorg/apache/xalan/transformer/MsgMgr;
+Lorg/apache/xalan/transformer/TransformerImpl;->getOutputFormat()Lorg/apache/xalan/templates/OutputProperties;
+Lorg/apache/xalan/transformer/TransformerImpl;->getResultTreeHandler()Lorg/apache/xml/serializer/SerializationHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->getSerializationHandler()Lorg/apache/xml/serializer/SerializationHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_attrSetStack:Ljava/util/Stack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentMatchedNodes:Lorg/apache/xml/utils/NodeVector;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentMatchTemplates:Ljava/util/Stack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentTemplateElements:Lorg/apache/xml/utils/ObjectStack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentTemplateRuleIsNull:Lorg/apache/xml/utils/BoolStack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_inputContentHandler:Lorg/xml/sax/ContentHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_outputTarget:Ljavax/xml/transform/Result;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_stringWriterObjectPool:Lorg/apache/xml/utils/ObjectPool;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_urlOfSource:Ljava/lang/String;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_xcontext:Lorg/apache/xpath/XPathContext;
+Lorg/apache/xalan/transformer/TransformerImpl;->popCurrentFuncResult()Ljava/lang/Object;
+Lorg/apache/xalan/transformer/TransformerImpl;->pushCurrentFuncResult(Ljava/lang/Object;)V
+Lorg/apache/xalan/transformer/TransformerImpl;->pushElemTemplateElement(Lorg/apache/xalan/templates/ElemTemplateElement;)V
+Lorg/apache/xalan/Version;->getVersion()Ljava/lang/String;
+Lorg/apache/xalan/xslt/EnvironmentCheck;-><init>()V
+Lorg/apache/xalan/xslt/EnvironmentCheck;->appendEnvironmentReport(Lorg/w3c/dom/Node;Lorg/w3c/dom/Document;Ljava/util/Hashtable;)V
+Lorg/apache/xalan/xslt/EnvironmentCheck;->getEnvironmentHash()Ljava/util/Hashtable;
+Lorg/apache/xalan/xslt/ObjectFactory;->findClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xalan/xslt/ObjectFactory;->newInstance(Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/lang/Object;
+Lorg/apache/xml/dtm/Axis;->getNames(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/Axis;->isReverse(I)Z
+Lorg/apache/xml/dtm/DTM;->getDocument()I
+Lorg/apache/xml/dtm/DTM;->getDocumentRoot(I)I
+Lorg/apache/xml/dtm/DTM;->getFirstChild(I)I
+Lorg/apache/xml/dtm/DTM;->getNextSibling(I)I
+Lorg/apache/xml/dtm/DTM;->getNode(I)Lorg/w3c/dom/Node;
+Lorg/apache/xml/dtm/DTM;->getNodeName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/DTM;->getNodeType(I)S
+Lorg/apache/xml/dtm/DTM;->getParent(I)I
+Lorg/apache/xml/dtm/DTM;->getSourceLocatorFor(I)Ljavax/xml/transform/SourceLocator;
+Lorg/apache/xml/dtm/DTM;->getStringValue(I)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/dtm/DTM;->migrateTo(Lorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xml/dtm/DTMAxisIterator;->cloneIterator()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/DTMAxisIterator;->getLast()I
+Lorg/apache/xml/dtm/DTMAxisIterator;->getNodeByPosition(I)I
+Lorg/apache/xml/dtm/DTMAxisIterator;->getPosition()I
+Lorg/apache/xml/dtm/DTMAxisIterator;->gotoMark()V
+Lorg/apache/xml/dtm/DTMAxisIterator;->isReverse()Z
+Lorg/apache/xml/dtm/DTMAxisIterator;->next()I
+Lorg/apache/xml/dtm/DTMAxisIterator;->reset()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/DTMAxisIterator;->setMark()V
+Lorg/apache/xml/dtm/DTMAxisIterator;->setRestartable(Z)V
+Lorg/apache/xml/dtm/DTMAxisIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/DTMException;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/DTMFilter;->acceptNode(II)S
+Lorg/apache/xml/dtm/DTMIterator;->cloneWithReset()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xml/dtm/DTMIterator;->getCurrentPos()I
+Lorg/apache/xml/dtm/DTMIterator;->getDTM(I)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xml/dtm/DTMIterator;->nextNode()I
+Lorg/apache/xml/dtm/DTMIterator;->runTo(I)V
+Lorg/apache/xml/dtm/DTMIterator;->setCurrentPos(I)V
+Lorg/apache/xml/dtm/DTMIterator;->setRoot(ILjava/lang/Object;)V
+Lorg/apache/xml/dtm/DTMIterator;->setShouldCacheNodes(Z)V
+Lorg/apache/xml/dtm/DTMManager;->getDTM(Ljavax/xml/transform/Source;ZLorg/apache/xml/dtm/DTMWSFilter;ZZ)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xml/dtm/DTMManager;->getXMLStringFactory()Lorg/apache/xml/utils/XMLStringFactory;
+Lorg/apache/xml/dtm/DTMManager;->release(Lorg/apache/xml/dtm/DTM;Z)Z
+Lorg/apache/xml/dtm/ref/CoroutineManager;-><init>()V
+Lorg/apache/xml/dtm/ref/CoroutineManager;->co_joinCoroutineSet(I)I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;-><init>()V
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->includeSelf()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->reset()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->resetPosition()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->returnNode(I)I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->setRestartable(Z)V
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_includeSelf:Z
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_isRestartable:Z
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_last:I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_markedNode:I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_position:I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_startNode:I
+Lorg/apache/xml/dtm/ref/DTMAxisIterNodeList;-><init>(Lorg/apache/xml/dtm/DTM;Lorg/apache/xml/dtm/DTMAxisIterator;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->appendChild(IZZ)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->appendTextChild(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->declareNamespaceInContext(II)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->documentRegistration()V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->documentRelease()V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->ensureSizeOfIndex(II)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->error(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findGTE([IIII)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findInSortedSuballocatedIntVector(Lorg/apache/xml/utils/SuballocatedIntVector;I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findNamespaceContext(I)Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocument()I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentAllDeclarationsProcessed()Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentBaseURI()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentEncoding(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentRoot(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentStandalone(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentSystemIdentifier(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentVersion(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDTMIDs()Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getExpandedTypeID(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getFirstChild(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getFirstNamespaceNode(IZ)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLastChild(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLevel(I)S
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLocalNameFromExpandedNameID(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getManager()Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNamespaceFromExpandedNameID(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNamespaceType(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextAttribute(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextNamespaceNode(IIZ)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextSibling(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNode(I)Lorg/w3c/dom/Node;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeHandle(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeIdent(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeType(I)S
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getOwnerDocument(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getParent(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getPreviousSibling(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getShouldStripWhitespace()Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getStringValueChunk(II[I)[C
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getStringValueChunkCount(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->hasChildNodes(I)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->indexNode(II)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isCharacterElementContentWhitespace(I)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isDocumentAllDeclarationsProcessed(I)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isNodeAfter(II)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isSupported(Ljava/lang/String;Ljava/lang/String;)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->makeNodeHandle(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->makeNodeIdentity(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_expandedNameTable:Lorg/apache/xml/dtm/ref/ExpandedNameTable;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_exptype:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_firstch:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_nextsib:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_parent:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_prevsib:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_size:I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_wsfilter:Lorg/apache/xml/dtm/DTMWSFilter;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_xstrf:Lorg/apache/xml/utils/XMLStringFactory;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->popShouldStripWhitespace()V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->pushShouldStripWhitespace(Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setDocumentBaseURI(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setFeature(Ljava/lang/String;Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setShouldStripWhitespace(Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->supportsPreStripping()Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_exptype(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_firstch(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_level(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_nextsib(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_parent(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_prevsib(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_type(I)S
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$InternalAxisIteratorBase;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$InternalAxisIteratorBase;->_currentNode:I
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;->next()I
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NthDescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;I)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$SingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$SingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;I)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;-><init>(Lorg/apache/xml/dtm/DTMManager;Ljavax/xml/transform/Source;ILorg/apache/xml/dtm/DTMWSFilter;Lorg/apache/xml/utils/XMLStringFactory;Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;->getAxisIterator(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;->getTypedAxisIterator(II)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseTraversers;->getAxisTraverser(I)Lorg/apache/xml/dtm/DTMAxisTraverser;
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;-><init>()V
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->addDTM(Lorg/apache/xml/dtm/DTM;I)V
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->addDTM(Lorg/apache/xml/dtm/DTM;II)V
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->getFirstFreeDTMID()I
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->getXMLReader(Ljavax/xml/transform/Source;)Lorg/xml/sax/XMLReader;
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->releaseXMLReader(Lorg/xml/sax/XMLReader;)V
+Lorg/apache/xml/dtm/ref/DTMNodeIterator;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xml/dtm/ref/DTMNodeIterator;->getDTMIterator()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xml/dtm/ref/DTMNodeIterator;->getRoot()Lorg/w3c/dom/Node;
+Lorg/apache/xml/dtm/ref/DTMNodeList;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;-><init>(Lorg/apache/xml/dtm/DTM;I)V
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getDTM()Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getDTMNodeNumber()I
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getStringValue()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMStringPool;-><init>()V
+Lorg/apache/xml/dtm/ref/DTMStringPool;->indexToString(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMStringPool;->m_intToString:Ljava/util/Vector;
+Lorg/apache/xml/dtm/ref/DTMStringPool;->removeAllElements()V
+Lorg/apache/xml/dtm/ref/DTMStringPool;->stringToIndex(Ljava/lang/String;)I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;I)I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;IZ)I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getLocalName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getSize()I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getType(I)S
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->deliverMoreNodes(Z)Ljava/lang/Object;
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->setContentHandler(Lorg/xml/sax/ContentHandler;)V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->setLexicalHandler(Lorg/xml/sax/ext/LexicalHandler;)V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->startParse(Lorg/xml/sax/InputSource;)V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource_Filter;-><init>()V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource_Filter;->setXMLReader(Lorg/xml/sax/XMLReader;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;->next()I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AttributeIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ChildrenIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ChildrenIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$DescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$FollowingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$FollowingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ParentIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ParentIterator;->setNodeType(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$PrecedingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$PrecedingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedAncestorIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedAttributeIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedChildrenIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedDescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedFollowingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedFollowingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedPrecedingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedPrecedingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedSingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;-><init>(Lorg/apache/xml/dtm/DTMManager;Ljavax/xml/transform/Source;ILorg/apache/xml/dtm/DTMWSFilter;Lorg/apache/xml/utils/XMLStringFactory;ZIZZZ)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyAttribute(IILorg/apache/xml/serializer/SerializationHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyAttributes(ILorg/apache/xml/serializer/SerializationHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyElement(IILorg/apache/xml/serializer/SerializationHandler;)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyNS(ILorg/apache/xml/serializer/SerializationHandler;Z)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyTextNode(ILorg/apache/xml/serializer/SerializationHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->dispatchCharactersEvents(ILorg/xml/sax/ContentHandler;Z)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getFirstAttribute(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getIdForNamespace(Ljava/lang/String;)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getLocalName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeNameX(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeValue(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValue()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValue(I)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValueX(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->m_buildIdIndex:Z
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_exptype2(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_exptype2Type(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_firstch2(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_nextsib2(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->dispatchToEvents(ILorg/xml/sax/ContentHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getAttributeNode(ILjava/lang/String;Ljava/lang/String;)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getContentHandler()Lorg/xml/sax/ContentHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDeclHandler()Lorg/xml/sax/ext/DeclHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDocumentTypeDeclarationPublicIdentifier()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDocumentTypeDeclarationSystemIdentifier()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDTDHandler()Lorg/xml/sax/DTDHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getEntityResolver()Lorg/xml/sax/EntityResolver;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getErrorHandler()Lorg/xml/sax/ErrorHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getLexicalHandler()Lorg/xml/sax/ext/LexicalHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getNamespaceURI(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getNumberOfNodes()I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getPrefix(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getSourceLocatorFor(I)Ljavax/xml/transform/SourceLocator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getUnparsedEntityURI(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->isAttributeSpecified(I)Z
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->migrateTo(Lorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_idAttributes:Ljava/util/Hashtable;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_parents:Lorg/apache/xml/utils/IntStack;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_previous:I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->needsTwoThreads()Z
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->setProperty(Ljava/lang/String;Ljava/lang/Object;)V
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getContextClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getFileExists(Ljava/io/File;)Z
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getFileInputStream(Ljava/io/File;)Ljava/io/FileInputStream;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getInstance()Lorg/apache/xml/dtm/ref/SecuritySupport;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getLastModified(Ljava/io/File;)J
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getParentClassLoader(Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getResourceAsStream(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/io/InputStream;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getSystemClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getSystemProperty(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/res/XMLErrorResources;-><init>()V
+Lorg/apache/xml/res/XMLMessages;->createXMLMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
+Lorg/apache/xml/serializer/CharInfo$CharKey;-><init>(C)V
+Lorg/apache/xml/serializer/CharInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V
+Lorg/apache/xml/serializer/CharInfo;->get(I)Z
+Lorg/apache/xml/serializer/CharInfo;->getCharInfo(Ljava/lang/String;Ljava/lang/String;)Lorg/apache/xml/serializer/CharInfo;
+Lorg/apache/xml/serializer/CharInfo;->set(I)V
+Lorg/apache/xml/serializer/dom3/LSSerializerImpl;-><init>()V
+Lorg/apache/xml/serializer/DOMSerializer;->serialize(Lorg/w3c/dom/Node;)V
+Lorg/apache/xml/serializer/ElemContext;->m_elementName:Ljava/lang/String;
+Lorg/apache/xml/serializer/ElemContext;->m_elementURI:Ljava/lang/String;
+Lorg/apache/xml/serializer/ElemContext;->m_startTagOpen:Z
+Lorg/apache/xml/serializer/ElemContext;->push(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/apache/xml/serializer/ElemContext;
+Lorg/apache/xml/serializer/ElemDesc;->isAttrFlagSet(Ljava/lang/String;I)Z
+Lorg/apache/xml/serializer/Encodings;->convertMime2JavaEncoding(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/Encodings;->getMimeEncoding(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/Encodings;->getWriter(Ljava/io/OutputStream;Ljava/lang/String;)Ljava/io/Writer;
+Lorg/apache/xml/serializer/NamespaceMappings;-><init>()V
+Lorg/apache/xml/serializer/NamespaceMappings;->generateNextPrefix()Ljava/lang/String;
+Lorg/apache/xml/serializer/NamespaceMappings;->lookupNamespace(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/NamespaceMappings;->lookupPrefix(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/OutputPropertiesFactory;->getDefaultMethodProperties(Ljava/lang/String;)Ljava/util/Properties;
+Lorg/apache/xml/serializer/OutputPropertyUtils;->getBooleanProperty(Ljava/lang/String;Ljava/util/Properties;)Z
+Lorg/apache/xml/serializer/OutputPropertyUtils;->getIntProperty(Ljava/lang/String;Ljava/util/Properties;)I
+Lorg/apache/xml/serializer/SerializationHandler;->close()V
+Lorg/apache/xml/serializer/SerializationHandler;->flushPending()V
+Lorg/apache/xml/serializer/SerializationHandler;->setEscaping(Z)Z
+Lorg/apache/xml/serializer/SerializationHandler;->setIndentAmount(I)V
+Lorg/apache/xml/serializer/SerializationHandler;->setNamespaceMappings(Lorg/apache/xml/serializer/NamespaceMappings;)V
+Lorg/apache/xml/serializer/Serializer;->asContentHandler()Lorg/xml/sax/ContentHandler;
+Lorg/apache/xml/serializer/Serializer;->asDOMSerializer()Lorg/apache/xml/serializer/DOMSerializer;
+Lorg/apache/xml/serializer/Serializer;->getOutputFormat()Ljava/util/Properties;
+Lorg/apache/xml/serializer/Serializer;->getOutputStream()Ljava/io/OutputStream;
+Lorg/apache/xml/serializer/Serializer;->getWriter()Ljava/io/Writer;
+Lorg/apache/xml/serializer/Serializer;->reset()Z
+Lorg/apache/xml/serializer/Serializer;->setOutputFormat(Ljava/util/Properties;)V
+Lorg/apache/xml/serializer/Serializer;->setOutputStream(Ljava/io/OutputStream;)V
+Lorg/apache/xml/serializer/Serializer;->setWriter(Ljava/io/Writer;)V
+Lorg/apache/xml/serializer/SerializerBase;->fireCharEvent([CII)V
+Lorg/apache/xml/serializer/SerializerBase;->fireCommentEvent([CII)V
+Lorg/apache/xml/serializer/SerializerBase;->fireEndDoc()V
+Lorg/apache/xml/serializer/SerializerBase;->fireEndElem(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->fireEscapingEvent(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->getDoctypePublic()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getDoctypeSystem()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getEncoding()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getPrefixPart(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getVersion()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->m_attributes:Lorg/apache/xml/serializer/AttributesImplSerializer;
+Lorg/apache/xml/serializer/SerializerBase;->m_charsBuff:[C
+Lorg/apache/xml/serializer/SerializerBase;->m_elemContext:Lorg/apache/xml/serializer/ElemContext;
+Lorg/apache/xml/serializer/SerializerBase;->m_needToCallStartDocument:Z
+Lorg/apache/xml/serializer/SerializerBase;->m_tracer:Lorg/apache/xml/serializer/SerializerTrace;
+Lorg/apache/xml/serializer/SerializerBase;->setDoctypePublic(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setDoctypeSystem(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setIndent(Z)V
+Lorg/apache/xml/serializer/SerializerBase;->setMediaType(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setOmitXMLDeclaration(Z)V
+Lorg/apache/xml/serializer/SerializerBase;->setStandalone(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setStandaloneInternal(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setVersion(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerFactory;->getSerializer(Ljava/util/Properties;)Lorg/apache/xml/serializer/Serializer;
+Lorg/apache/xml/serializer/SerializerTraceWriter;-><init>(Ljava/io/Writer;Lorg/apache/xml/serializer/SerializerTrace;)V
+Lorg/apache/xml/serializer/ToHTMLStream;-><init>()V
+Lorg/apache/xml/serializer/ToHTMLStream;->getElemDesc(Ljava/lang/String;)Lorg/apache/xml/serializer/ElemDesc;
+Lorg/apache/xml/serializer/ToSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToSAXHandler;->m_lexHandler:Lorg/xml/sax/ext/LexicalHandler;
+Lorg/apache/xml/serializer/ToSAXHandler;->m_saxHandler:Lorg/xml/sax/ContentHandler;
+Lorg/apache/xml/serializer/ToSAXHandler;->reset()Z
+Lorg/apache/xml/serializer/ToSAXHandler;->startDocumentInternal()V
+Lorg/apache/xml/serializer/ToSAXHandler;->startElement(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToStream;->setCdataSectionElements(Ljava/lang/String;Ljava/util/Properties;)V
+Lorg/apache/xml/serializer/ToStream;->setEncoding(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToStream;->setIndentAmount(I)V
+Lorg/apache/xml/serializer/ToTextSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToTextSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToTextStream;-><init>()V
+Lorg/apache/xml/serializer/ToUnknownStream;-><init>()V
+Lorg/apache/xml/serializer/ToXMLSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToXMLSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToXMLStream;-><init>()V
+Lorg/apache/xml/serializer/WriterToASCI;-><init>(Ljava/io/OutputStream;)V
+Lorg/apache/xml/serializer/WriterToUTF8Buffered;-><init>(Ljava/io/OutputStream;)V
+Lorg/apache/xml/utils/DefaultErrorHandler;-><init>()V
+Lorg/apache/xml/utils/DefaultErrorHandler;->printLocation(Ljava/io/PrintWriter;Ljava/lang/Throwable;)V
+Lorg/apache/xml/utils/DOMHelper;->isNodeAfter(Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Z
+Lorg/apache/xml/utils/DOMHelper;->isNodeTheSame(Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Z
+Lorg/apache/xml/utils/FastStringBuffer;->append(Ljava/lang/String;)V
+Lorg/apache/xml/utils/FastStringBuffer;->getString(II)Ljava/lang/String;
+Lorg/apache/xml/utils/FastStringBuffer;->length()I
+Lorg/apache/xml/utils/IntStack;->peek()I
+Lorg/apache/xml/utils/ObjectVector;->elementAt(I)Ljava/lang/Object;
+Lorg/apache/xml/utils/ObjectVector;->size()I
+Lorg/apache/xml/utils/PrefixResolverDefault;-><init>(Lorg/w3c/dom/Node;)V
+Lorg/apache/xml/utils/PrefixResolverDefault;->getNamespaceForPrefix(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/QName;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/QName;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/utils/QName;->getLocalName()Ljava/lang/String;
+Lorg/apache/xml/utils/SAXSourceLocator;-><init>(Lorg/xml/sax/SAXParseException;)V
+Lorg/apache/xml/utils/StringBufferPool;->free(Lorg/apache/xml/utils/FastStringBuffer;)V
+Lorg/apache/xml/utils/StringBufferPool;->get()Lorg/apache/xml/utils/FastStringBuffer;
+Lorg/apache/xml/utils/StringVector;->elementAt(I)Ljava/lang/String;
+Lorg/apache/xml/utils/StringVector;->size()I
+Lorg/apache/xml/utils/StylesheetPIHandler;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/utils/StylesheetPIHandler;->getAssociatedStylesheet()Ljavax/xml/transform/Source;
+Lorg/apache/xml/utils/StylesheetPIHandler;->setBaseId(Ljava/lang/String;)V
+Lorg/apache/xml/utils/StylesheetPIHandler;->setURIResolver(Ljavax/xml/transform/URIResolver;)V
+Lorg/apache/xml/utils/SuballocatedIntVector;-><init>(I)V
+Lorg/apache/xml/utils/SuballocatedIntVector;->elementAt(I)I
+Lorg/apache/xml/utils/SuballocatedIntVector;->setElementAt(II)V
+Lorg/apache/xml/utils/SuballocatedIntVector;->size()I
+Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURI(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURI(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURIFromRelative(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/SystemIDResolver;->isAbsoluteURI(Ljava/lang/String;)Z
+Lorg/apache/xml/utils/URI$MalformedURIException;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;-><init>(Lorg/apache/xml/utils/URI;)V
+Lorg/apache/xml/utils/URI;-><init>(Lorg/apache/xml/utils/URI;Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->getFragment()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getHost()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getPath()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getPort()I
+Lorg/apache/xml/utils/URI;->getQueryString()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getScheme()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getUserinfo()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->setFragment(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->setHost(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->setPort(I)V
+Lorg/apache/xml/utils/URI;->setScheme(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->setUserinfo(Ljava/lang/String;)V
+Lorg/apache/xml/utils/WrappedRuntimeException;-><init>(Ljava/lang/Exception;)V
+Lorg/apache/xml/utils/WrappedRuntimeException;->getException()Ljava/lang/Exception;
+Lorg/apache/xml/utils/XML11Char;->isXML11ValidNCName(Ljava/lang/String;)Z
+Lorg/apache/xml/utils/XML11Char;->isXML11ValidQName(Ljava/lang/String;)Z
+Lorg/apache/xml/utils/XMLReaderManager;->getInstance()Lorg/apache/xml/utils/XMLReaderManager;
+Lorg/apache/xml/utils/XMLReaderManager;->getXMLReader()Lorg/xml/sax/XMLReader;
+Lorg/apache/xml/utils/XMLReaderManager;->releaseXMLReader(Lorg/xml/sax/XMLReader;)V
+Lorg/apache/xml/utils/XMLString;->dispatchCharactersEvents(Lorg/xml/sax/ContentHandler;)V
+Lorg/apache/xml/utils/XMLString;->equals(Lorg/apache/xml/utils/XMLString;)Z
+Lorg/apache/xml/utils/XMLString;->fixWhiteSpace(ZZZ)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/utils/XMLStringDefault;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/XMLStringFactory;-><init>()V
+Lorg/apache/xml/utils/XMLStringFactory;->emptystr()Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/utils/XMLStringFactory;->newstr(Ljava/lang/String;)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xpath/axes/ChildTestIterator;-><init>(Lorg/apache/xml/dtm/DTMAxisTraverser;)V
+Lorg/apache/xpath/axes/DescendantIterator;-><init>()V
+Lorg/apache/xpath/axes/LocPathIterator;->getDTM(I)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xpath/axes/LocPathIterator;->getPrefixResolver()Lorg/apache/xml/utils/PrefixResolver;
+Lorg/apache/xpath/axes/LocPathIterator;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xpath/axes/NodeSequence;->getContainedIter()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/axes/NodeSequence;->nextNode()I
+Lorg/apache/xpath/axes/OneStepIterator;-><init>(Lorg/apache/xml/dtm/DTMAxisIterator;I)V
+Lorg/apache/xpath/CachedXPathAPI;-><init>()V
+Lorg/apache/xpath/CachedXPathAPI;-><init>(Lorg/apache/xpath/CachedXPathAPI;)V
+Lorg/apache/xpath/CachedXPathAPI;->eval(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/CachedXPathAPI;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xpath/CachedXPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/CachedXPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/CachedXPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/CachedXPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/compiler/FunctionTable;-><init>()V
+Lorg/apache/xpath/compiler/FunctionTable;->installFunction(Ljava/lang/String;Ljava/lang/Class;)I
+Lorg/apache/xpath/Expression;->assertion(ZLjava/lang/String;)V
+Lorg/apache/xpath/Expression;->error(Lorg/apache/xpath/XPathContext;Ljava/lang/String;[Ljava/lang/Object;)V
+Lorg/apache/xpath/Expression;->exprGetParent()Lorg/apache/xpath/ExpressionNode;
+Lorg/apache/xpath/ExpressionNode;->exprGetParent()Lorg/apache/xpath/ExpressionNode;
+Lorg/apache/xpath/functions/FuncCurrent;-><init>()V
+Lorg/apache/xpath/functions/FuncExtFunction;->getFunctionName()Ljava/lang/String;
+Lorg/apache/xpath/functions/FuncExtFunction;->getMethodKey()Ljava/lang/Object;
+Lorg/apache/xpath/functions/Function;-><init>()V
+Lorg/apache/xpath/functions/WrongNumberArgsException;-><init>(Ljava/lang/String;)V
+Lorg/apache/xpath/NodeSet;-><init>()V
+Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/Node;)V
+Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/NodeList;)V
+Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/traversal/NodeIterator;)V
+Lorg/apache/xpath/NodeSet;->addElement(Lorg/w3c/dom/Node;)V
+Lorg/apache/xpath/NodeSet;->addNode(Lorg/w3c/dom/Node;)V
+Lorg/apache/xpath/NodeSet;->contains(Lorg/w3c/dom/Node;)Z
+Lorg/apache/xpath/NodeSet;->elementAt(I)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/NodeSet;->setShouldCacheNodes(Z)V
+Lorg/apache/xpath/NodeSetDTM;-><init>(Lorg/w3c/dom/NodeList;Lorg/apache/xpath/XPathContext;)V
+Lorg/apache/xpath/NodeSetDTM;-><init>(Lorg/w3c/dom/traversal/NodeIterator;Lorg/apache/xpath/XPathContext;)V
+Lorg/apache/xpath/NodeSetDTM;->addNode(I)V
+Lorg/apache/xpath/NodeSetDTM;->detach()V
+Lorg/apache/xpath/NodeSetDTM;->getLength()I
+Lorg/apache/xpath/NodeSetDTM;->item(I)I
+Lorg/apache/xpath/objects/XBoolean;-><init>(Z)V
+Lorg/apache/xpath/objects/XBoolean;->bool()Z
+Lorg/apache/xpath/objects/XBoolean;->str()Ljava/lang/String;
+Lorg/apache/xpath/objects/XBooleanStatic;-><init>(Z)V
+Lorg/apache/xpath/objects/XNodeSet;-><init>(ILorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xpath/objects/XNodeSet;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xpath/objects/XNodeSet;-><init>(Lorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xpath/objects/XNodeSet;->iterRaw()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/objects/XNodeSet;->mutableNodeset()Lorg/apache/xpath/NodeSetDTM;
+Lorg/apache/xpath/objects/XNodeSet;->nodelist()Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/objects/XNumber;-><init>(D)V
+Lorg/apache/xpath/objects/XNumber;->num()D
+Lorg/apache/xpath/objects/XNumber;->str()Ljava/lang/String;
+Lorg/apache/xpath/objects/XObject;->bool()Z
+Lorg/apache/xpath/objects/XObject;->create(Ljava/lang/Object;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/objects/XObject;->getType()I
+Lorg/apache/xpath/objects/XObject;->getTypeString()Ljava/lang/String;
+Lorg/apache/xpath/objects/XObject;->iter()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/objects/XObject;->nodelist()Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/objects/XObject;->nodeset()Lorg/w3c/dom/traversal/NodeIterator;
+Lorg/apache/xpath/objects/XObject;->num()D
+Lorg/apache/xpath/objects/XObject;->object()Ljava/lang/Object;
+Lorg/apache/xpath/objects/XObject;->str()Ljava/lang/String;
+Lorg/apache/xpath/objects/XObject;->xstr()Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xpath/objects/XRTreeFrag;-><init>(ILorg/apache/xpath/XPathContext;)V
+Lorg/apache/xpath/objects/XRTreeFrag;->asNodeIterator()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/objects/XRTreeFrag;->convertToNodeset()Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/objects/XString;-><init>(Ljava/lang/String;)V
+Lorg/apache/xpath/objects/XString;->num()D
+Lorg/apache/xpath/patterns/NodeTest;->setWhatToShow(I)V
+Lorg/apache/xpath/res/XPATHErrorResources;-><init>()V
+Lorg/apache/xpath/res/XPATHMessages;->createXPATHMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
+Lorg/apache/xpath/XPath;-><init>(Ljava/lang/String;Ljavax/xml/transform/SourceLocator;Lorg/apache/xml/utils/PrefixResolver;I)V
+Lorg/apache/xpath/XPath;-><init>(Ljava/lang/String;Ljavax/xml/transform/SourceLocator;Lorg/apache/xml/utils/PrefixResolver;ILjavax/xml/transform/ErrorListener;)V
+Lorg/apache/xpath/XPath;->execute(Lorg/apache/xpath/XPathContext;ILorg/apache/xml/utils/PrefixResolver;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/XPath;->execute(Lorg/apache/xpath/XPathContext;Lorg/w3c/dom/Node;Lorg/apache/xml/utils/PrefixResolver;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/XPath;->getPatternString()Ljava/lang/String;
+Lorg/apache/xpath/XPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/XPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/XPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/XPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/XPathContext$XPathExpressionContext;->getDTMManager()Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xpath/XPathContext$XPathExpressionContext;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xpath/XPathContext;-><init>()V
+Lorg/apache/xpath/XPathContext;-><init>(Ljava/lang/Object;)V
+Lorg/apache/xpath/XPathContext;->getAxesIteratorStackStacks()Ljava/util/Stack;
+Lorg/apache/xpath/XPathContext;->getContextNodeList()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/XPathContext;->getContextNodeListsStack()Ljava/util/Stack;
+Lorg/apache/xpath/XPathContext;->getCurrentExpressionNodeStack()Lorg/apache/xml/utils/IntStack;
+Lorg/apache/xpath/XPathContext;->getCurrentNode()I
+Lorg/apache/xpath/XPathContext;->getCurrentNodeStack()Lorg/apache/xml/utils/IntStack;
+Lorg/apache/xpath/XPathContext;->getDTM(I)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xpath/XPathContext;->getDTMHandleFromNode(Lorg/w3c/dom/Node;)I
+Lorg/apache/xpath/XPathContext;->getDTMManager()Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xpath/XPathContext;->getExpressionContext()Lorg/apache/xalan/extensions/ExpressionContext;
+Lorg/apache/xpath/XPathContext;->getNamespaceContext()Lorg/apache/xml/utils/PrefixResolver;
+Lorg/apache/xpath/XPathContext;->getOwnerObject()Ljava/lang/Object;
+Lorg/apache/xpath/XPathContext;->getSAXLocator()Ljavax/xml/transform/SourceLocator;
+Lorg/apache/xpath/XPathContext;->getVarStack()Lorg/apache/xpath/VariableStack;
+Lorg/apache/xpath/XPathContext;->m_dtmManager:Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xpath/XPathContext;->popContextNodeList()V
+Lorg/apache/xpath/XPathContext;->popCurrentNode()V
+Lorg/apache/xpath/XPathContext;->pushContextNodeList(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xpath/XPathContext;->pushCurrentNode(I)V
+Lorg/apache/xpath/XPathContext;->reset()V
+Lorg/apache/xpath/XPathContext;->setAxesIteratorStackStacks(Ljava/util/Stack;)V
+Lorg/apache/xpath/XPathContext;->setContextNodeListsStack(Ljava/util/Stack;)V
+Lorg/apache/xpath/XPathContext;->setCurrentExpressionNodeStack(Lorg/apache/xml/utils/IntStack;)V
+Lorg/apache/xpath/XPathContext;->setCurrentNodeStack(Lorg/apache/xml/utils/IntStack;)V
+Lorg/apache/xpath/XPathContext;->setSecureProcessing(Z)V
+Lorg/apache/xpath/XPathContext;->setVarStack(Lorg/apache/xpath/VariableStack;)V
+Lorg/ccil/cowan/tagsoup/AttributesImpl;-><init>(Lorg/xml/sax/Attributes;)V
+Lorg/ccil/cowan/tagsoup/AttributesImpl;->addAttribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String;
Lorg/ccil/cowan/tagsoup/AttributesImpl;->length:I
+Lorg/ccil/cowan/tagsoup/AttributesImpl;->setAttribute(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/AttributesImpl;->setValue(ILjava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/AutoDetector;->autoDetectingReader(Ljava/io/InputStream;)Ljava/io/Reader;
+Lorg/ccil/cowan/tagsoup/Element;-><init>(Lorg/ccil/cowan/tagsoup/ElementType;Z)V
+Lorg/ccil/cowan/tagsoup/Element;->anonymize()V
+Lorg/ccil/cowan/tagsoup/Element;->atts()Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/Element;->canContain(Lorg/ccil/cowan/tagsoup/Element;)Z
+Lorg/ccil/cowan/tagsoup/Element;->clean()V
+Lorg/ccil/cowan/tagsoup/Element;->flags()I
+Lorg/ccil/cowan/tagsoup/Element;->localName()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Element;->name()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Element;->namespace()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Element;->next()Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Element;->parent()Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/Element;->preclosed:Z
+Lorg/ccil/cowan/tagsoup/Element;->setAttribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/Element;->setNext(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Element;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/Element;->theNext:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Element;->theType:Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/ElementType;-><init>(Ljava/lang/String;IIILorg/ccil/cowan/tagsoup/Schema;)V
+Lorg/ccil/cowan/tagsoup/ElementType;->atts()Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/ElementType;->setAttribute(Lorg/ccil/cowan/tagsoup/AttributesImpl;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
Lorg/ccil/cowan/tagsoup/ElementType;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
Lorg/ccil/cowan/tagsoup/ElementType;->theFlags:I
Lorg/ccil/cowan/tagsoup/ElementType;->theLocalName:Ljava/lang/String;
@@ -2292,10 +5600,500 @@
Lorg/ccil/cowan/tagsoup/ElementType;->theNamespace:Ljava/lang/String;
Lorg/ccil/cowan/tagsoup/ElementType;->theParent:Lorg/ccil/cowan/tagsoup/ElementType;
Lorg/ccil/cowan/tagsoup/ElementType;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/HTMLScanner;-><init>()V
Lorg/ccil/cowan/tagsoup/HTMLSchema;-><init>()V
+Lorg/ccil/cowan/tagsoup/jaxp/SAXFactoryImpl;-><init>()V
+Lorg/ccil/cowan/tagsoup/jaxp/SAXParserImpl;-><init>()V
+Lorg/ccil/cowan/tagsoup/jaxp/SAXParserImpl;->newInstance(Ljava/util/Map;)Lorg/ccil/cowan/tagsoup/jaxp/SAXParserImpl;
Lorg/ccil/cowan/tagsoup/Parser;-><init>()V
+Lorg/ccil/cowan/tagsoup/Parser;->bogonsEmpty:Z
+Lorg/ccil/cowan/tagsoup/Parser;->CDATAElements:Z
+Lorg/ccil/cowan/tagsoup/Parser;->cleanPublicid(Ljava/lang/String;)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->defaultAttributes:Z
+Lorg/ccil/cowan/tagsoup/Parser;->etagchars:[C
+Lorg/ccil/cowan/tagsoup/Parser;->expandEntities(Ljava/lang/String;)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->getInputStream(Ljava/lang/String;Ljava/lang/String;)Ljava/io/InputStream;
+Lorg/ccil/cowan/tagsoup/Parser;->ignorableWhitespace:Z
+Lorg/ccil/cowan/tagsoup/Parser;->ignoreBogons:Z
+Lorg/ccil/cowan/tagsoup/Parser;->lookupEntity([CII)I
+Lorg/ccil/cowan/tagsoup/Parser;->makeName([CII)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->pop()V
+Lorg/ccil/cowan/tagsoup/Parser;->push(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Parser;->rectify(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Parser;->restart(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Parser;->restartablyPop()V
+Lorg/ccil/cowan/tagsoup/Parser;->rootBogons:Z
+Lorg/ccil/cowan/tagsoup/Parser;->schemaProperty:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->split(Ljava/lang/String;)[Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theAttributeName:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theAutoDetector:Lorg/ccil/cowan/tagsoup/AutoDetector;
+Lorg/ccil/cowan/tagsoup/Parser;->theContentHandler:Lorg/xml/sax/ContentHandler;
+Lorg/ccil/cowan/tagsoup/Parser;->theDoctypeIsPresent:Z
+Lorg/ccil/cowan/tagsoup/Parser;->theDoctypeSystemId:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theFeatures:Ljava/util/HashMap;
+Lorg/ccil/cowan/tagsoup/Parser;->theLexicalHandler:Lorg/xml/sax/ext/LexicalHandler;
+Lorg/ccil/cowan/tagsoup/Parser;->theNewElement:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->thePCDATA:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->thePITarget:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theSaved:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->theScanner:Lorg/ccil/cowan/tagsoup/Scanner;
+Lorg/ccil/cowan/tagsoup/Parser;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/Parser;->theStack:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->trimquotes(Ljava/lang/String;)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->virginStack:Z
+Lorg/ccil/cowan/tagsoup/PYXScanner;-><init>()V
+Lorg/ccil/cowan/tagsoup/PYXWriter;-><init>(Ljava/io/Writer;)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->aname([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->aval([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->entity([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->eof([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->etag([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->gi([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->pcdata([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->pi([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->stagc([CII)V
+Lorg/ccil/cowan/tagsoup/Scanner;->startCDATA()V
+Lorg/ccil/cowan/tagsoup/Schema;->elementType(Ljava/lang/String;III)V
+Lorg/ccil/cowan/tagsoup/Schema;->getElementType(Ljava/lang/String;)Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/Schema;->getEntity(Ljava/lang/String;)I
+Lorg/ccil/cowan/tagsoup/Schema;->getPrefix()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Schema;->getURI()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Schema;->parent(Ljava/lang/String;Ljava/lang/String;)V
Lorg/ccil/cowan/tagsoup/Schema;->theElementTypes:Ljava/util/HashMap;
Lorg/ccil/cowan/tagsoup/Schema;->theEntities:Ljava/util/HashMap;
Lorg/ccil/cowan/tagsoup/Schema;->thePrefix:Ljava/lang/String;
Lorg/ccil/cowan/tagsoup/Schema;->theRoot:Lorg/ccil/cowan/tagsoup/ElementType;
Lorg/ccil/cowan/tagsoup/Schema;->theURI:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/XMLWriter;-><init>(Ljava/io/Writer;)V
+Lorg/ccil/cowan/tagsoup/XMLWriter;->htmlMode:Z
+Lorg/ccil/cowan/tagsoup/XMLWriter;->setOutput(Ljava/io/Writer;)V
+Lorg/ccil/cowan/tagsoup/XMLWriter;->setOutputProperty(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/XMLWriter;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/xml/sax/helpers/NamespaceSupport$Context;-><init>(Lorg/xml/sax/helpers/NamespaceSupport;)V
+Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;-><init>(Lorg/xml/sax/helpers/ParserAdapter;)V
+Lsun/misc/ASCIICaseInsensitiveComparator;->CASE_INSENSITIVE_ORDER:Ljava/util/Comparator;
+Lsun/misc/ASCIICaseInsensitiveComparator;->lowerCaseHashCode(Ljava/lang/String;)I
+Lsun/misc/BASE64Decoder;-><init>()V
+Lsun/misc/BASE64Decoder;->pem_convert_array:[B
+Lsun/misc/BASE64Encoder;-><init>()V
+Lsun/misc/BASE64Encoder;->pem_array:[C
+Lsun/misc/CEFormatException;-><init>(Ljava/lang/String;)V
+Lsun/misc/CEStreamExhausted;-><init>()V
+Lsun/misc/CharacterDecoder;-><init>()V
+Lsun/misc/CharacterEncoder;-><init>()V
+Lsun/misc/CharacterEncoder;->encodeBuffer([B)Ljava/lang/String;
+Lsun/misc/CharacterEncoder;->encodeBufferPrefix(Ljava/io/OutputStream;)V
+Lsun/misc/CharacterEncoder;->pStream:Ljava/io/PrintStream;
+Lsun/misc/Cleaner;->create(Ljava/lang/Object;Ljava/lang/Runnable;)Lsun/misc/Cleaner;
+Lsun/misc/FloatingDecimal;->$assertionsDisabled:Z
+Lsun/misc/FloatingDecimal;->getHexDigit(Ljava/lang/String;I)I
+Lsun/misc/FloatingDecimal;->stripLeadingZeros(Ljava/lang/String;)Ljava/lang/String;
+Lsun/misc/FormattedFloatingDecimal$Form;->COMPATIBLE:Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal$Form;->DECIMAL_FLOAT:Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal$Form;->SCIENTIFIC:Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal;->$assertionsDisabled:Z
+Lsun/misc/FpUtils;->$assertionsDisabled:Z
+Lsun/misc/FpUtils;->rawCopySign(DD)D
+Lsun/misc/HexDumpEncoder;-><init>()V
+Lsun/misc/HexDumpEncoder;->currentByte:I
+Lsun/misc/HexDumpEncoder;->offset:I
+Lsun/misc/HexDumpEncoder;->thisLine:[B
+Lsun/misc/HexDumpEncoder;->thisLineLength:I
+Lsun/misc/IOUtils;->readFully(Ljava/io/InputStream;IZ)[B
+Lsun/misc/JarIndex;-><init>([Ljava/lang/String;)V
+Lsun/misc/JarIndex;->write(Ljava/io/OutputStream;)V
+Lsun/misc/MessageUtils;-><init>()V
+Lsun/misc/MetaIndex;->forJar(Ljava/io/File;)Lsun/misc/MetaIndex;
+Lsun/misc/MetaIndex;->registerDirectory(Ljava/io/File;)V
+Lsun/misc/VM;->maxDirectMemory()J
+Lsun/net/ftp/FtpClient;-><init>()V
+Lsun/net/util/IPAddressUtil;->isIPv4LiteralAddress(Ljava/lang/String;)Z
+Lsun/net/util/IPAddressUtil;->isIPv6LiteralAddress(Ljava/lang/String;)Z
+Lsun/net/www/MessageHeader;-><init>()V
+Lsun/net/www/MessageHeader;-><init>(Ljava/io/InputStream;)V
+Lsun/net/www/MessageHeader;->add(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/net/www/MessageHeader;->findValue(Ljava/lang/String;)Ljava/lang/String;
+Lsun/net/www/MessageHeader;->prepend(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/net/www/MessageHeader;->print(Ljava/io/PrintStream;)V
+Lsun/net/www/MessageHeader;->set(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/net/www/ParseUtil;->decode(Ljava/lang/String;)Ljava/lang/String;
+Lsun/net/www/ParseUtil;->encodePath(Ljava/lang/String;Z)Ljava/lang/String;
+Lsun/net/www/ParseUtil;->fileToEncodedURL(Ljava/io/File;)Ljava/net/URL;
+Lsun/net/www/URLConnection;-><init>(Ljava/net/URL;)V
+Lsun/net/www/URLConnection;->setProperties(Lsun/net/www/MessageHeader;)V
+Lsun/nio/ch/DirectBuffer;->address()J
+Lsun/nio/ch/FileChannelImpl;->unmap0(JJ)I
+Lsun/nio/ch/SelectorImpl;->publicSelectedKeys:Ljava/util/Set;
+Lsun/nio/ch/SelectorImpl;->selectedKeys:Ljava/util/Set;
+Lsun/nio/cs/HistoricallyNamedCharset;->historicalName()Ljava/lang/String;
+Lsun/nio/cs/ThreadLocalCoders;->decoderFor(Ljava/lang/Object;)Ljava/nio/charset/CharsetDecoder;
+Lsun/nio/fs/BasicFileAttributesHolder;->get()Ljava/nio/file/attribute/BasicFileAttributes;
+Lsun/reflect/misc/ReflectUtil;->checkPackageAccess(Ljava/lang/Class;)V
+Lsun/reflect/misc/ReflectUtil;->checkPackageAccess(Ljava/lang/String;)V
+Lsun/reflect/misc/ReflectUtil;->isPackageAccessible(Ljava/lang/Class;)Z
+Lsun/reflect/misc/ReflectUtil;->isSubclassOf(Ljava/lang/Class;Ljava/lang/Class;)Z
+Lsun/reflect/Reflection;->ensureMemberAccess(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)V
+Lsun/reflect/Reflection;->isSubclassOf(Ljava/lang/Class;Ljava/lang/Class;)Z
+Lsun/security/action/GetBooleanAction;-><init>(Ljava/lang/String;)V
+Lsun/security/action/GetIntegerAction;-><init>(Ljava/lang/String;I)V
+Lsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;)V
+Lsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/jca/GetInstance$Instance;->impl:Ljava/lang/Object;
+Lsun/security/jca/GetInstance$Instance;->provider:Ljava/security/Provider;
+Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;)Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/security/Provider;)Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/JCAUtil;->getSecureRandom()Ljava/security/SecureRandom;
+Lsun/security/jca/ProviderConfig;->argument:Ljava/lang/String;
+Lsun/security/jca/ProviderConfig;->CL_STRING:[Ljava/lang/Class;
+Lsun/security/jca/ProviderConfig;->disableLoad()V
+Lsun/security/jca/ProviderConfig;->hasArgument()Z
+Lsun/security/jca/ProviderList;->getService(Ljava/lang/String;Ljava/lang/String;)Ljava/security/Provider$Service;
+Lsun/security/jca/Providers;->getProviderList()Lsun/security/jca/ProviderList;
+Lsun/security/jca/Providers;->startJarVerification()Ljava/lang/Object;
+Lsun/security/jca/Providers;->stopJarVerification(Ljava/lang/Object;)V
+Lsun/security/pkcs/ContentInfo;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/ContentInfo;-><init>([B)V
+Lsun/security/pkcs/ContentInfo;->DATA_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/ContentInfo;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/pkcs/ContentInfo;->getData()[B
+Lsun/security/pkcs/ParsingException;-><init>(Ljava/lang/String;)V
+Lsun/security/pkcs/PKCS7;-><init>([B)V
+Lsun/security/pkcs/PKCS7;-><init>([Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/ContentInfo;[Ljava/security/cert/X509Certificate;[Ljava/security/cert/X509CRL;[Lsun/security/pkcs/SignerInfo;)V
+Lsun/security/pkcs/PKCS7;-><init>([Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/ContentInfo;[Ljava/security/cert/X509Certificate;[Lsun/security/pkcs/SignerInfo;)V
+Lsun/security/pkcs/PKCS7;->encodeSignedData(Ljava/io/OutputStream;)V
+Lsun/security/pkcs/PKCS7;->getCertificates()[Ljava/security/cert/X509Certificate;
+Lsun/security/pkcs/PKCS7;->getContentInfo()Lsun/security/pkcs/ContentInfo;
+Lsun/security/pkcs/PKCS7;->getSignerInfos()[Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS7;->verify(Lsun/security/pkcs/SignerInfo;[B)Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS7;->verify([B)[Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS8Key;-><init>()V
+Lsun/security/pkcs/PKCS8Key;->algid:Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/PKCS8Key;->encodedKey:[B
+Lsun/security/pkcs/PKCS8Key;->key:[B
+Lsun/security/pkcs/PKCS9Attribute;-><init>(Ljava/lang/String;Ljava/lang/Object;)V
+Lsun/security/pkcs/PKCS9Attribute;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/PKCS9Attribute;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/lang/Object;)V
+Lsun/security/pkcs/PKCS9Attribute;->CONTENT_TYPE_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->derEncode(Ljava/io/OutputStream;)V
+Lsun/security/pkcs/PKCS9Attribute;->EMAIL_ADDRESS_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->getValue()Ljava/lang/Object;
+Lsun/security/pkcs/PKCS9Attribute;->MESSAGE_DIGEST_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->SIGNING_TIME_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attributes;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/pkcs/PKCS9Attributes;-><init>(Lsun/security/util/DerInputStream;Z)V
+Lsun/security/pkcs/PKCS9Attributes;-><init>([Lsun/security/pkcs/PKCS9Attribute;)V
+Lsun/security/pkcs/PKCS9Attributes;->encode(BLjava/io/OutputStream;)V
+Lsun/security/pkcs/PKCS9Attributes;->getAttribute(Ljava/lang/String;)Lsun/security/pkcs/PKCS9Attribute;
+Lsun/security/pkcs/PKCS9Attributes;->getAttributeValue(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Object;
+Lsun/security/pkcs/PKCS9Attributes;->getDerEncoding()[B
+Lsun/security/pkcs/SignerInfo;-><init>(Lsun/security/x509/X500Name;Ljava/math/BigInteger;Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/PKCS9Attributes;Lsun/security/x509/AlgorithmId;[BLsun/security/pkcs/PKCS9Attributes;)V
+Lsun/security/pkcs/SignerInfo;-><init>(Lsun/security/x509/X500Name;Ljava/math/BigInteger;Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;[B)V
+Lsun/security/pkcs/SignerInfo;->getCertificate(Lsun/security/pkcs/PKCS7;)Ljava/security/cert/X509Certificate;
+Lsun/security/pkcs/SignerInfo;->getCertificateChain(Lsun/security/pkcs/PKCS7;)Ljava/util/ArrayList;
+Lsun/security/pkcs/SignerInfo;->getDigestAlgorithmId()Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/SignerInfo;->getDigestEncryptionAlgorithmId()Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/SignerInfo;->getEncryptedDigest()[B
+Lsun/security/provider/certpath/X509CertificatePair;->clearCache()V
+Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/io/InputStream;)V
+Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/io/InputStream;Ljava/lang/String;)V
+Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/util/List;)V
+Lsun/security/provider/certpath/X509CertPath;->certs:Ljava/util/List;
+Lsun/security/provider/certpath/X509CertPath;->getEncodingsStatic()Ljava/util/Iterator;
+Lsun/security/provider/X509Factory;->addToCache(Lsun/security/util/Cache;[BLjava/lang/Object;)V
+Lsun/security/provider/X509Factory;->certCache:Lsun/security/util/Cache;
+Lsun/security/provider/X509Factory;->crlCache:Lsun/security/util/Cache;
+Lsun/security/provider/X509Factory;->getFromCache(Lsun/security/util/Cache;[B)Ljava/lang/Object;
+Lsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509Certificate;)Lsun/security/x509/X509CertImpl;
+Lsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509CRL;)Lsun/security/x509/X509CRLImpl;
+Lsun/security/timestamp/TimestampToken;-><init>([B)V
+Lsun/security/timestamp/TimestampToken;->getDate()Ljava/util/Date;
+Lsun/security/timestamp/TimestampToken;->getHashAlgorithm()Lsun/security/x509/AlgorithmId;
+Lsun/security/timestamp/TimestampToken;->getHashedMessage()[B
+Lsun/security/timestamp/TimestampToken;->getNonce()Ljava/math/BigInteger;
+Lsun/security/util/BitArray;-><init>(I[B)V
+Lsun/security/util/BitArray;->toByteArray()[B
+Lsun/security/util/Cache;-><init>()V
+Lsun/security/util/Cache;->clear()V
+Lsun/security/util/Cache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Lsun/security/util/Cache;->newHardMemoryCache(I)Lsun/security/util/Cache;
+Lsun/security/util/Cache;->put(Ljava/lang/Object;Ljava/lang/Object;)V
+Lsun/security/util/Debug;->getInstance(Ljava/lang/String;)Lsun/security/util/Debug;
+Lsun/security/util/Debug;->println()V
+Lsun/security/util/Debug;->println(Ljava/lang/String;)V
+Lsun/security/util/Debug;->toHexString(Ljava/math/BigInteger;)Ljava/lang/String;
+Lsun/security/util/DerIndefLenConverter;-><init>()V
+Lsun/security/util/DerIndefLenConverter;->convert([B)[B
+Lsun/security/util/DerIndefLenConverter;->data:[B
+Lsun/security/util/DerIndefLenConverter;->dataPos:I
+Lsun/security/util/DerIndefLenConverter;->dataSize:I
+Lsun/security/util/DerIndefLenConverter;->isIndefinite(I)Z
+Lsun/security/util/DerIndefLenConverter;->newData:[B
+Lsun/security/util/DerIndefLenConverter;->numOfTotalLenBytes:I
+Lsun/security/util/DerIndefLenConverter;->parseLength()I
+Lsun/security/util/DerIndefLenConverter;->parseTag()V
+Lsun/security/util/DerIndefLenConverter;->parseValue(I)V
+Lsun/security/util/DerIndefLenConverter;->writeLengthAndValue()V
+Lsun/security/util/DerIndefLenConverter;->writeTag()V
+Lsun/security/util/DerInputStream;-><init>([B)V
+Lsun/security/util/DerInputStream;->available()I
+Lsun/security/util/DerInputStream;->getBigInteger()Ljava/math/BigInteger;
+Lsun/security/util/DerInputStream;->getBitString()[B
+Lsun/security/util/DerInputStream;->getDerValue()Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getInteger()I
+Lsun/security/util/DerInputStream;->getOctetString()[B
+Lsun/security/util/DerInputStream;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/DerInputStream;->getSequence(I)[Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getSet(I)[Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getSet(IZ)[Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getUTCTime()Ljava/util/Date;
+Lsun/security/util/DerInputStream;->getUTF8String()Ljava/lang/String;
+Lsun/security/util/DerInputStream;->mark(I)V
+Lsun/security/util/DerInputStream;->peekByte()I
+Lsun/security/util/DerInputStream;->reset()V
+Lsun/security/util/DerInputStream;->subStream(IZ)Lsun/security/util/DerInputStream;
+Lsun/security/util/DerInputStream;->tag:B
+Lsun/security/util/DerOutputStream;-><init>()V
+Lsun/security/util/DerOutputStream;-><init>(I)V
+Lsun/security/util/DerOutputStream;->putBitString([B)V
+Lsun/security/util/DerOutputStream;->putBoolean(Z)V
+Lsun/security/util/DerOutputStream;->putDerValue(Lsun/security/util/DerValue;)V
+Lsun/security/util/DerOutputStream;->putIA5String(Ljava/lang/String;)V
+Lsun/security/util/DerOutputStream;->putInteger(I)V
+Lsun/security/util/DerOutputStream;->putInteger(Ljava/math/BigInteger;)V
+Lsun/security/util/DerOutputStream;->putNull()V
+Lsun/security/util/DerOutputStream;->putOctetString([B)V
+Lsun/security/util/DerOutputStream;->putOID(Lsun/security/util/ObjectIdentifier;)V
+Lsun/security/util/DerOutputStream;->putOrderedSetOf(B[Lsun/security/util/DerEncoder;)V
+Lsun/security/util/DerOutputStream;->putPrintableString(Ljava/lang/String;)V
+Lsun/security/util/DerOutputStream;->putSequence([Lsun/security/util/DerValue;)V
+Lsun/security/util/DerOutputStream;->putUTCTime(Ljava/util/Date;)V
+Lsun/security/util/DerOutputStream;->putUTF8String(Ljava/lang/String;)V
+Lsun/security/util/DerOutputStream;->write(BLsun/security/util/DerOutputStream;)V
+Lsun/security/util/DerOutputStream;->write(B[B)V
+Lsun/security/util/DerValue;-><init>(B[B)V
+Lsun/security/util/DerValue;-><init>(Ljava/io/InputStream;)V
+Lsun/security/util/DerValue;-><init>(Ljava/lang/String;)V
+Lsun/security/util/DerValue;-><init>([B)V
+Lsun/security/util/DerValue;-><init>([BII)V
+Lsun/security/util/DerValue;->buffer:Lsun/security/util/DerInputBuffer;
+Lsun/security/util/DerValue;->createTag(BZB)B
+Lsun/security/util/DerValue;->data:Lsun/security/util/DerInputStream;
+Lsun/security/util/DerValue;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/util/DerValue;->getAsString()Ljava/lang/String;
+Lsun/security/util/DerValue;->getBigInteger()Ljava/math/BigInteger;
+Lsun/security/util/DerValue;->getBitString()[B
+Lsun/security/util/DerValue;->getData()Lsun/security/util/DerInputStream;
+Lsun/security/util/DerValue;->getDataBytes()[B
+Lsun/security/util/DerValue;->getOctetString()[B
+Lsun/security/util/DerValue;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/DerValue;->getPositiveBigInteger()Ljava/math/BigInteger;
+Lsun/security/util/DerValue;->getUnalignedBitString()Lsun/security/util/BitArray;
+Lsun/security/util/DerValue;->isConstructed()Z
+Lsun/security/util/DerValue;->isContextSpecific()Z
+Lsun/security/util/DerValue;->isContextSpecific(B)Z
+Lsun/security/util/DerValue;->isPrintableStringChar(C)Z
+Lsun/security/util/DerValue;->resetTag(B)V
+Lsun/security/util/DerValue;->tag:B
+Lsun/security/util/DerValue;->toByteArray()[B
+Lsun/security/util/DerValue;->toDerInputStream()Lsun/security/util/DerInputStream;
+Lsun/security/util/ManifestDigester$Entry;->digest(Ljava/security/MessageDigest;)[B
+Lsun/security/util/ManifestDigester$Entry;->digestWorkaround(Ljava/security/MessageDigest;)[B
+Lsun/security/util/ManifestDigester;-><init>([B)V
+Lsun/security/util/ManifestDigester;->get(Ljava/lang/String;Z)Lsun/security/util/ManifestDigester$Entry;
+Lsun/security/util/ManifestDigester;->manifestDigest(Ljava/security/MessageDigest;)[B
+Lsun/security/util/MemoryCache$HardCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;J)V
+Lsun/security/util/MemoryCache$SoftCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;JLjava/lang/ref/ReferenceQueue;)V
+Lsun/security/util/ObjectIdentifier;-><init>(Ljava/lang/String;)V
+Lsun/security/util/ObjectIdentifier;-><init>([I)V
+Lsun/security/util/ObjectIdentifier;->equals(Lsun/security/util/ObjectIdentifier;)Z
+Lsun/security/util/ObjectIdentifier;->newInternal([I)Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/PropertyExpander;->expand(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/util/ResourcesMgr;->getString(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/util/SecurityConstants;->CREATE_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SecurityConstants;->GET_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SecurityConstants;->MODIFY_THREADGROUP_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SecurityConstants;->MODIFY_THREAD_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SignatureFileVerifier;->isBlockOrSF(Ljava/lang/String;)Z
+Lsun/security/x509/AccessDescription;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/AccessDescription;->getAccessLocation()Lsun/security/x509/GeneralName;
+Lsun/security/x509/AccessDescription;->getAccessMethod()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;-><init>()V
+Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;)V
+Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/security/AlgorithmParameters;)V
+Lsun/security/x509/AlgorithmId;->derEncode(Ljava/io/OutputStream;)V
+Lsun/security/x509/AlgorithmId;->DSA_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->EC_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->encode()[B
+Lsun/security/x509/AlgorithmId;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/AlgorithmId;->equals(Lsun/security/x509/AlgorithmId;)Z
+Lsun/security/x509/AlgorithmId;->getAlgorithmId(Ljava/lang/String;)Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AlgorithmId;->getDigAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/x509/AlgorithmId;->getEncAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/x509/AlgorithmId;->getEncodedParams()[B
+Lsun/security/x509/AlgorithmId;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->getParameters()Ljava/security/AlgorithmParameters;
+Lsun/security/x509/AlgorithmId;->MD2_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->MD5_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->params:Lsun/security/util/DerValue;
+Lsun/security/x509/AlgorithmId;->parse(Lsun/security/util/DerValue;)Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AlgorithmId;->RSAEncryption_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->sha1WithRSAEncryption_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA256_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA384_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA512_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AttributeNameEnumeration;-><init>()V
+Lsun/security/x509/AVA;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
+Lsun/security/x509/AVA;->getDerValue()Lsun/security/util/DerValue;
+Lsun/security/x509/AVA;->getObjectIdentifier()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVA;->getValueString()Ljava/lang/String;
+Lsun/security/x509/AVA;->toRFC2253CanonicalString()Ljava/lang/String;
+Lsun/security/x509/AVAComparator;->INSTANCE:Ljava/util/Comparator;
+Lsun/security/x509/AVAKeyword;->getOID(Ljava/lang/String;ILjava/util/Map;)Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVAKeyword;->isCompliant(I)Z
+Lsun/security/x509/AVAKeyword;->keyword:Ljava/lang/String;
+Lsun/security/x509/AVAKeyword;->keywordMap:Ljava/util/Map;
+Lsun/security/x509/AVAKeyword;->oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVAKeyword;->oidMap:Ljava/util/Map;
+Lsun/security/x509/CertificateAlgorithmId;-><init>(Lsun/security/x509/AlgorithmId;)V
+Lsun/security/x509/CertificateExtensions;-><init>()V
+Lsun/security/x509/CertificateExtensions;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/CertificateExtensions;->encode(Ljava/io/OutputStream;Z)V
+Lsun/security/x509/CertificateExtensions;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/CertificateExtensions;->set(Ljava/lang/String;Ljava/lang/Object;)V
+Lsun/security/x509/CertificateIssuerName;-><init>(Lsun/security/x509/X500Name;)V
+Lsun/security/x509/CertificateSerialNumber;-><init>(I)V
+Lsun/security/x509/CertificateSerialNumber;-><init>(Ljava/math/BigInteger;)V
+Lsun/security/x509/CertificateSubjectName;-><init>(Lsun/security/x509/X500Name;)V
+Lsun/security/x509/CertificateSubjectName;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/CertificateValidity;-><init>(Ljava/util/Date;Ljava/util/Date;)V
+Lsun/security/x509/CertificateVersion;-><init>(I)V
+Lsun/security/x509/CertificateX509Key;-><init>(Ljava/security/PublicKey;)V
+Lsun/security/x509/CRLDistributionPointsExtension;->encodeThis()V
+Lsun/security/x509/CRLNumberExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V
+Lsun/security/x509/CRLNumberExtension;->encodeThis()V
+Lsun/security/x509/CRLNumberExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/Extension;-><init>(Lsun/security/x509/Extension;)V
+Lsun/security/x509/Extension;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/Extension;->getExtensionId()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/GeneralName;-><init>(Lsun/security/x509/GeneralNameInterface;)V
+Lsun/security/x509/GeneralName;->getName()Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralName;->getType()I
+Lsun/security/x509/GeneralNames;-><init>()V
+Lsun/security/x509/GeneralNames;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/GeneralNames;->add(Lsun/security/x509/GeneralName;)Lsun/security/x509/GeneralNames;
+Lsun/security/x509/GeneralNames;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/GeneralNames;->isEmpty()Z
+Lsun/security/x509/KeyIdentifier;-><init>(Ljava/security/PublicKey;)V
+Lsun/security/x509/KeyIdentifier;->getIdentifier()[B
+Lsun/security/x509/KeyIdentifier;->octetString:[B
+Lsun/security/x509/KeyUsageExtension;-><init>([Z)V
+Lsun/security/x509/KeyUsageExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/NetscapeCertTypeExtension;-><init>([B)V
+Lsun/security/x509/NetscapeCertTypeExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/OIDMap$OIDInfo;->clazz:Ljava/lang/Class;
+Lsun/security/x509/OIDMap;->getClass(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Class;
+Lsun/security/x509/OIDMap;->nameMap:Ljava/util/Map;
+Lsun/security/x509/OIDMap;->oidMap:Ljava/util/Map;
+Lsun/security/x509/PKIXExtensions;->CertificateIssuer_Id:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/SerialNumber;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/SubjectAlternativeNameExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/SubjectKeyIdentifierExtension;-><init>([B)V
+Lsun/security/x509/UniqueIdentity;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/UniqueIdentity;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/UniqueIdentity;->encode(Lsun/security/util/DerOutputStream;B)V
+Lsun/security/x509/URIName;->getName()Ljava/lang/String;
+Lsun/security/x509/URIName;->getScheme()Ljava/lang/String;
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/X500Name;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X500Name;-><init>([B)V
+Lsun/security/x509/X500Name;->allAvas()Ljava/util/List;
+Lsun/security/x509/X500Name;->asX500Name(Ljavax/security/auth/x500/X500Principal;)Lsun/security/x509/X500Name;
+Lsun/security/x509/X500Name;->asX500Principal()Ljavax/security/auth/x500/X500Principal;
+Lsun/security/x509/X500Name;->commonName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->countryName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->DNQUALIFIER_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->DOMAIN_COMPONENT_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/X500Name;->GENERATIONQUALIFIER_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->getCommonName()Ljava/lang/String;
+Lsun/security/x509/X500Name;->GIVENNAME_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->INITIALS_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->ipAddress_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->isEmpty()Z
+Lsun/security/x509/X500Name;->localityName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->orgName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->orgUnitName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->SERIALNUMBER_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->stateName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->streetAddress_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->SURNAME_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->title_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->userid_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X509CertImpl;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X509CertImpl;-><init>(Lsun/security/x509/X509CertInfo;)V
+Lsun/security/x509/X509CertImpl;-><init>([B)V
+Lsun/security/x509/X509CertImpl;->algId:Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/X509CertImpl;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/X509CertImpl;->getEncodedInternal()[B
+Lsun/security/x509/X509CertImpl;->parse(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X509CertImpl;->readOnly:Z
+Lsun/security/x509/X509CertImpl;->sign(Ljava/security/PrivateKey;Ljava/lang/String;)V
+Lsun/security/x509/X509CertImpl;->signature:[B
+Lsun/security/x509/X509CertImpl;->signedCert:[B
+Lsun/security/x509/X509CertInfo;-><init>()V
+Lsun/security/x509/X509CertInfo;-><init>([B)V
+Lsun/security/x509/X509CertInfo;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/X509CertInfo;->set(Ljava/lang/String;Ljava/lang/Object;)V
+Lsun/security/x509/X509CRLEntryImpl;->getExtension(Lsun/security/util/ObjectIdentifier;)Lsun/security/x509/Extension;
+Lsun/security/x509/X509CRLImpl;-><init>(Ljava/io/InputStream;)V
+Lsun/security/x509/X509CRLImpl;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X509CRLImpl;-><init>([B)V
+Lsun/security/x509/X509CRLImpl;->getEncodedInternal()[B
+Lsun/security/x509/X509Key;-><init>()V
+Lsun/security/x509/X509Key;->algid:Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/X509Key;->encodedKey:[B
+Lsun/security/x509/X509Key;->key:[B
+Lsun/security/x509/X509Key;->parse(Lsun/security/util/DerValue;)Ljava/security/PublicKey;
+Lsun/security/x509/X509Key;->unusedBits:I
+Lsun/util/calendar/AbstractCalendar;->getDayOfWeekDateOnOrBefore(JI)J
+Lsun/util/calendar/AbstractCalendar;->getTimeOfDayValue(Lsun/util/calendar/CalendarDate;)J
+Lsun/util/calendar/BaseCalendar$Date;->getNormalizedYear()I
+Lsun/util/calendar/BaseCalendar$Date;->setNormalizedYear(I)V
+Lsun/util/calendar/CalendarDate;->getDayOfMonth()I
+Lsun/util/calendar/CalendarDate;->getMonth()I
+Lsun/util/calendar/CalendarDate;->getTimeOfDay()J
+Lsun/util/calendar/CalendarDate;->getYear()I
+Lsun/util/calendar/CalendarDate;->setDate(III)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setDayOfMonth(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setHours(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setMillis(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setMinutes(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setSeconds(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarSystem;->forName(Ljava/lang/String;)Lsun/util/calendar/CalendarSystem;
+Lsun/util/calendar/CalendarSystem;->getGregorianCalendar()Lsun/util/calendar/Gregorian;
+Lsun/util/calendar/CalendarSystem;->getTime(Lsun/util/calendar/CalendarDate;)J
+Lsun/util/calendar/CalendarSystem;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarSystem;->validate(Lsun/util/calendar/CalendarDate;)Z
+Lsun/util/calendar/CalendarUtils;->floorDivide(II)I
+Lsun/util/calendar/CalendarUtils;->floorDivide(JJ)J
+Lsun/util/calendar/CalendarUtils;->mod(II)I
+Lsun/util/calendar/CalendarUtils;->mod(JJ)J
+Lsun/util/calendar/Era;-><init>(Ljava/lang/String;Ljava/lang/String;JZ)V
+Lsun/util/calendar/Era;->getAbbreviation()Ljava/lang/String;
+Lsun/util/calendar/Era;->getName()Ljava/lang/String;
+Lsun/util/calendar/Era;->getSinceDate()Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/ImmutableGregorianDate;->unsupported()V
+Lsun/util/calendar/LocalGregorianCalendar$Date;->getNormalizedYear()I
+Lsun/util/calendar/LocalGregorianCalendar$Date;->setEra(Lsun/util/calendar/Era;)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Lsun/util/calendar/LocalGregorianCalendar$Date;->setNormalizedYear(I)V
+Lsun/util/calendar/LocalGregorianCalendar$Date;->setYear(I)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Lsun/util/calendar/LocalGregorianCalendar;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Lsun/util/calendar/LocalGregorianCalendar;->normalize(Lsun/util/calendar/CalendarDate;)Z
+Lsun/util/calendar/LocalGregorianCalendar;->validate(Lsun/util/calendar/CalendarDate;)Z
diff --git a/config/preloaded-classes b/config/preloaded-classes
index b6bff9c..22fc5e8 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -3240,7 +3240,7 @@
android.view.FocusFinder$FocusSorter
android.view.FocusFinder$UserSpecifiedFocusComparator
android.view.FocusFinder$UserSpecifiedFocusComparator$NextFocusGetter
-android.view.FrameInfo
+android.graphics.FrameInfo
android.view.FrameMetrics
android.view.FrameMetricsObserver
android.view.FrameStats
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index d7cca15..997ed25 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -76,7 +76,8 @@
* @attr ref android.R.styleable#AccessibilityService_notificationTimeout
* @attr ref android.R.styleable#AccessibilityService_packageNames
* @attr ref android.R.styleable#AccessibilityService_settingsActivity
- * @attr ref android.R.styleable#AccessibilityService_minimumUiTimeout
+ * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
+ * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
* @see AccessibilityService
* @see android.view.accessibility.AccessibilityEvent
* @see android.view.accessibility.AccessibilityManager
@@ -434,11 +435,14 @@
public boolean crashed;
/**
- * The minimum timeout in milliseconds that UI controls need to remain on the screen.
- *
- * @see #setMinimumUiTimeoutMillis
+ * A recommended timeout in milliseconds for non-interactive controls.
*/
- private int mMinimumUiTimeout;
+ private int mNonInteractiveUiTimeout;
+
+ /**
+ * A recommended timeout in milliseconds for interactive controls.
+ */
+ private int mInteractiveUiTimeout;
/**
* The component name the accessibility service.
@@ -544,8 +548,11 @@
notificationTimeout = asAttributes.getInt(
com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
0);
- mMinimumUiTimeout = asAttributes.getInt(
- com.android.internal.R.styleable.AccessibilityService_minimumUiTimeout,
+ mNonInteractiveUiTimeout = asAttributes.getInt(
+ com.android.internal.R.styleable.AccessibilityService_nonInteractiveUiTimeout,
+ 0);
+ mInteractiveUiTimeout = asAttributes.getInt(
+ com.android.internal.R.styleable.AccessibilityService_interactiveUiTimeout,
0);
flags = asAttributes.getInt(
com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
@@ -616,7 +623,8 @@
packageNames = other.packageNames;
feedbackType = other.feedbackType;
notificationTimeout = other.notificationTimeout;
- mMinimumUiTimeout = other.mMinimumUiTimeout;
+ mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout;
+ mInteractiveUiTimeout = other.mInteractiveUiTimeout;
flags = other.flags;
}
@@ -775,26 +783,57 @@
}
/**
- * Set the minimum time that controls need to remain on the screen to support the user.
+ * Set the recommended time that non-interactive controls need to remain on the screen to
+ * support the user.
* <p>
- * <strong>This value can be dynamically set at runtime by
- * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
+ * <strong>This value can be dynamically set at runtime by
+ * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
* </p>
*
* @param timeout The timeout in milliseconds.
+ *
+ * @see android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
*/
- public void setMinimumUiTimeoutMillis(int timeout) {
- mMinimumUiTimeout = timeout;
+ public void setNonInteractiveUiTimeoutMillis(int timeout) {
+ mNonInteractiveUiTimeout = timeout;
}
/**
- * Get the minimum ui timeout.
+ * Get the recommended timeout for non-interactive controls.
*
- * @see #setMinimumUiTimeoutMillis
* @return The timeout in milliseconds.
+ *
+ * @see #setNonInteractiveUiTimeoutMillis(int)
*/
- public int getMinimumUiTimeoutMillis() {
- return mMinimumUiTimeout;
+ public int getNonInteractiveUiTimeoutMillis() {
+ return mNonInteractiveUiTimeout;
+ }
+
+ /**
+ * Set the recommended time that interactive controls need to remain on the screen to
+ * support the user.
+ * <p>
+ * <strong>This value can be dynamically set at runtime by
+ * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
+ * </p>
+ *
+ * @param timeout The timeout in milliseconds.
+ *
+ * @see android.R.styleable#AccessibilityService_interactiveUiTimeout
+ */
+ public void setInteractiveUiTimeoutMillis(int timeout) {
+ mInteractiveUiTimeout = timeout;
+ }
+
+ /**
+ * Get the recommended timeout for interactive controls.
+ *
+ * @return The timeout in milliseconds.
+ *
+ * @see #setInteractiveUiTimeoutMillis(int)
+ */
+ public int getInteractiveUiTimeoutMillis() {
+ return mInteractiveUiTimeout;
}
/** {@hide} */
@@ -815,7 +854,8 @@
parcel.writeStringArray(packageNames);
parcel.writeInt(feedbackType);
parcel.writeLong(notificationTimeout);
- parcel.writeInt(mMinimumUiTimeout);
+ parcel.writeInt(mNonInteractiveUiTimeout);
+ parcel.writeInt(mInteractiveUiTimeout);
parcel.writeInt(flags);
parcel.writeInt(crashed ? 1 : 0);
parcel.writeParcelable(mComponentName, flagz);
@@ -833,7 +873,8 @@
packageNames = parcel.readStringArray();
feedbackType = parcel.readInt();
notificationTimeout = parcel.readLong();
- mMinimumUiTimeout = parcel.readInt();
+ mNonInteractiveUiTimeout = parcel.readInt();
+ mInteractiveUiTimeout = parcel.readInt();
flags = parcel.readInt();
crashed = parcel.readInt() != 0;
mComponentName = parcel.readParcelable(this.getClass().getClassLoader());
@@ -884,7 +925,9 @@
stringBuilder.append(", ");
stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
stringBuilder.append(", ");
- stringBuilder.append("minimumUiTimeout: ").append(mMinimumUiTimeout);
+ stringBuilder.append("nonInteractiveUiTimeout: ").append(mNonInteractiveUiTimeout);
+ stringBuilder.append(", ");
+ stringBuilder.append("interactiveUiTimeout: ").append(mInteractiveUiTimeout);
stringBuilder.append(", ");
appendFlags(stringBuilder, flags);
stringBuilder.append(", ");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8d54e91..86ed267 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -120,6 +120,7 @@
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
+import android.view.intelligence.ContentCaptureEvent;
import android.view.intelligence.IntelligenceManager;
import android.widget.AdapterView;
import android.widget.Toast;
@@ -1023,6 +1024,31 @@
return mIntelligenceManager;
}
+ private void notifyIntelligenceManagerIfNeeded(@ContentCaptureEvent.EventType int event) {
+ final IntelligenceManager im = getIntelligenceManager();
+ if (im == null || !im.isContentCaptureEnabled()) {
+ return;
+ }
+ switch (event) {
+ case ContentCaptureEvent.TYPE_ACTIVITY_CREATED:
+ //TODO(b/111276913): decide whether the InteractionSessionId should be
+ // saved / restored in the activity bundle.
+ im.onActivityCreated(mToken, getComponentName());
+ break;
+ case ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED:
+ im.onActivityDestroyed();
+ break;
+ case ContentCaptureEvent.TYPE_ACTIVITY_STARTED:
+ case ContentCaptureEvent.TYPE_ACTIVITY_RESUMED:
+ case ContentCaptureEvent.TYPE_ACTIVITY_PAUSED:
+ case ContentCaptureEvent.TYPE_ACTIVITY_STOPPED:
+ im.onActivityLifecycleEvent(event);
+ break;
+ default:
+ Log.w(TAG, "notifyIntelligenceManagerIfNeeded(): invalid type " + event);
+ }
+ }
+
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
@@ -1099,11 +1125,7 @@
mRestoredFromBundle = savedInstanceState != null;
mCalled = true;
- if (getIntelligenceManager() != null) {
- //TODO(b/111276913): decide whether the screen_obs session id should be saved / restored
- // in the activity bundle.
- mIntelligenceManager.onActivityCreated(mToken, getComponentName());
- }
+ notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED);
}
/**
@@ -1337,6 +1359,7 @@
if (mAutoFillResetNeeded) {
getAutofillManager().onVisibleForAutofill();
}
+ notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED);
}
/**
@@ -1419,6 +1442,7 @@
}
}
}
+ notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED);
mCalled = true;
}
@@ -1812,6 +1836,7 @@
mAutoFillIgnoreFirstResumePause = false;
}
}
+ notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED);
mCalled = true;
}
@@ -2000,6 +2025,7 @@
getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL,
mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
}
+ notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STOPPED);
}
}
@@ -2071,9 +2097,8 @@
getApplication().dispatchActivityDestroyed(this);
- if (getIntelligenceManager() != null) {
- mIntelligenceManager.onActivityDestroyed();
- }
+ notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);
+
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9079f1a..805fb68 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -72,6 +72,7 @@
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.HardwareRenderer;
import android.graphics.ImageDecoder;
import android.hardware.display.DisplayManagerGlobal;
import android.net.ConnectivityManager;
@@ -5652,7 +5653,7 @@
int uid = Process.myUid();
String[] packages = getPackageManager().getPackagesForUid(uid);
if (packages != null) {
- ThreadedRenderer.setupDiskCache(codeCacheDir);
+ HardwareRenderer.setupDiskCache(codeCacheDir);
RenderScriptCacheDir.setupDiskCache(codeCacheDir);
}
} catch (RemoteException e) {
@@ -5887,7 +5888,8 @@
// Allow renderer debugging features if we're debuggable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
- ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+ HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+ HardwareRenderer.setPackageName(data.appInfo.packageName);
/**
* Initialize the default http proxy in this process for the reasons we set the time zone.
@@ -5954,7 +5956,7 @@
StrictMode.setThreadPolicyMask(oldMask);
}
} else {
- ThreadedRenderer.setIsolatedProcess(true);
+ HardwareRenderer.setIsolatedProcess(true);
}
// If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7df8de0..a9819fc 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -28,7 +28,9 @@
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
+import android.database.ContentObserver;
import android.media.AudioAttributes.AttributeUsage;
+import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
@@ -36,6 +38,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserManager;
+import android.provider.Settings;
import android.util.ArrayMap;
import com.android.internal.app.IAppOpsActiveCallback;
@@ -50,6 +53,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* API for interacting with "application operation" tracking.
@@ -1608,9 +1612,70 @@
* @hide
*/
public static int opToDefaultMode(int op) {
+ // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+ switch (op) {
+ // SMS permissions
+ case AppOpsManager.OP_SEND_SMS:
+ case AppOpsManager.OP_RECEIVE_SMS:
+ case AppOpsManager.OP_READ_SMS:
+ case AppOpsManager.OP_RECEIVE_WAP_PUSH:
+ case AppOpsManager.OP_RECEIVE_MMS:
+ case AppOpsManager.OP_READ_CELL_BROADCASTS:
+ // CallLog permissions
+ case AppOpsManager.OP_READ_CALL_LOG:
+ case AppOpsManager.OP_WRITE_CALL_LOG:
+ case AppOpsManager.OP_PROCESS_OUTGOING_CALLS: {
+ if (sSmsAndCallLogRestrictionEnabled.get() < 0) {
+ startWatchingSmsRestrictionEnabled();
+ }
+ if (sSmsAndCallLogRestrictionEnabled.get() == 1) {
+ return AppOpsManager.MODE_DEFAULT;
+ }
+ }
+ }
return sOpDefaultMode[op];
}
+ // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+ private static final AtomicInteger sSmsAndCallLogRestrictionEnabled = new AtomicInteger(-1);
+
+ // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+ private static void startWatchingSmsRestrictionEnabled() {
+ final Context context = ActivityThread.currentApplication();
+ if (context == null) {
+ // Should never happen
+ return;
+ }
+
+ sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
+ .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+
+ final Uri uri = Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
+ context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
+ context.getMainThreadHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
+ context.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+ }
+ });
+ }
+
+ /**
+ * Retrieve the default mode for the app op.
+ *
+ * @param appOp The app op name
+ *
+ * @return the default mode for the app op
+ *
+ * @hide
+ */
+ @SystemApi
+ public static int opToDefaultMode(@NonNull String appOp) {
+ return opToDefaultMode(strOpToOp(appOp));
+ }
+
/**
* Retrieve the human readable mode.
* @hide
@@ -2483,26 +2548,6 @@
}
}
- /**
- * Resets given app op in its default mode for app ops in the UID.
- * This applies to all apps currently in the UID or installed in this UID in the future.
- *
- * @param appOp The app op.
- * @param uid The UID for which to set the app.
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
- @SystemApi
- public void resetUidMode(String appOp, int uid, boolean force) {
- int code = strOpToOp(appOp);
- if (!(opAllowsReset(code) || force)) {
- return;
- }
- int mode = opToDefaultMode(code);
- setUidMode(code, uid, mode);
- }
-
/** @hide */
public void setUserRestriction(int code, boolean restricted, IBinder token) {
setUserRestriction(code, restricted, token, /*exceptionPackages*/null);
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index f5d5e6e..7fe21b2 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.NonNull;
import android.util.SparseIntArray;
import com.android.internal.util.function.QuadFunction;
@@ -73,4 +74,21 @@
* access to app ops for their user.
*/
public abstract void setDeviceAndProfileOwners(SparseIntArray owners);
+
+ /**
+ * Sets the app-ops mode for a certain app-op and uid.
+ *
+ * <p>Similar as {@link AppOpsManager#setMode} but does not require the package manager to be
+ * working. Hence this can be used very early during boot.
+ *
+ * <p>Only for internal callers. Does <u>not</u> verify that package name belongs to uid.
+ *
+ * @param code The op code to set.
+ * @param uid The UID for which to set.
+ * @param packageName The package for which to set.
+ * @param mode The new mode to set.
+ * @param isPrivileged If the package is privileged
+ */
+ public abstract void setMode(int code, int uid, @NonNull String packageName, int mode,
+ boolean isPrivileged);
}
diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java
index 0643414..229bee5 100644
--- a/core/java/android/app/DexLoadReporter.java
+++ b/core/java/android/app/DexLoadReporter.java
@@ -87,7 +87,7 @@
}
@Override
- public void report(List<BaseDexClassLoader> classLoadersChain, List<String> classPaths) {
+ public void report(List<ClassLoader> classLoadersChain, List<String> classPaths) {
if (classLoadersChain.size() != classPaths.size()) {
Slog.wtf(TAG, "Bad call to DexLoadReporter: argument size mismatch");
return;
@@ -113,12 +113,12 @@
registerSecondaryDexForProfiling(dexPathsForRegistration);
}
- private void notifyPackageManager(List<BaseDexClassLoader> classLoadersChain,
+ private void notifyPackageManager(List<ClassLoader> classLoadersChain,
List<String> classPaths) {
// Get the class loader names for the binder call.
List<String> classLoadersNames = new ArrayList<>(classPaths.size());
- for (BaseDexClassLoader bdc : classLoadersChain) {
- classLoadersNames.add(bdc.getClass().getName());
+ for (ClassLoader classLoader : classLoadersChain) {
+ classLoadersNames.add(classLoader.getClass().getName());
}
String packageName = ActivityThread.currentPackageName();
try {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 519a274..e759762 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -265,17 +265,6 @@
void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
boolean killProcessesBelowForeground(in String reason);
UserInfo getCurrentUser();
- /**
- * Informs ActivityManagerService that the keyguard is showing.
- *
- * @param showingKeyguard True if the keyguard is showing, false otherwise.
- * @param showingAod True if AOD is showing, false otherwise.
- * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
- * is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
- * showing is true.
- */
- void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
- int secondaryDisplayShowing);
// This is not public because you need to be very careful in how you
// manage your activity to make sure it is always the uid you expect.
int getLaunchedFromUid(in IBinder activityToken);
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index fcfcc21..6f11a76 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -245,16 +245,16 @@
ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType);
/**
- * Informs ActivityManagerService that the keyguard is showing.
+ * Informs ActivityTaskManagerService that the keyguard is showing.
*
* @param showingKeyguard True if the keyguard is showing, false otherwise.
* @param showingAod True if AOD is showing, false otherwise.
- * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
- * is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
- * showing is true.
+ * @param secondaryDisplaysShowing The displayId's of the secondary displays on which the
+ * keyguard is showing, or {@code null} if there is no such display. Only meaningful if showing
+ * is {@code true}.
*/
void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
- int secondaryDisplayShowing);
+ in int[] secondaryDisplaysShowing);
Bundle getAssistContextExtras(int requestType);
boolean launchAssistIntent(in Intent intent, int requestType, in String hint, int userHandle,
in Bundle args);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 6d464fb..4f4df5d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4457,6 +4457,7 @@
contentView.setViewVisibility(R.id.time, View.GONE);
contentView.setImageViewIcon(R.id.profile_badge, null);
contentView.setViewVisibility(R.id.profile_badge, View.GONE);
+ contentView.setViewVisibility(R.id.alerted_icon, View.GONE);
mN.mUsesStandardHeader = false;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e95f9ab..713f752 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -857,11 +857,17 @@
@Override
public BiometricManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- final IBinder binder =
- ServiceManager.getServiceOrThrow(Context.BIOMETRIC_SERVICE);
- final IBiometricService service =
- IBiometricService.Stub.asInterface(binder);
- return new BiometricManager(ctx.getOuterContext(), service);
+ if (BiometricManager.hasBiometrics(ctx)) {
+ final IBinder binder =
+ ServiceManager.getServiceOrThrow(Context.BIOMETRIC_SERVICE);
+ final IBiometricService service =
+ IBiometricService.Stub.asInterface(binder);
+ return new BiometricManager(ctx.getOuterContext(), service);
+ } else {
+ // Allow access to the manager when service is null. This saves memory
+ // on devices without biometric hardware.
+ return new BiometricManager(ctx.getOuterContext(), null);
+ }
}
});
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 096c7aa..78b7d48 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfigurationProto.ACTIVITY_TYPE;
import static android.app.WindowConfigurationProto.APP_BOUNDS;
import static android.app.WindowConfigurationProto.WINDOWING_MODE;
+import static android.view.Surface.rotationToString;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -60,6 +61,17 @@
*/
private Rect mAppBounds;
+ /**
+ * The current rotation of this window container relative to the default
+ * orientation of the display it is on (regardless of how deep in the hierarchy
+ * it is). It is used by the configuration hierarchy to apply rotation-dependent
+ * policy during bounds calculation.
+ */
+ private int mRotation = ROTATION_UNDEFINED;
+
+ /** Rotation is not defined, use the parent containers rotation. */
+ public static final int ROTATION_UNDEFINED = -1;
+
/** The current windowing mode of the configuration. */
private @WindowingMode int mWindowingMode;
@@ -161,6 +173,9 @@
/** Bit that indicates that the {@link #mAlwaysOnTop} changed.
* @hide */
public static final int WINDOW_CONFIG_ALWAYS_ON_TOP = 1 << 4;
+ /** Bit that indicates that the {@link #mRotation} changed.
+ * @hide */
+ public static final int WINDOW_CONFIG_ROTATION = 1 << 5;
/** @hide */
@IntDef(flag = true, prefix = { "WINDOW_CONFIG_" }, value = {
WINDOW_CONFIG_BOUNDS,
@@ -168,6 +183,7 @@
WINDOW_CONFIG_WINDOWING_MODE,
WINDOW_CONFIG_ACTIVITY_TYPE,
WINDOW_CONFIG_ALWAYS_ON_TOP,
+ WINDOW_CONFIG_ROTATION,
})
public @interface WindowConfig {}
@@ -194,6 +210,7 @@
dest.writeInt(mWindowingMode);
dest.writeInt(mActivityType);
dest.writeInt(mAlwaysOnTop);
+ dest.writeInt(mRotation);
}
private void readFromParcel(Parcel source) {
@@ -202,6 +219,7 @@
mWindowingMode = source.readInt();
mActivityType = source.readInt();
mAlwaysOnTop = source.readInt();
+ mRotation = source.readInt();
}
@Override
@@ -287,6 +305,14 @@
return mBounds;
}
+ public int getRotation() {
+ return mRotation;
+ }
+
+ public void setRotation(int rotation) {
+ mRotation = rotation;
+ }
+
public void setWindowingMode(@WindowingMode int windowingMode) {
mWindowingMode = windowingMode;
}
@@ -324,6 +350,7 @@
setWindowingMode(other.mWindowingMode);
setActivityType(other.mActivityType);
setAlwaysOnTop(other.mAlwaysOnTop);
+ setRotation(other.mRotation);
}
/** Set this object to completely undefined.
@@ -339,6 +366,7 @@
setWindowingMode(WINDOWING_MODE_UNDEFINED);
setActivityType(ACTIVITY_TYPE_UNDEFINED);
setAlwaysOnTop(ALWAYS_ON_TOP_UNDEFINED);
+ setRotation(ROTATION_UNDEFINED);
}
/**
@@ -375,6 +403,10 @@
changed |= WINDOW_CONFIG_ALWAYS_ON_TOP;
setAlwaysOnTop(delta.mAlwaysOnTop);
}
+ if (delta.mRotation != ROTATION_UNDEFINED && delta.mRotation != mRotation) {
+ changed |= WINDOW_CONFIG_ROTATION;
+ setRotation(delta.mRotation);
+ }
return changed;
}
@@ -418,6 +450,11 @@
changes |= WINDOW_CONFIG_ALWAYS_ON_TOP;
}
+ if ((compareUndefined || other.mRotation != ROTATION_UNDEFINED)
+ && mRotation != other.mRotation) {
+ changes |= WINDOW_CONFIG_ROTATION;
+ }
+
return changes;
}
@@ -454,6 +491,8 @@
if (n != 0) return n;
n = mAlwaysOnTop - that.mAlwaysOnTop;
if (n != 0) return n;
+ n = mRotation - that.mRotation;
+ if (n != 0) return n;
// if (n != 0) return n;
return n;
@@ -482,6 +521,7 @@
result = 31 * result + mWindowingMode;
result = 31 * result + mActivityType;
result = 31 * result + mAlwaysOnTop;
+ result = 31 * result + mRotation;
return result;
}
@@ -493,6 +533,8 @@
+ " mWindowingMode=" + windowingModeToString(mWindowingMode)
+ " mActivityType=" + activityTypeToString(mActivityType)
+ " mAlwaysOnTop=" + alwaysOnTopToString(mAlwaysOnTop)
+ + " mRotation=" + (mRotation == ROTATION_UNDEFINED
+ ? "undefined" : rotationToString(mRotation))
+ "}";
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ccf8417..2aa32c4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4227,6 +4227,15 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.os.ThermalService} for accessing the thermal service.
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ public static final String THERMAL_SERVICE = "thermalservice";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.pm.ShortcutManager} for accessing the launcher shortcut service.
*
* @see #getSystemService(String)
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6c0fa4c..aa34da8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1753,6 +1753,30 @@
"android.intent.action.MANAGE_APP_PERMISSIONS";
/**
+ * Activity action: Launch UI to manage a specific permissions of an app.
+ * <p>
+ * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permission
+ * will be managed by the launched UI.
+ * </p>
+ * <p>
+ * Input: {@link #EXTRA_PERMISSION_NAME} specifies the (individual) permission
+ * that should be managed by the launched UI.
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ *
+ * @see #EXTRA_PACKAGE_NAME
+ * @see #EXTRA_PERMISSION_NAME
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGE_APP_PERMISSION =
+ "android.intent.action.MANAGE_APP_PERMISSION";
+
+ /**
* Activity action: Launch UI to manage permissions.
* <p>
* Input: Nothing.
@@ -1882,8 +1906,8 @@
/**
* Activity action: Launch UI to manage which apps have a given permission.
* <p>
- * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access
- * to which will be managed by the launched UI.
+ * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission group
+ * which will be managed by the launched UI.
* </p>
* <p>
* Output: Nothing.
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index d3652e8..877dfee 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -57,6 +57,9 @@
*
* <p>This callback will be run on your main thread.
*
+ * <p><em>Note: This callback will not be triggered when preferences are cleared via
+ * {@link Editor#clear()}.</em>
+ *
* @param sharedPreferences The {@link SharedPreferences} that received
* the change.
* @param key The key of the preference that was changed, added, or
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 8fddb99..cef21f6 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -38,4 +38,9 @@
void commit(in IntentSender statusReceiver, boolean forTransferred);
void transfer(in String packageName);
void abandon();
+ boolean isMultiPackage();
+ int[] getChildSessionIds();
+ void addChildSessionId(in int sessionId);
+ void removeChildSessionId(in int sessionId);
+ int getParentSessionId();
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4a4de51..a87ee57 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -475,7 +475,7 @@
* @param classPaths the class paths corresponding to the class loaders names from
* {@param classLoadersNames}. The the first element corresponds to the first class loader
* and so on. A classpath is represented as a list of dex files separated by
- * {@code File.pathSeparator}.
+ * {@code File.pathSeparator}, or null if the class loader's classpath is not known.
* The dex files found in the first class path will be recorded in the usage file.
* @param loaderIsa the ISA of the loader process
*/
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index e9cfa78..8f90199 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -365,12 +365,14 @@
*/
public @NonNull Session openSession(int sessionId) throws IOException {
try {
- return new Session(mInstaller.openSession(sessionId));
+ try {
+ return new Session(mInstaller.openSession(sessionId));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
} catch (RuntimeException e) {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
}
}
@@ -769,9 +771,18 @@
* If an APK included in this session is already defined by the existing
* installation (for example, the same split name), the APK in this session
* will replace the existing APK.
+ * <p>
+ * In such a case that multiple packages need to be commited simultaneously,
+ * multiple sessions can be referenced by a single multi-package session.
+ * This session is created with no package name and calling
+ * {@link SessionParams#setMultiPackage()} with {@code true}. The
+ * individual session IDs can be added with {@link #addChildSessionId(int)}
+ * and commit of the multi-package session will result in all child sessions
+ * being committed atomically.
*/
public static class Session implements Closeable {
- private IPackageInstallerSession mSession;
+ /** {@hide} */
+ protected final IPackageInstallerSession mSession;
/** {@hide} */
public Session(IPackageInstallerSession session) {
@@ -1080,6 +1091,71 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * @return {@code true} if this session will commit more than one package when it is
+ * committed.
+ */
+ public boolean isMultiPackage() {
+ try {
+ return mSession.isMultiPackage();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return the session ID of the multi-package session that this belongs to or
+ * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
+ */
+ public int getParentSessionId() {
+ try {
+ return mSession.getParentSessionId();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return the set of session IDs that will be committed atomically when this session is
+ * committed if this is a multi-package session or null if none exist.
+ */
+ @NonNull
+ public int[] getChildSessionIds() {
+ try {
+ return mSession.getChildSessionIds();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Adds a session ID to the set of sessions that will be committed atomically
+ * when this session is committed.
+ *
+ * @param sessionId the session ID to add to this multi-package session.
+ */
+ public void addChildSessionId(int sessionId) {
+ try {
+ mSession.addChildSessionId(sessionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Removes a session ID from the set of sessions that will be committed
+ * atomically when this session is committed.
+ *
+ * @param sessionId the session ID to remove from this multi-package session.
+ */
+ public void removeChildSessionId(int sessionId) {
+ try {
+ mSession.removeChildSessionId(sessionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
/**
@@ -1149,6 +1225,8 @@
public String[] grantedRuntimePermissions;
/** {@hide} */
public String installerPackageName;
+ /** {@hide} */
+ public boolean isMultiPackage;
/**
* Construct parameters for a new package install session.
@@ -1178,6 +1256,7 @@
volumeUuid = source.readString();
grantedRuntimePermissions = source.readStringArray();
installerPackageName = source.readString();
+ isMultiPackage = source.readBoolean();
}
/**
@@ -1392,6 +1471,18 @@
this.installerPackageName = installerPackageName;
}
+ /**
+ * Set this session to be the parent of a multi-package install.
+ *
+ * A multi-package install session contains no APKs and only references other install
+ * sessions via ID. When a multi-package session is committed, all of its children
+ * are committed to the system in an atomic manner. If any children fail to install,
+ * all of them do, including the multi-package session.
+ */
+ public void setMultiPackage() {
+ this.isMultiPackage = true;
+ }
+
/** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
@@ -1408,6 +1499,7 @@
pw.printPair("volumeUuid", volumeUuid);
pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
pw.printPair("installerPackageName", installerPackageName);
+ pw.printPair("isMultiPackage", isMultiPackage);
pw.println();
}
@@ -1433,6 +1525,7 @@
dest.writeString(volumeUuid);
dest.writeStringArray(grantedRuntimePermissions);
dest.writeString(installerPackageName);
+ dest.writeBoolean(isMultiPackage);
}
public static final Parcelable.Creator<SessionParams>
@@ -1454,6 +1547,12 @@
*/
public static class SessionInfo implements Parcelable {
+ /**
+ * A session ID that does not exist or is invalid.
+ */
+ public static final int INVALID_ID = -1;
+ /** {@hide} */
+ private static final int[] NO_SESSIONS = {};
/** {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public int sessionId;
@@ -1503,6 +1602,12 @@
public String[] grantedRuntimePermissions;
/** {@hide} */
public int installFlags;
+ /** {@hide} */
+ public boolean isMultiPackage;
+ /** {@hide} */
+ public int parentSessionId = INVALID_ID;
+ /** {@hide} */
+ public int[] childSessionIds = NO_SESSIONS;
/** {@hide} */
@UnsupportedAppUsage
@@ -1531,6 +1636,12 @@
referrerUri = source.readParcelable(null);
grantedRuntimePermissions = source.readStringArray();
installFlags = source.readInt();
+ isMultiPackage = source.readBoolean();
+ parentSessionId = source.readInt();
+ childSessionIds = source.createIntArray();
+ if (childSessionIds == null) {
+ childSessionIds = NO_SESSIONS;
+ }
}
/**
@@ -1784,6 +1895,30 @@
return createDetailsIntent();
}
+ /**
+ * Returns true if this session is a multi-package session containing references to other
+ * sessions.
+ */
+ public boolean isMultiPackage() {
+ return isMultiPackage;
+ }
+
+ /**
+ * Returns the parent multi-package session ID if this session belongs to one,
+ * {@link #INVALID_ID} otherwise.
+ */
+ public int getParentSessionId() {
+ return parentSessionId;
+ }
+
+ /**
+ * Returns the set of session IDs that will be committed when this session is commited if
+ * this session is a multi-package session.
+ */
+ public int[] getChildSessionIds() {
+ return childSessionIds;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -1811,6 +1946,9 @@
dest.writeParcelable(referrerUri, flags);
dest.writeStringArray(grantedRuntimePermissions);
dest.writeInt(installFlags);
+ dest.writeBoolean(isMultiPackage);
+ dest.writeInt(parentSessionId);
+ dest.writeIntArray(childSessionIds);
}
public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 67b86c0..d3e4045 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -915,6 +915,11 @@
public static final int INSTALL_REASON_USER = 4;
/**
+ * @hide
+ */
+ public static final int INSTALL_UNKNOWN = 0;
+
+ /**
* Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
* on success.
*
@@ -2943,6 +2948,15 @@
public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 1 << 6;
/**
+ * Permission flag: The permission has not been explicitly requested by
+ * the app but has been added automatically by the system. Revoke once
+ * the app does explicitly request it.
+ *
+ * @hide
+ */
+ public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 1 << 7;
+
+ /**
* Mask for all permission flags.
*
* @hide
@@ -3593,7 +3607,10 @@
FLAG_PERMISSION_POLICY_FIXED,
FLAG_PERMISSION_REVOKE_ON_UPGRADE,
FLAG_PERMISSION_SYSTEM_FIXED,
- FLAG_PERMISSION_GRANTED_BY_DEFAULT
+ FLAG_PERMISSION_GRANTED_BY_DEFAULT,
+ /*
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESED
+ */
})
@Retention(RetentionPolicy.SOURCE)
public @interface PermissionFlags {}
@@ -5808,16 +5825,16 @@
* {@code android.permission.SUSPEND_APPS} can put any app on the device into a suspended state.
*
* <p>While in this state, the application's notifications will be hidden, any of its started
- * activities will be stopped and it will not be able to show toasts or dialogs or ring the
- * device. When the user tries to launch a suspended app, the system will, instead, show a
+ * activities will be stopped and it will not be able to show toasts or dialogs or play audio.
+ * When the user tries to launch a suspended app, the system will, instead, show a
* dialog to the user informing them that they cannot use this app while it is suspended.
*
* <p>When an app is put into this state, the broadcast action
* {@link Intent#ACTION_MY_PACKAGE_SUSPENDED} will be delivered to any of its broadcast
* receivers that included this action in their intent-filters, <em>including manifest
* receivers.</em> Similarly, a broadcast action {@link Intent#ACTION_MY_PACKAGE_UNSUSPENDED}
- * is delivered when a previously suspended app is taken out of this state.
- * </p>
+ * is delivered when a previously suspended app is taken out of this state. Apps are expected to
+ * use these to gracefully deal with transitions to and from this state.
*
* @return {@code true} if the calling package has been suspended, {@code false} otherwise.
*
@@ -6133,6 +6150,7 @@
case FLAG_PERMISSION_REVOKE_ON_UPGRADE: return "REVOKE_ON_UPGRADE";
case FLAG_PERMISSION_USER_FIXED: return "USER_FIXED";
case FLAG_PERMISSION_REVIEW_REQUIRED: return "REVIEW_REQUIRED";
+ case FLAG_PERMISSION_REVOKE_WHEN_REQUESTED: return "REVOKE_WHEN_REQUESTED";
default: return Integer.toString(flag);
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index dc33bde..7ef5264 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2435,7 +2435,7 @@
}
final int NP = PackageParser.NEW_PERMISSIONS.length;
- StringBuilder implicitPerms = null;
+ StringBuilder newPermsMsg = null;
for (int ip=0; ip<NP; ip++) {
final PackageParser.NewPermissionInfo npi
= PackageParser.NEW_PERMISSIONS[ip];
@@ -2443,19 +2443,20 @@
break;
}
if (!pkg.requestedPermissions.contains(npi.name)) {
- if (implicitPerms == null) {
- implicitPerms = new StringBuilder(128);
- implicitPerms.append(pkg.packageName);
- implicitPerms.append(": compat added ");
+ if (newPermsMsg == null) {
+ newPermsMsg = new StringBuilder(128);
+ newPermsMsg.append(pkg.packageName);
+ newPermsMsg.append(": compat added ");
} else {
- implicitPerms.append(' ');
+ newPermsMsg.append(' ');
}
- implicitPerms.append(npi.name);
+ newPermsMsg.append(npi.name);
pkg.requestedPermissions.add(npi.name);
+ pkg.implicitPermissions.add(npi.name);
}
}
- if (implicitPerms != null) {
- Slog.i(TAG, implicitPerms.toString());
+ if (newPermsMsg != null) {
+ Slog.i(TAG, newPermsMsg.toString());
}
@@ -2472,6 +2473,7 @@
final String perm = newPerms.get(in);
if (!pkg.requestedPermissions.contains(perm)) {
pkg.requestedPermissions.add(perm);
+ pkg.implicitPermissions.add(perm);
}
}
}
@@ -6394,6 +6396,9 @@
@UnsupportedAppUsage
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
+ /** Permissions requested but not in the manifest. */
+ public final ArrayList<String> implicitPermissions = new ArrayList<>();
+
@UnsupportedAppUsage
public ArrayList<String> protectedBroadcasts;
@@ -6923,6 +6928,8 @@
dest.readStringList(requestedPermissions);
internStringArrayList(requestedPermissions);
+ dest.readStringList(implicitPermissions);
+ internStringArrayList(implicitPermissions);
protectedBroadcasts = dest.createStringArrayList();
internStringArrayList(protectedBroadcasts);
@@ -7087,6 +7094,7 @@
dest.writeParcelableList(instrumentation, flags);
dest.writeStringList(requestedPermissions);
+ dest.writeStringList(implicitPermissions);
dest.writeStringList(protectedBroadcasts);
// TODO: This doesn't work: b/64295061
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index fe00604..ff58c75 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -22,6 +22,7 @@
import android.annotation.IntDef;
import android.annotation.RequiresPermission;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.util.Slog;
@@ -64,6 +65,19 @@
private final Context mContext;
private final IBiometricService mService;
+ private final boolean mHasHardware;
+
+ /**
+ * @param context
+ * @return
+ * @hide
+ */
+ public static boolean hasBiometrics(Context context) {
+ final PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
+ || pm.hasSystemFeature(PackageManager.FEATURE_IRIS)
+ || pm.hasSystemFeature(PackageManager.FEATURE_FACE);
+ }
/**
* @hide
@@ -73,6 +87,8 @@
public BiometricManager(Context context, IBiometricService service) {
mContext = context;
mService = service;
+
+ mHasHardware = hasBiometrics(context);
}
/**
@@ -93,8 +109,12 @@
throw e.rethrowFromSystemServer();
}
} else {
- Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
- return BIOMETRIC_ERROR_UNAVAILABLE;
+ if (!mHasHardware) {
+ return BIOMETRIC_ERROR_NO_HARDWARE;
+ } else {
+ Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
+ return BIOMETRIC_ERROR_UNAVAILABLE;
+ }
}
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 46e66e0..444ca87 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -22,12 +22,14 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
import android.hardware.camera2.impl.SyntheticKey;
+import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.utils.ArrayUtils;
import android.hardware.camera2.utils.TypeReference;
import android.util.Rational;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -193,6 +195,7 @@
private List<CaptureRequest.Key<?>> mAvailableSessionKeys;
private List<CaptureRequest.Key<?>> mAvailablePhysicalRequestKeys;
private List<CaptureResult.Key<?>> mAvailableResultKeys;
+ private ArrayList<RecommendedStreamConfigurationMap> mRecommendedConfigurations;
/**
* Takes ownership of the passed-in properties object
@@ -313,6 +316,103 @@
}
/**
+ * <p>Retrieve camera device recommended stream configuration map
+ * {@link RecommendedStreamConfigurationMap} for a given use case.</p>
+ *
+ * <p>The stream configurations advertised here are efficient in terms of power and performance
+ * for common use cases like preview, video, snapshot, etc. The recommended maps are usually
+ * only small subsets of the exhaustive list provided in
+ * {@link #SCALER_STREAM_CONFIGURATION_MAP} and suggested for a particular use case by the
+ * camera device implementation. For further information about the expected configurations in
+ * various scenarios please refer to:
+ * <ul>
+ * <li>{@link RecommendedStreamConfigurationMap#USECASE_PREVIEW}</li>
+ * <li>{@link RecommendedStreamConfigurationMap#USECASE_RECORD}</li>
+ * <li>{@link RecommendedStreamConfigurationMap#USECASE_VIDEO_SNAPSHOT}</li>
+ * <li>{@link RecommendedStreamConfigurationMap#USECASE_SNAPSHOT}</li>
+ * <li>{@link RecommendedStreamConfigurationMap#USECASE_RAW}</li>
+ * <li>{@link RecommendedStreamConfigurationMap#USECASE_ZSL}</li>
+ * </ul>
+ * </p>
+ *
+ * <p>For example on how this can be used by camera clients to find out the maximum recommended
+ * preview and snapshot resolution, consider the following pseudo-code:
+ * </p>
+ * <pre><code>
+ * public static Size getMaxSize(Size... sizes) {
+ * if (sizes == null || sizes.length == 0) {
+ * throw new IllegalArgumentException("sizes was empty");
+ * }
+ *
+ * Size sz = sizes[0];
+ * for (Size size : sizes) {
+ * if (size.getWidth() * size.getHeight() > sz.getWidth() * sz.getHeight()) {
+ * sz = size;
+ * }
+ * }
+ *
+ * return sz;
+ * }
+ *
+ * CameraCharacteristics characteristics =
+ * cameraManager.getCameraCharacteristics(cameraId);
+ * RecommendedStreamConfigurationMap previewConfig =
+ * characteristics.getRecommendedStreamConfigurationMap(
+ * RecommendedStreamConfigurationMap.USECASE_PREVIEW);
+ * RecommendedStreamConfigurationMap snapshotConfig =
+ * characteristics.getRecommendedStreamConfigurationMap(
+ * RecommendedStreamConfigurationMap.USECASE_SNAPSHOT);
+ *
+ * if ((previewConfig != null) && (snapshotConfig != null)) {
+ *
+ * Set<Size> snapshotSizeSet = snapshotConfig.getOutputSizes(
+ * ImageFormat.JPEG);
+ * Size[] snapshotSizes = new Size[snapshotSizeSet.size()];
+ * snapshotSizes = snapshotSizeSet.toArray(snapshotSizes);
+ * Size suggestedMaxJpegSize = getMaxSize(snapshotSizes);
+ *
+ * Set<Size> previewSizeSet = snapshotConfig.getOutputSizes(
+ * ImageFormat.PRIVATE);
+ * Size[] previewSizes = new Size[previewSizeSet.size()];
+ * previewSizes = previewSizeSet.toArray(previewSizes);
+ * Size suggestedMaxPreviewSize = getMaxSize(previewSizes);
+ * }
+ *
+ * </code></pre>
+ *
+ * <p>Similar logic can be used for other use cases as well.</p>
+ *
+ * <p>Support for recommended stream configurations is optional. In case there a no
+ * suggested configurations for the particular use case, please refer to
+ * {@link #SCALER_STREAM_CONFIGURATION_MAP} for the exhaustive available list.</p>
+ *
+ * @param usecase Use case id.
+ *
+ * @throws IllegalArgumentException In case the use case argument is invalid.
+ * @return Valid {@link RecommendedStreamConfigurationMap} or null in case the camera device
+ * doesn't have any recommendation for this use case or the recommended configurations
+ * are invalid.
+ */
+ public RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap(
+ @RecommendedStreamConfigurationMap.RecommendedUsecase int usecase) {
+ if (((usecase >= RecommendedStreamConfigurationMap.USECASE_PREVIEW) &&
+ (usecase <= RecommendedStreamConfigurationMap.USECASE_RAW)) ||
+ ((usecase >= RecommendedStreamConfigurationMap.USECASE_VENDOR_START) &&
+ (usecase < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT))) {
+ if (mRecommendedConfigurations == null) {
+ mRecommendedConfigurations = mProperties.getRecommendedStreamConfigurations();
+ if (mRecommendedConfigurations == null) {
+ return null;
+ }
+ }
+
+ return mRecommendedConfigurations.get(usecase);
+ }
+
+ throw new IllegalArgumentException(String.format("Invalid use case: %d", usecase));
+ }
+
+ /**
* <p>Returns a subset of {@link #getAvailableCaptureRequestKeys} keys that the
* camera device can pass as part of the capture session initialization.</p>
*
@@ -329,7 +429,7 @@
* but clients should be aware and expect delays during their application.
* An example usage scenario could look like this:</p>
* <ul>
- * <li>The camera client starts by quering the session parameter key list via
+ * <li>The camera client starts by querying the session parameter key list via
* {@link android.hardware.camera2.CameraCharacteristics#getAvailableSessionKeys }.</li>
* <li>Before triggering the capture session create sequence, a capture request
* must be built via {@link CameraDevice#createCaptureRequest } using an
@@ -1583,7 +1683,7 @@
* {@link android.graphics.ImageFormat#RAW12 RAW12}.</li>
* <li>Processed (but not-stalling): any non-RAW format without a stall duration. Typically
* {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888},
- * {@link android.graphics.ImageFormat#NV21 NV21}, or {@link android.graphics.ImageFormat#YV12 YV12}.</li>
+ * {@link android.graphics.ImageFormat#NV21 NV21}, {@link android.graphics.ImageFormat#YV12 YV12}, or {@link android.graphics.ImageFormat#Y8 Y8} .</li>
* </ul>
* <p><b>Range of valid values:</b><br></p>
* <p>For processed (and stalling) format streams, >= 1.</p>
@@ -1646,6 +1746,7 @@
* <li>{@link android.graphics.ImageFormat#NV21 NV21}</li>
* <li>{@link android.graphics.ImageFormat#YV12 YV12}</li>
* <li>Implementation-defined formats, i.e. {@link android.hardware.camera2.params.StreamConfigurationMap#isOutputSupportedFor(Class) }</li>
+ * <li>{@link android.graphics.ImageFormat#Y8 Y8}</li>
* </ul>
* <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a
* processed format -- it will return 0 for a non-stalling stream.</p>
@@ -2122,6 +2223,35 @@
* or output will never hurt maximum frame rate (i.e. {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration getOutputStallDuration(ImageFormat.PRIVATE, size)} is always 0),</p>
* <p>Attempting to configure an input stream with output streams not
* listed as available in this map is not valid.</p>
+ * <p>Additionally, if the camera device is MONOCHROME with Y8 support, it will also support
+ * the following map of formats if its dependent capability
+ * ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}) is supported:</p>
+ * <table>
+ * <thead>
+ * <tr>
+ * <th align="left">Input Format</th>
+ * <th align="left">Output Format</th>
+ * <th align="left">Capability</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td align="left">{@link android.graphics.ImageFormat#PRIVATE }</td>
+ * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+ * <td align="left">PRIVATE_REPROCESSING</td>
+ * </tr>
+ * <tr>
+ * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+ * <td align="left">{@link android.graphics.ImageFormat#JPEG }</td>
+ * <td align="left">YUV_REPROCESSING</td>
+ * </tr>
+ * <tr>
+ * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+ * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+ * <td align="left">YUV_REPROCESSING</td>
+ * </tr>
+ * </tbody>
+ * </table>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
@@ -2297,6 +2427,7 @@
* <li>{@link android.graphics.ImageFormat#YUV_420_888 }</li>
* <li>{@link android.graphics.ImageFormat#RAW10 }</li>
* <li>{@link android.graphics.ImageFormat#RAW12 }</li>
+ * <li>{@link android.graphics.ImageFormat#Y8 }</li>
* </ul>
* <p>All other formats may or may not have an allowed stall duration on
* a per-capability basis; refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
@@ -2447,6 +2578,37 @@
new Key<Integer>("android.scaler.croppingType", int.class);
/**
+ * <p>Recommended stream configurations for common client use cases.</p>
+ * <p>Optional subset of the android.scaler.availableStreamConfigurations that contains
+ * similar tuples listed as
+ * (i.e. width, height, format, output/input stream, usecase bit field).
+ * Camera devices will be able to suggest particular stream configurations which are
+ * power and performance efficient for specific use cases. For more information about
+ * retrieving the suggestions see
+ * {@link android.hardware.camera2.CameraCharacteristics#getRecommendedStreamConfigurationMap }.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * @hide
+ */
+ public static final Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]> SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS =
+ new Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]>("android.scaler.availableRecommendedStreamConfigurations", android.hardware.camera2.params.RecommendedStreamConfiguration[].class);
+
+ /**
+ * <p>Recommended mappings of image formats that are supported by this
+ * camera device for input streams, to their corresponding output formats.</p>
+ * <p>This is a recommended subset of the complete list of mappings found in
+ * android.scaler.availableInputOutputFormatsMap. The same requirements apply here as well.
+ * The list however doesn't need to contain all available and supported mappings. Instead of
+ * this developers must list only recommended and efficient entries.
+ * If set, the information will be available in the ZERO_SHUTTER_LAG recommended stream
+ * configuration see
+ * {@link android.hardware.camera2.CameraCharacteristics#getRecommendedStreamConfigurationMap }.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * @hide
+ */
+ public static final Key<android.hardware.camera2.params.ReprocessFormatsMap> SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP =
+ new Key<android.hardware.camera2.params.ReprocessFormatsMap>("android.scaler.availableRecommendedInputOutputFormatsMap", android.hardware.camera2.params.ReprocessFormatsMap.class);
+
+ /**
* <p>The area of the image sensor which corresponds to active pixels after any geometric
* distortion correction has been applied.</p>
* <p>This is the rectangle representing the size of the active region of the sensor (i.e.
@@ -3487,6 +3649,21 @@
new Key<Boolean>("android.depth.depthIsExclusive", boolean.class);
/**
+ * <p>Recommended depth stream configurations for common client use cases.</p>
+ * <p>Optional subset of the android.depth.availableDepthStreamConfigurations that
+ * contains similar tuples listed as
+ * (i.e. width, height, format, output/input stream, usecase bit field).
+ * Camera devices will be able to suggest particular depth stream configurations which are
+ * power and performance efficient for specific use cases. For more information about
+ * retrieving the suggestions see
+ * {@link android.hardware.camera2.CameraCharacteristics#getRecommendedStreamConfigurationMap }.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * @hide
+ */
+ public static final Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]> DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS =
+ new Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]>("android.depth.availableRecommendedDepthStreamConfigurations", android.hardware.camera2.params.RecommendedStreamConfiguration[].class);
+
+ /**
* <p>String containing the ids of the underlying physical cameras.</p>
* <p>For a logical camera, this is concatenation of all underlying physical camera ids.
* The null terminator for physical camera id must be preserved so that the whole string
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ce88697..ac00f14 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -356,6 +356,12 @@
* </table><br>
* </p>
*
+ * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
+ * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME})
+ * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
+ * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level
+ * and capabilities.</p>
+ *
* <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
* support at least the following stream combinations in addition to those for
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index d4dc181..ffc2264 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -539,6 +539,8 @@
* <li>{@link android.graphics.ImageFormat#PRIVATE } will be reprocessable into both
* {@link android.graphics.ImageFormat#YUV_420_888 } and
* {@link android.graphics.ImageFormat#JPEG } formats.</li>
+ * <li>For a MONOCHROME camera supporting Y8 format, {@link android.graphics.ImageFormat#PRIVATE } will be reprocessable into
+ * {@link android.graphics.ImageFormat#Y8 }.</li>
* <li>The maximum available resolution for PRIVATE streams
* (both input/output) will match the maximum available
* resolution of JPEG streams.</li>
@@ -612,7 +614,7 @@
* then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at
* least one resolution >= 8 megapixels, with a minimum frame duration of <= 1/20
* s.</p>
- * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be
+ * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, {@link android.graphics.ImageFormat#Y8 }, then those can also be
* captured at the same rate as the maximum-size YUV_420_888 resolution is.</p>
* <p>If the device supports the PRIVATE_REPROCESSING capability, then the same guarantees
* as for the YUV_420_888 format also apply to the {@link android.graphics.ImageFormat#PRIVATE } format.</p>
@@ -646,6 +648,8 @@
* {@link android.graphics.ImageFormat#YUV_420_888 } and {@link android.graphics.ImageFormat#JPEG } formats.</li>
* <li>The maximum available resolution for {@link android.graphics.ImageFormat#YUV_420_888 } streams (both input/output) will match the
* maximum available resolution of {@link android.graphics.ImageFormat#JPEG } streams.</li>
+ * <li>For a MONOCHROME camera with Y8 format support, all the requirements mentioned
+ * above for YUV_420_888 apply for Y8 format as well.</li>
* <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li>
* <li>Only the below controls are effective for reprocessing requests and will be present
* in capture results. The reprocess requests are from the original capture results
@@ -692,8 +696,8 @@
* <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li>
* <li>As of Android P, the {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} entry is listed by this device.</li>
* <li>A LIMITED camera with only the DEPTH_OUTPUT capability does not have to support
- * normal YUV_420_888, JPEG, and PRIV-format outputs. It only has to support the DEPTH16
- * format.</li>
+ * normal YUV_420_888, Y8, JPEG, and PRIV-format outputs. It only has to support the
+ * DEPTH16 format.</li>
* </ul>
* <p>Generally, depth output operates at a slower frame rate than standard color capture,
* so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
@@ -877,6 +881,10 @@
/**
* <p>The camera device is a monochrome camera that doesn't contain a color filter array,
* and the pixel values on U and V planes are all 128.</p>
+ * <p>A MONOCHROME camera must support the guaranteed stream combinations required for
+ * its device level and capabilities. Additionally, if the monochrome camera device
+ * supports Y8 format, all mandatory stream combination requirements related to {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888} apply
+ * to {@link android.graphics.ImageFormat#Y8 Y8} as well.</p>
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 4a20468..2744e91 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -3277,8 +3277,8 @@
* will not slow down capture rate when applying correction. FAST may be the same as OFF if
* any correction at all would slow down capture rate. Every output stream will have a
* similar amount of enhancement applied.</p>
- * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
- * applied to any RAW output.</p>
+ * <p>The correction only applies to processed outputs such as YUV, Y8, JPEG, or DEPTH16; it is
+ * not applied to any RAW output.</p>
* <p>This control will be on by default on devices that support this control. Applications
* disabling distortion correction need to pay extra attention with the coordinate system of
* metering regions, crop region, and face rectangles. When distortion correction is OFF,
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index a7e185c..2b67f3e 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -4620,8 +4620,8 @@
* will not slow down capture rate when applying correction. FAST may be the same as OFF if
* any correction at all would slow down capture rate. Every output stream will have a
* similar amount of enhancement applied.</p>
- * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
- * applied to any RAW output.</p>
+ * <p>The correction only applies to processed outputs such as YUV, Y8, JPEG, or DEPTH16; it is
+ * not applied to any RAW output.</p>
* <p>This control will be on by default on devices that support this control. Applications
* disabling distortion correction need to pay extra attention with the coordinate system of
* metering regions, crop region, and face rectangles. When distortion correction is OFF,
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 0610d7a..f81bd13 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -21,6 +21,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.marshal.MarshalQueryable;
@@ -38,6 +39,7 @@
import android.hardware.camera2.marshal.impl.MarshalQueryableParcelable;
import android.hardware.camera2.marshal.impl.MarshalQueryablePrimitive;
import android.hardware.camera2.marshal.impl.MarshalQueryableRange;
+import android.hardware.camera2.marshal.impl.MarshalQueryableRecommendedStreamConfiguration;
import android.hardware.camera2.marshal.impl.MarshalQueryableRect;
import android.hardware.camera2.marshal.impl.MarshalQueryableReprocessFormatsMap;
import android.hardware.camera2.marshal.impl.MarshalQueryableRggbChannelVector;
@@ -50,6 +52,8 @@
import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.OisSample;
+import android.hardware.camera2.params.RecommendedStreamConfiguration;
+import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
import android.hardware.camera2.params.ReprocessFormatsMap;
import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.params.StreamConfigurationDuration;
@@ -911,6 +915,252 @@
return true;
}
+ private void parseRecommendedConfigurations(RecommendedStreamConfiguration[] configurations,
+ StreamConfigurationMap fullMap, boolean isDepth,
+ ArrayList<ArrayList<StreamConfiguration>> /*out*/streamConfigList,
+ ArrayList<ArrayList<StreamConfigurationDuration>> /*out*/streamDurationList,
+ ArrayList<ArrayList<StreamConfigurationDuration>> /*out*/streamStallList,
+ boolean[] /*out*/supportsPrivate) {
+
+ streamConfigList.ensureCapacity(RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+ streamDurationList.ensureCapacity(RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+ streamStallList.ensureCapacity(RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+ for (int i = 0; i < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT; i++) {
+ streamConfigList.add(new ArrayList<StreamConfiguration> ());
+ streamDurationList.add(new ArrayList<StreamConfigurationDuration> ());
+ streamStallList.add(new ArrayList<StreamConfigurationDuration> ());
+ }
+
+ for (RecommendedStreamConfiguration c : configurations) {
+ int width = c.getWidth();
+ int height = c.getHeight();
+ int internalFormat = c.getFormat();
+ int publicFormat =
+ (isDepth) ? StreamConfigurationMap.depthFormatToPublic(internalFormat) :
+ StreamConfigurationMap.imageFormatToPublic(internalFormat);
+ Size sz = new Size(width, height);
+ int usecaseBitmap = c.getUsecaseBitmap();
+
+ if (!c.isInput()) {
+ StreamConfigurationDuration minDurationConfiguration = null;
+ StreamConfigurationDuration stallDurationConfiguration = null;
+
+ StreamConfiguration streamConfiguration = new StreamConfiguration(internalFormat,
+ width, height, /*input*/ false);
+
+ long minFrameDuration = fullMap.getOutputMinFrameDuration(publicFormat, sz);
+ if (minFrameDuration > 0) {
+ minDurationConfiguration = new StreamConfigurationDuration(internalFormat,
+ width, height, minFrameDuration);
+ }
+
+ long stallDuration = fullMap.getOutputStallDuration(publicFormat, sz);
+ if (stallDuration > 0) {
+ stallDurationConfiguration = new StreamConfigurationDuration(internalFormat,
+ width, height, stallDuration);
+ }
+
+ for (int i = 0; i < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT; i++) {
+ if ((usecaseBitmap & (1 << i)) != 0) {
+ ArrayList<StreamConfiguration> sc = streamConfigList.get(i);
+ sc.add(streamConfiguration);
+
+ if (minFrameDuration > 0) {
+ ArrayList<StreamConfigurationDuration> scd = streamDurationList.get(i);
+ scd.add(minDurationConfiguration);
+ }
+
+ if (stallDuration > 0) {
+ ArrayList<StreamConfigurationDuration> scs = streamStallList.get(i);
+ scs.add(stallDurationConfiguration);
+ }
+
+ if ((supportsPrivate != null) && !supportsPrivate[i] &&
+ (publicFormat == ImageFormat.PRIVATE)) {
+ supportsPrivate[i] = true;
+ }
+ }
+ }
+ } else {
+ if (usecaseBitmap != (1 << RecommendedStreamConfigurationMap.USECASE_ZSL)) {
+ throw new IllegalArgumentException("Recommended input stream configurations " +
+ "should only be advertised in the ZSL use case!");
+ }
+
+ ArrayList<StreamConfiguration> sc = streamConfigList.get(
+ RecommendedStreamConfigurationMap.USECASE_ZSL);
+ sc.add(new StreamConfiguration(internalFormat,
+ width, height, /*input*/ true));
+ }
+ }
+ }
+
+ private class StreamConfigurationData {
+ StreamConfiguration [] streamConfigurationArray = null;
+ StreamConfigurationDuration [] minDurationArray = null;
+ StreamConfigurationDuration [] stallDurationArray = null;
+ }
+
+ public void initializeStreamConfigurationData(ArrayList<StreamConfiguration> sc,
+ ArrayList<StreamConfigurationDuration> scd, ArrayList<StreamConfigurationDuration> scs,
+ StreamConfigurationData /*out*/scData) {
+ if ((scData == null) || (sc == null)) {
+ return;
+ }
+
+ scData.streamConfigurationArray = new StreamConfiguration[sc.size()];
+ scData.streamConfigurationArray = sc.toArray(scData.streamConfigurationArray);
+
+ if ((scd != null) && !scd.isEmpty()) {
+ scData.minDurationArray = new StreamConfigurationDuration[scd.size()];
+ scData.minDurationArray = scd.toArray(scData.minDurationArray);
+ } else {
+ scData.minDurationArray = new StreamConfigurationDuration[0];
+ }
+
+ if ((scs != null) && !scs.isEmpty()) {
+ scData.stallDurationArray = new StreamConfigurationDuration[scs.size()];
+ scData.stallDurationArray = scs.toArray(scData.stallDurationArray);
+ } else {
+ scData.stallDurationArray = new StreamConfigurationDuration[0];
+ }
+ }
+
+ /**
+ * Retrieve the list of recommended stream configurations.
+ *
+ * @return A list of recommended stream configuration maps for each common use case or null
+ * in case the recommended stream configurations are invalid or incomplete.
+ * @hide
+ */
+ public ArrayList<RecommendedStreamConfigurationMap> getRecommendedStreamConfigurations() {
+ RecommendedStreamConfiguration[] configurations = getBase(
+ CameraCharacteristics.SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS);
+ RecommendedStreamConfiguration[] depthConfigurations = getBase(
+ CameraCharacteristics.DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS);
+ if ((configurations == null) && (depthConfigurations == null)) {
+ return null;
+ }
+
+ StreamConfigurationMap fullMap = getStreamConfigurationMap();
+ ArrayList<RecommendedStreamConfigurationMap> recommendedConfigurations =
+ new ArrayList<RecommendedStreamConfigurationMap> ();
+
+ ArrayList<ArrayList<StreamConfiguration>> streamConfigList =
+ new ArrayList<ArrayList<StreamConfiguration>>();
+ ArrayList<ArrayList<StreamConfigurationDuration>> streamDurationList =
+ new ArrayList<ArrayList<StreamConfigurationDuration>>();
+ ArrayList<ArrayList<StreamConfigurationDuration>> streamStallList =
+ new ArrayList<ArrayList<StreamConfigurationDuration>>();
+ boolean[] supportsPrivate =
+ new boolean[RecommendedStreamConfigurationMap.MAX_USECASE_COUNT];
+ try {
+ if (configurations != null) {
+ parseRecommendedConfigurations(configurations, fullMap, /*isDepth*/ false,
+ streamConfigList, streamDurationList, streamStallList, supportsPrivate);
+ }
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed parsing the recommended stream configurations!");
+ return null;
+ }
+
+ ArrayList<ArrayList<StreamConfiguration>> depthStreamConfigList =
+ new ArrayList<ArrayList<StreamConfiguration>>();
+ ArrayList<ArrayList<StreamConfigurationDuration>> depthStreamDurationList =
+ new ArrayList<ArrayList<StreamConfigurationDuration>>();
+ ArrayList<ArrayList<StreamConfigurationDuration>> depthStreamStallList =
+ new ArrayList<ArrayList<StreamConfigurationDuration>>();
+ if (depthConfigurations != null) {
+ try {
+ parseRecommendedConfigurations(depthConfigurations, fullMap, /*isDepth*/ true,
+ depthStreamConfigList, depthStreamDurationList, depthStreamStallList,
+ /*supportsPrivate*/ null);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed parsing the recommended depth stream configurations!");
+ return null;
+ }
+ }
+
+ ReprocessFormatsMap inputOutputFormatsMap = getBase(
+ CameraCharacteristics.SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP);
+ HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
+ CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
+ boolean listHighResolution = isBurstSupported();
+ recommendedConfigurations.ensureCapacity(
+ RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+ for (int i = 0; i < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT; i++) {
+ StreamConfigurationData scData = new StreamConfigurationData();
+ if (configurations != null) {
+ initializeStreamConfigurationData(streamConfigList.get(i),
+ streamDurationList.get(i), streamStallList.get(i), scData);
+ }
+
+ StreamConfigurationData depthScData = new StreamConfigurationData();
+ if (depthConfigurations != null) {
+ initializeStreamConfigurationData(depthStreamConfigList.get(i),
+ depthStreamDurationList.get(i), depthStreamStallList.get(i), depthScData);
+ }
+
+ if ((scData.streamConfigurationArray == null) &&
+ (depthScData.streamConfigurationArray == null)) {
+ recommendedConfigurations.add(null);
+ continue;
+ }
+
+ StreamConfigurationMap map = null;
+ switch (i) {
+ case RecommendedStreamConfigurationMap.USECASE_PREVIEW:
+ case RecommendedStreamConfigurationMap.USECASE_RAW:
+ case RecommendedStreamConfigurationMap.USECASE_VIDEO_SNAPSHOT:
+ map = new StreamConfigurationMap(scData.streamConfigurationArray,
+ scData.minDurationArray, scData.stallDurationArray,
+ /*depthconfiguration*/ null, /*depthminduration*/ null,
+ /*depthstallduration*/ null, /*highspeedvideoconfigurations*/ null,
+ /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
+ break;
+ case RecommendedStreamConfigurationMap.USECASE_RECORD:
+ map = new StreamConfigurationMap(scData.streamConfigurationArray,
+ scData.minDurationArray, scData.stallDurationArray,
+ /*depthconfiguration*/ null, /*depthminduration*/ null,
+ /*depthstallduration*/ null, highSpeedVideoConfigurations,
+ /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
+ break;
+ case RecommendedStreamConfigurationMap.USECASE_ZSL:
+ map = new StreamConfigurationMap(scData.streamConfigurationArray,
+ scData.minDurationArray, scData.stallDurationArray,
+ depthScData.streamConfigurationArray, depthScData.minDurationArray,
+ depthScData.stallDurationArray, /*highSpeedVideoConfigurations*/ null,
+ inputOutputFormatsMap, listHighResolution, supportsPrivate[i]);
+ break;
+ default:
+ map = new StreamConfigurationMap(scData.streamConfigurationArray,
+ scData.minDurationArray, scData.stallDurationArray,
+ depthScData.streamConfigurationArray, depthScData.minDurationArray,
+ depthScData.stallDurationArray, /*highSpeedVideoConfigurations*/ null,
+ /*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]);
+ }
+
+ recommendedConfigurations.add(new RecommendedStreamConfigurationMap(map, /*usecase*/i,
+ supportsPrivate[i]));
+ }
+
+ return recommendedConfigurations;
+ }
+
+ private boolean isBurstSupported() {
+ boolean ret = false;
+
+ int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ for (int capability : capabilities) {
+ if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+ }
+
private StreamConfigurationMap getStreamConfigurationMap() {
StreamConfiguration[] configurations = getBase(
CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
@@ -928,14 +1178,7 @@
CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
ReprocessFormatsMap inputOutputFormatsMap = getBase(
CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP);
- int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
- boolean listHighResolution = false;
- for (int capability : capabilities) {
- if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
- listHighResolution = true;
- break;
- }
- }
+ boolean listHighResolution = isBurstSupported();
return new StreamConfigurationMap(
configurations, minFrameDurations, stallDurations,
depthConfigurations, depthMinFrameDurations, depthStallDurations,
@@ -1399,6 +1642,7 @@
new MarshalQueryableRggbChannelVector(),
new MarshalQueryableBlackLevelPattern(),
new MarshalQueryableHighSpeedVideoConfiguration(),
+ new MarshalQueryableRecommendedStreamConfiguration(),
// generic parcelable marshaler (MUST BE LAST since it has lowest priority)
new MarshalQueryableParcelable(),
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableRecommendedStreamConfiguration.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableRecommendedStreamConfiguration.java
new file mode 100644
index 0000000..22a76b7
--- /dev/null
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableRecommendedStreamConfiguration.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 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.hardware.camera2.marshal.impl;
+
+import android.hardware.camera2.marshal.Marshaler;
+import android.hardware.camera2.marshal.MarshalQueryable;
+import android.hardware.camera2.params.RecommendedStreamConfiguration;
+import android.hardware.camera2.utils.TypeReference;
+
+import static android.hardware.camera2.impl.CameraMetadataNative.*;
+import static android.hardware.camera2.marshal.MarshalHelpers.*;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Marshaler for {@code android.scaler.availableRecommendedStreamConfigurations} custom class
+ * {@link RecommendedStreamConfiguration}
+ *
+ * <p>Data is stored as {@code (width, height, format, input, usecaseBitmap)} tuples (int32).</p>
+ */
+public class MarshalQueryableRecommendedStreamConfiguration
+ implements MarshalQueryable<RecommendedStreamConfiguration> {
+ private static final int SIZE = SIZEOF_INT32 * 5;
+
+ private class MarshalerRecommendedStreamConfiguration
+ extends Marshaler<RecommendedStreamConfiguration> {
+ protected MarshalerRecommendedStreamConfiguration(
+ TypeReference<RecommendedStreamConfiguration> typeReference, int nativeType) {
+ super(MarshalQueryableRecommendedStreamConfiguration.this, typeReference, nativeType);
+ }
+
+ @Override
+ public void marshal(RecommendedStreamConfiguration value, ByteBuffer buffer) {
+ buffer.putInt(value.getWidth());
+ buffer.putInt(value.getHeight());
+ buffer.putInt(value.getFormat());
+ buffer.putInt(value.isInput() ? 1 : 0);
+ buffer.putInt(value.getUsecaseBitmap());
+ }
+
+ @Override
+ public RecommendedStreamConfiguration unmarshal(ByteBuffer buffer) {
+ int width = buffer.getInt();
+ int height = buffer.getInt();
+ int format = buffer.getInt();
+ boolean input = buffer.getInt() != 0;
+ int usecaseBitmap = buffer.getInt();
+
+ return new RecommendedStreamConfiguration(format, width, height, input, usecaseBitmap);
+ }
+
+ @Override
+ public int getNativeSize() {
+ return SIZE;
+ }
+
+ }
+
+ @Override
+ public Marshaler<RecommendedStreamConfiguration> createMarshaler(
+ TypeReference<RecommendedStreamConfiguration> managedType, int nativeType) {
+ return new MarshalerRecommendedStreamConfiguration(managedType, nativeType);
+ }
+
+ @Override
+ public boolean isTypeMappingSupported(TypeReference<RecommendedStreamConfiguration> managedType,
+ int nativeType) {
+ return nativeType ==
+ TYPE_INT32 && managedType.getType().equals(RecommendedStreamConfiguration.class);
+ }
+}
diff --git a/core/java/android/hardware/camera2/params/RecommendedStreamConfiguration.java b/core/java/android/hardware/camera2/params/RecommendedStreamConfiguration.java
new file mode 100644
index 0000000..5dd0517
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/RecommendedStreamConfiguration.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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.hardware.camera2.params;
+
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.utils.HashCodeHelpers;
+
+/**
+ * Immutable class to store the recommended stream configurations to set up
+ * {@link android.view.Surface Surfaces} for creating a {@link CameraCaptureSession capture session}
+ * with {@link CameraDevice#createCaptureSession}.
+ *
+ * @see CameraCharacteristics#getRecommendedStreamConfigurationMap
+ *
+ * @hide
+ */
+public final class RecommendedStreamConfiguration extends StreamConfiguration{
+
+ /**
+ * Create a new {@link RecommendedStreamConfiguration}.
+ *
+ * @param format image format
+ * @param width image width, in pixels (positive)
+ * @param height image height, in pixels (positive)
+ * @param input true if this is an input configuration, false for output configurations
+ * @param usecaseBitmap Use case bitmap
+ *
+ * @throws IllegalArgumentException
+ * if width/height were not positive
+ * or if the format was not user-defined in ImageFormat/PixelFormat
+ * (IMPL_DEFINED is ok)
+ *
+ * @hide
+ */
+ public RecommendedStreamConfiguration(
+ final int format, final int width, final int height, final boolean input, final int
+ usecaseBitmap) {
+ super(format, width, height, input);
+ mUsecaseBitmap = usecaseBitmap;
+ }
+
+ /**
+ * Return usecase bitmap.
+ *
+ * @return usecase bitmap
+ */
+ public int getUsecaseBitmap() {
+ return mUsecaseBitmap;
+ }
+
+ /**
+ * Check if this {@link RecommendedStreamConfiguration} is equal to another
+ * {@link RecommendedStreamConfiguration}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof RecommendedStreamConfiguration) {
+ final RecommendedStreamConfiguration other = (RecommendedStreamConfiguration) obj;
+ return mFormat == other.mFormat &&
+ mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mUsecaseBitmap == other.mUsecaseBitmap &&
+ mInput == other.mInput;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0, mUsecaseBitmap);
+ }
+
+ private final int mUsecaseBitmap;
+}
diff --git a/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
new file mode 100644
index 0000000..59e4a33
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2018 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.hardware.camera2.params;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.util.ArraySet;
+import android.util.Range;
+import android.util.Size;
+import android.view.Surface;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Immutable class to store the recommended stream configurations to set up
+ * {@link android.view.Surface Surfaces} for creating a
+ * {@link android.hardware.camera2.CameraCaptureSession capture session} with
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession}.
+ *
+ * <p>The recommended list does not replace or deprecate the exhaustive complete list found in
+ * {@link StreamConfigurationMap}. It is a suggestion about available power and performance
+ * efficient stream configurations for a specific use case. Per definition it is only a subset
+ * of {@link StreamConfigurationMap} and can be considered by developers for optimization
+ * purposes.</p>
+ *
+ * <p>This also duplicates the minimum frame durations and stall durations from the
+ * {@link StreamConfigurationMap} for each format/size combination that can be used to calculate
+ * effective frame rate when submitting multiple captures.
+ * </p>
+ *
+ * <p>An instance of this object is available by invoking
+ * {@link CameraCharacteristics#getRecommendedStreamConfigurationMap} and passing a respective
+ * usecase id. For more information about supported use case constants see
+ * {@link #USECASE_PREVIEW}.</p>
+ *
+ * <pre><code>{@code
+ * CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
+ * RecommendedStreamConfigurationMap configs = characteristics.getRecommendedStreamConfigurationMap(
+ * RecommendedStreamConfigurationMap.USECASE_PREVIEW);
+ * }</code></pre>
+ *
+ * @see CameraCharacteristics#getRecommendedStreamConfigurationMap
+ * @see CameraDevice#createCaptureSession
+ */
+public final class RecommendedStreamConfigurationMap {
+
+ private static final String TAG = "RecommendedStreamConfigurationMap";
+ private int mUsecase;
+ private boolean mSupportsPrivate;
+ private StreamConfigurationMap mRecommendedMap;
+
+ /** @hide */
+ public static final int MAX_USECASE_COUNT = 32;
+
+ /**
+ * The recommended stream configuration map for use case preview must contain a subset of
+ * efficient, non-stalling configurations that must include both
+ * {@link android.graphics.ImageFormat#PRIVATE} and
+ * {@link android.graphics.ImageFormat#YUV_420_888} output formats. Even if available for the
+ * camera device, high speed or input configurations will be absent.
+ */
+ public static final int USECASE_PREVIEW = 0x0;
+
+ /**
+ * The recommended stream configuration map for recording must contain a subset of efficient
+ * video configurations that include {@link android.graphics.ImageFormat#PRIVATE}
+ * output format for at least all supported {@link android.media.CamcorderProfile profiles}.
+ * High speed configurations if supported will be available as well. Even if available for the
+ * camera device, input configurations will be absent.
+ */
+ public static final int USECASE_RECORD = 0x1;
+
+ /**
+ * The recommended stream configuration map for use case video snapshot must only contain a
+ * subset of efficient liveshot configurations that include
+ * {@link android.graphics.ImageFormat#JPEG} output format. The sizes will match at least
+ * the maximum resolution of usecase record and will not cause any preview glitches. Even
+ * if available for the camera device, high speed or input configurations will be absent.
+ */
+ public static final int USECASE_VIDEO_SNAPSHOT = 0x2;
+
+ /**
+ * The recommended stream configuration map for use case snapshot must contain a subset of
+ * efficient still capture configurations that must include
+ * {@link android.graphics.ImageFormat#JPEG} output format and at least one configuration with
+ * size approximately equal to the sensor pixel array size
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+ * Even if available for the camera device, high speed or input configurations will be absent.
+ */
+ public static final int USECASE_SNAPSHOT = 0x3;
+
+ /**
+ * In case the device supports
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING} and/or
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING},
+ * the recommended stream configuration map for use case ZSL must contain a subset of efficient
+ * configurations that include the suggested input and output format mappings. Even if
+ * available for the camera device, high speed configurations will be absent.
+ */
+ public static final int USECASE_ZSL = 0x4;
+
+ /**
+ * In case the device supports
+ * {@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW}, the
+ * recommended stream configuration map for use case RAW must contain a subset of efficient
+ * configurations that include the {@link android.graphics.ImageFormat#RAW_SENSOR} and other
+ * RAW output formats. Even if available for the camera device, high speed and input
+ * configurations will be absent.
+ */
+ public static final int USECASE_RAW = 0x5;
+
+ /**
+ * Device specific use cases.
+ * @hide
+ */
+ public static final int USECASE_VENDOR_START = 0x18;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"USECASE_"}, value =
+ {USECASE_PREVIEW,
+ USECASE_RECORD,
+ USECASE_VIDEO_SNAPSHOT,
+ USECASE_SNAPSHOT,
+ USECASE_ZSL,
+ USECASE_RAW })
+ public @interface RecommendedUsecase {};
+
+ /**
+ * Create a new {@link RecommendedStreamConfigurationMap}.
+ *
+ * @param recommendedMap stream configuration map that contains for the specific use case
+ * @param usecase Recommended use case
+ * @param supportsPrivate Flag indicating private format support.
+ *
+ * @hide
+ */
+ public RecommendedStreamConfigurationMap(StreamConfigurationMap recommendedMap, int usecase,
+ boolean supportsPrivate) {
+ mRecommendedMap = recommendedMap;
+ mUsecase = usecase;
+ mSupportsPrivate = supportsPrivate;
+ }
+
+ /**
+ * Get the use case value for the recommended stream configurations.
+ *
+ * @return Use case id.
+ */
+ public int getRecommendedUseCase() {
+ return mUsecase;
+ }
+
+ private Set<Integer> getUnmodifiableIntegerSet(int[] intArray) {
+ if ((intArray != null) && (intArray.length > 0)) {
+ ArraySet<Integer> integerSet = new ArraySet<Integer>();
+ integerSet.ensureCapacity(intArray.length);
+ for (int intEntry : intArray) {
+ integerSet.add(intEntry);
+ }
+
+ return Collections.unmodifiableSet(integerSet);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the image {@code format} output formats in this stream configuration.
+ *
+ * <p>
+ * For more information refer to {@link StreamConfigurationMap#getOutputFormats}.
+ * </p>
+ *
+ * @return a non-modifiable set of Integer formats
+ */
+ public @NonNull Set<Integer> getOutputFormats() {
+ return getUnmodifiableIntegerSet(mRecommendedMap.getOutputFormats());
+ }
+
+ /**
+ * Get the image {@code format} output formats for a reprocessing input format.
+ *
+ * <p>
+ * For more information refer to {@link StreamConfigurationMap#getValidOutputFormatsForInput}.
+ * </p>
+ *
+ * @return a non-modifiable set of Integer formats
+ */
+ public @Nullable Set<Integer> getValidOutputFormatsForInput(int inputFormat) {
+ return getUnmodifiableIntegerSet(mRecommendedMap.getValidOutputFormatsForInput(
+ inputFormat));
+ }
+
+ /**
+ * Get the image {@code format} input formats in this stream configuration.
+ *
+ * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+ * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+ *
+ * @return a non-modifiable set of Integer formats
+ */
+ public @Nullable Set<Integer> getInputFormats() {
+ return getUnmodifiableIntegerSet(mRecommendedMap.getInputFormats());
+ }
+
+ private Set<Size> getUnmodifiableSizeSet(Size[] sizeArray) {
+ if ((sizeArray != null) && (sizeArray.length > 0)) {
+ ArraySet<Size> sizeSet = new ArraySet<Size>();
+ sizeSet.addAll(Arrays.asList(sizeArray));
+ return Collections.unmodifiableSet(sizeSet);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the supported input sizes for this input format.
+ *
+ * <p>The format must have come from {@link #getInputFormats}; otherwise
+ * {@code null} is returned.</p>
+ *
+ * @param format a format from {@link #getInputFormats}
+ * @return a non-modifiable set of sizes, or {@code null} if the format was not available.
+ */
+ public @Nullable Set<Size> getInputSizes(int format) {
+ return getUnmodifiableSizeSet(mRecommendedMap.getInputSizes(format));
+ }
+
+ /**
+ * Determine whether or not output surfaces with a particular user-defined format can be passed
+ * {@link CameraDevice#createCaptureSession createCaptureSession}.
+ *
+ * <p>
+ * For further information refer to {@link StreamConfigurationMap#isOutputSupportedFor}.
+ * </p>
+ *
+ *
+ * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
+ * @return
+ * {@code true} if using a {@code surface} with this {@code format} will be
+ * supported with {@link CameraDevice#createCaptureSession}
+ *
+ * @throws IllegalArgumentException
+ * if the image format was not a defined named constant
+ * from either {@link ImageFormat} or {@link PixelFormat}
+ */
+ public boolean isOutputSupportedFor(int format) {
+ return mRecommendedMap.isOutputSupportedFor(format);
+ }
+
+ /**
+ * Get a list of sizes compatible with the requested image {@code format}.
+ *
+ * <p>
+ * For more information refer to {@link StreamConfigurationMap#getOutputSizes}.
+ * </p>
+ *
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @return a non-modifiable set of supported sizes,
+ * or {@code null} if the {@code format} is not a supported output
+ */
+ public @Nullable Set<Size> getOutputSizes(int format) {
+ return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(format));
+ }
+
+ /**
+ * Get a list of supported high speed video recording sizes.
+ * <p>
+ * For more information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizes}.
+ * </p>
+ *
+ * @return a non-modifiable set of supported high speed video recording sizes
+ */
+ public @Nullable Set<Size> getHighSpeedVideoSizes() {
+ return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizes());
+ }
+
+ private Set<Range<Integer>> getUnmodifiableRangeSet(Range<Integer>[] rangeArray) {
+ if ((rangeArray != null) && (rangeArray.length > 0)) {
+ ArraySet<Range<Integer>> rangeSet = new ArraySet<Range<Integer>>();
+ rangeSet.addAll(Arrays.asList(rangeArray));
+ return Collections.unmodifiableSet(rangeSet);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size.
+ *
+ * <p>
+ * For further information refer to
+ * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor}.
+ * </p>
+ * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()}
+ * @return a non-modifiable set of supported high speed video recording FPS ranges The upper
+ * bound of returned ranges is guaranteed to be greater than or equal to 120.
+ * @throws IllegalArgumentException if input size does not exist in the return value of
+ * getHighSpeedVideoSizes
+ */
+ public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRangesFor(Size size) {
+ return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRangesFor(size));
+ }
+
+ /**
+ * Get a list of supported high speed video recording FPS ranges.
+ * <p>
+ * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoFpsRanges}.
+ * </p>
+ * @return a non-modifiable set of supported high speed video recording FPS ranges The upper
+ * bound of returned ranges is guaranteed to be larger or equal to 120.
+ */
+ public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRanges() {
+ return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRanges());
+ }
+
+ /**
+ * Get the supported video sizes for an input high speed FPS range.
+ *
+ * <p>
+ * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizesFor}.
+ * </p>
+ *
+ * @param fpsRange one of the FPS range returned by {@link #getHighSpeedVideoFpsRanges()}
+ * @return A non-modifiable set of video sizes to create high speed capture sessions for high
+ * speed streaming use cases.
+ *
+ * @throws IllegalArgumentException if input FPS range does not exist in the return value of
+ * getHighSpeedVideoFpsRanges
+ */
+ public @Nullable Set<Size> getHighSpeedVideoSizesFor(Range<Integer> fpsRange) {
+ return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizesFor(fpsRange));
+ }
+
+ /**
+ * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE
+ * rate.
+ *
+ * <p>
+ * For further information refer to {@link StreamConfigurationMap#getHighResolutionOutputSizes}.
+ * </p>
+ *
+ * @return a non-modifiable set of supported slower high-resolution sizes, or {@code null} if
+ * the BURST_CAPTURE capability is not supported
+ */
+ public @Nullable Set<Size> getHighResolutionOutputSizes(int format) {
+ return getUnmodifiableSizeSet(mRecommendedMap.getHighResolutionOutputSizes(format));
+ }
+
+ /**
+ * Get the minimum
+ * {@link android.hardware.camera2.CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+ * for the format/size combination (in nanoseconds).
+ *
+ * <p>
+ * For further information refer to {@link StreamConfigurationMap#getOutputMinFrameDuration}.
+ * </p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >} 0 in nanoseconds, or
+ * 0 if the minimum frame duration is not available.
+ *
+ * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} was {@code null}
+ *
+ */
+ public long getOutputMinFrameDuration(int format, Size size) {
+ return mRecommendedMap.getOutputMinFrameDuration(format, size);
+ }
+
+ /**
+ * Get the stall duration for the format/size combination (in nanoseconds).
+ *
+ * <p>
+ * For further information refer to {@link StreamConfigurationMap#getOutputStallDuration}.
+ * </p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @param size an output-compatible size
+ * @return a stall duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} was {@code null}
+ */
+ public long getOutputStallDuration(int format, Size size) {
+ return mRecommendedMap.getOutputStallDuration(format, size);
+ }
+
+ /**
+ * Get a list of sizes compatible with {@code klass} to use as an output.
+ *
+ * <p>For further information refer to {@link StreamConfigurationMap#getOutputSizes(Class)}.
+ * </p>
+ *
+ * @param klass
+ * a non-{@code null} {@link Class} object reference
+ * @return
+ * a non-modifiable set of supported sizes for {@link ImageFormat#PRIVATE} format,
+ * or {@code null} if the {@code klass} is not a supported output.
+ *
+ *
+ * @throws NullPointerException if {@code klass} was {@code null}
+ *
+ */
+ public <T> @Nullable Set<Size> getOutputSizes(Class<T> klass) {
+ if (mSupportsPrivate) {
+ return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(klass));
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+ * for the class/size combination (in nanoseconds).
+ *
+ * <p>For more information refer to
+ * {@link StreamConfigurationMap#getOutputMinFrameDuration(Class, Size)}.</p>
+ *
+ * @param klass
+ * a class which has a non-empty array returned by {@link #getOutputSizes(Class)}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >} 0 in nanoseconds, or
+ * 0 if the minimum frame duration is not available.
+ *
+ * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+ *
+ */
+ public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
+ if (mSupportsPrivate) {
+ return mRecommendedMap.getOutputMinFrameDuration(klass, size);
+ }
+
+ return 0;
+ }
+
+ /**
+ * Get the stall duration for the class/size combination (in nanoseconds).
+ *
+ * <p>For more information refer to
+ * {@link StreamConfigurationMap#getOutputStallDuration(Class, Size)}.
+ *
+ * @param klass
+ * a class which has a non-empty array returned by {@link #getOutputSizes(Class)}.
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds, or 0 if the stall duration is
+ * not available.
+ *
+ * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+ *
+ */
+ public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
+ if (mSupportsPrivate) {
+ return mRecommendedMap.getOutputStallDuration(klass, size);
+ }
+
+ return 0;
+ }
+
+ /**
+ * Determine whether or not the {@code surface} in its current state is suitable to be included
+ * in a {@link CameraDevice#createCaptureSession capture session} as an output.
+ *
+ * <p>For more information refer to {@link StreamConfigurationMap#isOutputSupportedFor}.
+ * </p>
+ *
+ * @param surface a non-{@code null} {@link Surface} object reference
+ * @return {@code true} if this is supported, {@code false} otherwise
+ *
+ * @throws NullPointerException if {@code surface} was {@code null}
+ * @throws IllegalArgumentException if the Surface endpoint is no longer valid
+ *
+ */
+ public boolean isOutputSupportedFor(Surface surface) {
+ return mRecommendedMap.isOutputSupportedFor(surface);
+ }
+
+}
diff --git a/core/java/android/hardware/camera2/params/StreamConfiguration.java b/core/java/android/hardware/camera2/params/StreamConfiguration.java
index a6fc10f..eb92291 100644
--- a/core/java/android/hardware/camera2/params/StreamConfiguration.java
+++ b/core/java/android/hardware/camera2/params/StreamConfiguration.java
@@ -40,7 +40,7 @@
*
* @hide
*/
-public final class StreamConfiguration {
+public class StreamConfiguration {
/**
* Create a new {@link StreamConfiguration}.
@@ -164,8 +164,8 @@
return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0);
}
- private final int mFormat;
- private final int mWidth;
- private final int mHeight;
- private final boolean mInput;
+ protected int mFormat;
+ protected int mWidth;
+ protected int mHeight;
+ protected boolean mInput;
}
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 414c463..dd052a8 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -98,6 +98,43 @@
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
ReprocessFormatsMap inputOutputFormatsMap,
boolean listHighResolution) {
+ this(configurations, minFrameDurations, stallDurations,
+ depthConfigurations, depthMinFrameDurations, depthStallDurations,
+ highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution,
+ /*enforceImplementationDefined*/ true);
+ }
+
+ /**
+ * Create a new {@link StreamConfigurationMap}.
+ *
+ * <p>The array parameters ownership is passed to this object after creation; do not
+ * write to them after this constructor is invoked.</p>
+ *
+ * @param configurations a non-{@code null} array of {@link StreamConfiguration}
+ * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration}
+ * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration}
+ * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if
+ * camera device does not support high speed video recording
+ * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE
+ * and thus needs a separate list of slow high-resolution output sizes
+ * @param enforceImplementationDefined a flag indicating whether
+ * IMPLEMENTATION_DEFINED format configuration must be present
+ * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations
+ * were {@code null} or any subelements were {@code null}
+ *
+ * @hide
+ */
+ public StreamConfigurationMap(
+ StreamConfiguration[] configurations,
+ StreamConfigurationDuration[] minFrameDurations,
+ StreamConfigurationDuration[] stallDurations,
+ StreamConfiguration[] depthConfigurations,
+ StreamConfigurationDuration[] depthMinFrameDurations,
+ StreamConfigurationDuration[] depthStallDurations,
+ HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
+ ReprocessFormatsMap inputOutputFormatsMap,
+ boolean listHighResolution,
+ boolean enforceImplementationDefined) {
if (configurations == null) {
// If no color configurations exist, ensure depth ones do
@@ -169,7 +206,7 @@
mDepthOutputFormats.get(config.getFormat()) + 1);
}
- if (configurations != null &&
+ if (configurations != null && enforceImplementationDefined &&
mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) {
throw new AssertionError(
"At least one stream configuration for IMPLEMENTATION_DEFINED must exist");
@@ -208,7 +245,7 @@
* @see ImageFormat
* @see PixelFormat
*/
- public final int[] getOutputFormats() {
+ public int[] getOutputFormats() {
return getPublicFormats(/*output*/true);
}
@@ -232,7 +269,7 @@
* @see ImageFormat
* @see PixelFormat
*/
- public final int[] getValidOutputFormatsForInput(int inputFormat) {
+ public int[] getValidOutputFormatsForInput(int inputFormat) {
if (mInputOutputFormatsMap == null) {
return new int[0];
}
@@ -250,7 +287,7 @@
* @see ImageFormat
* @see PixelFormat
*/
- public final int[] getInputFormats() {
+ public int[] getInputFormats() {
return getPublicFormats(/*output*/false);
}
@@ -426,6 +463,34 @@
}
/**
+ * Determine whether or not the particular stream configuration is suitable to be included
+ * in a {@link CameraDevice#createCaptureSession capture session} as an output.
+ *
+ * @param size stream configuration size
+ * @param format stream configuration format
+ * @return {@code true} if this is supported, {@code false} otherwise
+ *
+ * @see CameraDevice#createCaptureSession
+ * @see #isOutputSupportedFor(Class)
+ * @hide
+ */
+ public boolean isOutputSupportedFor(Size size, int format) {
+ int internalFormat = imageFormatToInternal(format);
+ int dataspace = imageFormatToDataspace(format);
+
+ StreamConfiguration[] configs =
+ dataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
+ for (StreamConfiguration config : configs) {
+ if ((config.getFormat() == internalFormat) && config.isOutput() &&
+ config.getSize().equals(size)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Get a list of sizes compatible with {@code klass} to use as an output.
*
* <p>Some of the supported classes may support additional formats beyond
@@ -1062,8 +1127,9 @@
* @see ImageFormat
* @see PixelFormat
* @see #checkArgumentFormat
+ * @hide
*/
- static int imageFormatToPublic(int format) {
+ public static int imageFormatToPublic(int format) {
switch (format) {
case HAL_PIXEL_FORMAT_BLOB:
return ImageFormat.JPEG;
@@ -1105,8 +1171,9 @@
* @see ImageFormat
* @see PixelFormat
* @see #checkArgumentFormat
+ * @hide
*/
- static int depthFormatToPublic(int format) {
+ public static int depthFormatToPublic(int format) {
switch (format) {
case HAL_PIXEL_FORMAT_BLOB:
return ImageFormat.DEPTH_POINT_CLOUD;
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 7840fd0..9db1f92 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -235,7 +235,8 @@
// If true, enables automatic brightness control.
public boolean useAutoBrightness;
- // If true, scales the brightness to half of desired.
+ // If true, scales the brightness to a fraction of desired (as defined by
+ // screenLowPowerBrightnessFactor).
public boolean lowPowerMode;
// The factor to adjust the screen brightness in low power mode in the range
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 9f11246..2717c4e 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -107,9 +107,10 @@
* This method should be used if the caller wants to receive notifications even after the
* process exits. The client must have an open connection with the Context Hub Service (i.e. it
* cannot have been closed through the {@link #close()} method). Only one PendingIntent can be
- * registered at a time for a single ContextHubClient. If registered successfully, intents will
- * be delivered regarding events for the specified nanoapp from the attached Context Hub. Any
- * unicast messages for this client will also be delivered. The intent will have an extra
+ * registered at a time for a single ContextHubClient, and the PendingIntent cannot be
+ * registered if already registered by a ContextHubClient. If registered successfully, intents
+ * will be delivered regarding events for the specified nanoapp from the attached Context Hub.
+ * Any unicast messages for this client will also be delivered. The intent will have an extra
* {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
* describes the Context Hub the intent event was for. The intent will also have an extra
* {@link ContextHubManager.EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index ab048c5..b25707a 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -32,6 +32,8 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -55,8 +57,8 @@
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
private static final String PROPERTY_GFX_DRIVER_WHITELIST = "ro.gfx.driver.whitelist.0";
private static final String ANGLE_PACKAGE_NAME = "com.android.angle";
- private static final String GLES_MODE_METADATA_KEY = "com.android.angle.GLES_MODE";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
+ private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private ClassLoader mClassLoader;
private String mLayerPath;
@@ -207,38 +209,11 @@
&& (!angleEnabledApp.isEmpty() && !packageName.isEmpty())
&& angleEnabledApp.equals(packageName)) {
- if (DEBUG) Log.v(TAG, packageName + " opted in for ANGLE via Developer Setting");
+ Log.i(TAG, packageName + " opted in for ANGLE via Developer Setting");
devOptIn = true;
}
- ApplicationInfo appInfo;
- try {
- appInfo = context.getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Failed to get info about current application: " + packageName);
- return;
- }
-
- String appPref = "dontcare";
- final BaseBundle metadata = appInfo.metaData;
- if (metadata != null) {
- final String glesMode = metadata.getString(GLES_MODE_METADATA_KEY);
- if (glesMode != null) {
- if (glesMode.equals("angle")) {
- appPref = "angle";
- if (DEBUG) Log.v(TAG, packageName + " opted for ANGLE via AndroidManifest");
- } else if (glesMode.equals("native")) {
- appPref = "native";
- if (DEBUG) Log.v(TAG, packageName + " opted for NATIVE via AndroidManifest");
- } else {
- Log.w(TAG, "Unrecognized GLES_MODE (\"" + glesMode + "\") for " + packageName
- + ". Supported values are \"angle\" or \"native\"");
- }
- }
- }
-
ApplicationInfo angleInfo;
try {
angleInfo = context.getPackageManager().getApplicationInfo(ANGLE_PACKAGE_NAME,
@@ -261,39 +236,76 @@
if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths);
- // Pass the rules file to loader for ANGLE decisions
- AssetManager angleAssets = null;
- try {
- angleAssets =
- context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Failed to get AssetManager for '" + ANGLE_PACKAGE_NAME + "'");
- return;
- }
-
- AssetFileDescriptor assetsFd = null;
- try {
- assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
- } catch (IOException e) {
- Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
- + "'" + ANGLE_PACKAGE_NAME + "'");
- return;
- }
-
+ // Look up rules file to pass to ANGLE
FileDescriptor rulesFd = null;
long rulesOffset = 0;
long rulesLength = 0;
- if (assetsFd != null) {
- rulesFd = assetsFd.getFileDescriptor();
- rulesOffset = assetsFd.getStartOffset();
- rulesLength = assetsFd.getLength();
- } else {
- Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
- return;
+
+ // Check for temporary rules if debuggable or root
+ if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) {
+ String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES);
+ if (angleTempRules != null && !angleTempRules.isEmpty()) {
+ Log.i(TAG, "Detected system property " + ANGLE_TEMP_RULES + ": " + angleTempRules);
+ File tempRulesFile = new File(angleTempRules);
+ if (tempRulesFile.exists()) {
+ Log.i(TAG, angleTempRules + " exists, loading file.");
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(angleTempRules);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Unable to create stream for temp ANGLE rules");
+ }
+
+ if (stream != null) {
+ try {
+ rulesFd = stream.getFD();
+ rulesOffset = 0;
+ rulesLength = stream.getChannel().size();
+ Log.i(TAG, "Loaded temporary ANGLE rules from " + angleTempRules);
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to get input stream for " + angleTempRules);
+ }
+ }
+ }
+ }
+ }
+
+ // If no temp rules, load the real ones from the APK
+ if (rulesFd == null) {
+
+ // Pass the rules file to loader for ANGLE decisions
+ AssetManager angleAssets = null;
+ try {
+ angleAssets =
+ context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Failed to get AssetManager for '" + ANGLE_PACKAGE_NAME + "'");
+ return;
+ }
+
+ AssetFileDescriptor assetsFd = null;
+ try {
+ assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
+ + "'" + ANGLE_PACKAGE_NAME + "'");
+ return;
+ }
+
+ if (assetsFd != null) {
+ rulesFd = assetsFd.getFileDescriptor();
+ rulesOffset = assetsFd.getStartOffset();
+ rulesLength = assetsFd.getLength();
+ } else {
+ Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
+ return;
+ }
}
// Further opt-in logic is handled in native, so pass relevant info down
- setAngleInfo(paths, packageName, appPref, devOptIn,
+ // TODO: Move the ANGLE selection logic earlier so we don't need to keep these
+ // file descriptors open.
+ setAngleInfo(paths, packageName, devOptIn,
rulesFd, rulesOffset, rulesLength);
}
@@ -434,7 +446,7 @@
private static native void setDebugLayers(String layers);
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPath(String path);
- private static native void setAngleInfo(String path, String appPackage, String appPref,
+ private static native void setAngleInfo(String path, String appPackage,
boolean devOptIn, FileDescriptor rulesFd,
long rulesOffset, long rulesLength);
}
diff --git a/core/java/android/os/IThermalEventListener.aidl b/core/java/android/os/IThermalEventListener.aidl
index 9a6de60..fc93b5c 100644
--- a/core/java/android/os/IThermalEventListener.aidl
+++ b/core/java/android/os/IThermalEventListener.aidl
@@ -27,6 +27,5 @@
* Called when a thermal throttling start/stop event is received.
* @param temperature the temperature at which the event was generated.
*/
- void notifyThrottling(
- in boolean isThrottling, in Temperature temperature);
+ void notifyThrottling(in Temperature temperature);
}
diff --git a/core/java/android/os/IThermalService.aidl b/core/java/android/os/IThermalService.aidl
index e388eda..287a5ed 100644
--- a/core/java/android/os/IThermalService.aidl
+++ b/core/java/android/os/IThermalService.aidl
@@ -19,6 +19,8 @@
import android.os.IThermalEventListener;
import android.os.Temperature;
+import java.util.List;
+
/**
* {@hide}
*/
@@ -30,22 +32,29 @@
*/
void registerThermalEventListener(in IThermalEventListener listener);
/**
+ * Register a listener for thermal events on given temperature type.
+ * @param listener the IThermalEventListener to be notified.
+ * @param type the temperature type IThermalEventListener to be notified.
+ * {@hide}
+ */
+ void registerThermalEventListenerWithType(in IThermalEventListener listener, in int type);
+ /**
* Unregister a previously-registered listener for thermal events.
* @param listener the IThermalEventListener to no longer be notified.
* {@hide}
*/
void unregisterThermalEventListener(in IThermalEventListener listener);
/**
- * Send a thermal throttling start/stop notification to all listeners.
- * @param temperature the temperature at which the event was generated.
+ * Get current temperature with its throttling status.
+ * @return list of android.os.Temperature
* {@hide}
*/
- oneway void notifyThrottling(
- in boolean isThrottling, in Temperature temperature);
+ List<Temperature> getCurrentTemperatures();
/**
- * Return whether system performance is currently thermal throttling.
- * @return true if thermal throttling is currently in effect
+ * Get current temperature with its throttling status on given temperature type.
+ * @param type the temperature type to query.
+ * @return list of android.os.Temperature
* {@hide}
*/
- boolean isThrottling();
+ List<Temperature> getCurrentTemperaturesWithType(in int type);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index e0b2c78..27c281d 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -477,6 +477,13 @@
public static final String SHUTDOWN_BATTERY_THERMAL_STATE = "thermal,battery";
/**
+ * The value to pass as the 'reason' argument to android_reboot() when device temperature
+ * is too high.
+ * @hide
+ */
+ public static final String SHUTDOWN_THERMAL_STATE = "thermal";
+
+ /**
* The value to pass as the 'reason' argument to android_reboot() when device is running
* critically low on battery.
* @hide
diff --git a/core/java/android/os/Temperature.java b/core/java/android/os/Temperature.java
index 8767731..37ed52c 100644
--- a/core/java/android/os/Temperature.java
+++ b/core/java/android/os/Temperature.java
@@ -16,6 +16,13 @@
package android.os;
+import android.annotation.IntDef;
+import android.hardware.thermal.V2_0.TemperatureType;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Temperature values used by IThermalService.
*/
@@ -24,24 +31,89 @@
* @hide
*/
public class Temperature implements Parcelable {
- /* Temperature value */
+ /** Temperature value */
private float mValue;
- /* A temperature type from HardwarePropertiesManager */
+ /** A temperature type from ThermalHAL */
private int mType;
+ /** Name of this temperature */
+ private String mName;
+ /** The level of the sensor is currently in throttling */
+ private int mStatus;
- public Temperature() {
- this(HardwarePropertiesManager.UNDEFINED_TEMPERATURE,
- Integer.MIN_VALUE);
+ /** @hide */
+ @IntDef(prefix = { "THROTTLING_" }, value = {
+ THROTTLING_NONE,
+ THROTTLING_LIGHT,
+ THROTTLING_MODERATE,
+ THROTTLING_SEVERE,
+ THROTTLING_CRITICAL,
+ THROTTLING_WARNING,
+ THROTTLING_SHUTDOWN,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ThrottlingStatus {}
+
+ /** Keep in sync with hardware/interfaces/thermal/2.0/types.hal */
+ public static final int THROTTLING_NONE = ThrottlingSeverity.NONE;
+ public static final int THROTTLING_LIGHT = ThrottlingSeverity.LIGHT;
+ public static final int THROTTLING_MODERATE = ThrottlingSeverity.MODERATE;
+ public static final int THROTTLING_SEVERE = ThrottlingSeverity.SEVERE;
+ public static final int THROTTLING_CRITICAL = ThrottlingSeverity.CRITICAL;
+ public static final int THROTTLING_WARNING = ThrottlingSeverity.WARNING;
+ public static final int THROTTLING_SHUTDOWN = ThrottlingSeverity.SHUTDOWN;
+
+ /** @hide */
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_UNKNOWN,
+ TYPE_CPU,
+ TYPE_GPU,
+ TYPE_BATTERY,
+ TYPE_SKIN,
+ TYPE_USB_PORT,
+ TYPE_POWER_AMPLIFIER,
+ TYPE_BCL_VOLTAGE,
+ TYPE_BCL_CURRENT,
+ TYPE_BCL_PERCENTAGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ /* Keep in sync with hardware/interfaces/thermal/2.0/types.hal */
+ public static final int TYPE_UNKNOWN = TemperatureType.UNKNOWN;
+ public static final int TYPE_CPU = TemperatureType.CPU;
+ public static final int TYPE_GPU = TemperatureType.GPU;
+ public static final int TYPE_BATTERY = TemperatureType.BATTERY;
+ public static final int TYPE_SKIN = TemperatureType.SKIN;
+ public static final int TYPE_USB_PORT = TemperatureType.USB_PORT;
+ public static final int TYPE_POWER_AMPLIFIER = TemperatureType.POWER_AMPLIFIER;
+ public static final int TYPE_BCL_VOLTAGE = TemperatureType.BCL_VOLTAGE;
+ public static final int TYPE_BCL_CURRENT = TemperatureType.BCL_CURRENT;
+ public static final int TYPE_BCL_PERCENTAGE = TemperatureType.BCL_PERCENTAGE;
+
+ /**
+ * Verify a valid temperature type.
+ *
+ * @return true if a temperature type is valid otherwise false.
+ */
+ public static boolean isValidType(int type) {
+ return type >= TYPE_UNKNOWN && type <= TYPE_BCL_PERCENTAGE;
}
- public Temperature(float value, int type) {
+ public Temperature() {
+ this(Float.NaN, TYPE_UNKNOWN, "", THROTTLING_NONE);
+ }
+
+ public Temperature(float value, @Type int type, String name, int status) {
mValue = value;
- mType = type;
+ mType = isValidType(type) ? type : TYPE_UNKNOWN;
+ mName = name;
+ mStatus = status;
}
/**
* Return the temperature value.
- * @return a temperature value in floating point.
+ *
+ * @return a temperature value in floating point could be NaN.
*/
public float getValue() {
return mValue;
@@ -49,18 +121,30 @@
/**
* Return the temperature type.
- * @return a temperature type:
- * HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU, etc.
+ *
+ * @return a temperature type: TYPE_*
*/
- public int getType() {
+ public @Type int getType() {
return mType;
}
- /*
- * Parcel read/write code must be kept in sync with
- * frameworks/native/services/thermalservice/aidl/android/os/
- * Temperature.cpp
+ /**
+ * Return the temperature name.
+ *
+ * @return a temperature name as String.
*/
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Return the temperature throttling status.
+ *
+ * @return a temperature throttling status: THROTTLING_*
+ */
+ public @ThrottlingStatus int getStatus() {
+ return mStatus;
+ }
private Temperature(Parcel p) {
readFromParcel(p);
@@ -68,31 +152,36 @@
/**
* Fill in Temperature members from a Parcel.
+ *
* @param p the parceled Temperature object.
*/
public void readFromParcel(Parcel p) {
mValue = p.readFloat();
mType = p.readInt();
+ mName = p.readString();
+ mStatus = p.readInt();
}
@Override
public void writeToParcel(Parcel p, int flags) {
p.writeFloat(mValue);
p.writeInt(mType);
+ p.writeString(mName);
+ p.writeInt(mStatus);
}
public static final Parcelable.Creator<Temperature> CREATOR =
new Parcelable.Creator<Temperature>() {
- @Override
- public Temperature createFromParcel(Parcel p) {
- return new Temperature(p);
- }
+ @Override
+ public Temperature createFromParcel(Parcel p) {
+ return new Temperature(p);
+ }
- @Override
- public Temperature[] newArray(int size) {
- return new Temperature[size];
- }
- };
+ @Override
+ public Temperature[] newArray(int size) {
+ return new Temperature[size];
+ }
+ };
@Override
public int describeContents() {
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 5bef7ee..8a03e9e 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -331,7 +331,12 @@
* @return intent to request access, or {@code null} if the requested directory is invalid for
* that volume.
* @see DocumentsContract
+ * @deprecated Callers should migrate to using {@link Intent#ACTION_OPEN_DOCUMENT_TREE} instead.
+ * Launching this {@link Intent} on devices running
+ * {@link android.os.Build.VERSION_CODES#Q} or higher, will immediately finish
+ * with a result code of {@link android.app.Activity#RESULT_CANCELED}.
*/
+ @Deprecated
public @Nullable Intent createAccessIntent(String directoryName) {
if ((isPrimary() && directoryName == null) ||
(directoryName != null && !Environment.isStandardDirectory(directoryName))) {
@@ -425,32 +430,4 @@
parcel.writeString(mFsUuid);
parcel.writeString(mState);
}
-
- /** {@hide} */
- public static final class ScopedAccessProviderContract {
-
- private ScopedAccessProviderContract() {
- throw new UnsupportedOperationException("contains constants only");
- }
-
- public static final String AUTHORITY = "com.android.documentsui.scopedAccess";
-
- public static final String TABLE_PACKAGES = "packages";
- public static final String TABLE_PERMISSIONS = "permissions";
-
- public static final String COL_PACKAGE = "package_name";
- public static final String COL_VOLUME_UUID = "volume_uuid";
- public static final String COL_DIRECTORY = "directory";
- public static final String COL_GRANTED = "granted";
-
- public static final String[] TABLE_PACKAGES_COLUMNS = new String[] { COL_PACKAGE };
- public static final String[] TABLE_PERMISSIONS_COLUMNS =
- new String[] { COL_PACKAGE, COL_VOLUME_UUID, COL_DIRECTORY, COL_GRANTED };
-
- public static final int TABLE_PACKAGES_COL_PACKAGE = 0;
- public static final int TABLE_PERMISSIONS_COL_PACKAGE = 0;
- public static final int TABLE_PERMISSIONS_COL_VOLUME_UUID = 1;
- public static final int TABLE_PERMISSIONS_COL_DIRECTORY = 2;
- public static final int TABLE_PERMISSIONS_COL_GRANTED = 3;
- }
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index fc30eed..2ea7066 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -67,15 +67,14 @@
* such an old app asks for a location permission (i.e. the
* {@link SplitPermissionInfo#getSplitPermission()}), then the
* {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
- * {@{@link SplitPermissionInfo#getNewPermissions}) is added.
+ * {@link SplitPermissionInfo#getNewPermissions}) is added.
*
* <p>Note: Regular apps do not have to worry about this. The platform and permission controller
* automatically add the new permissions where needed.
*
* @return All permissions that are split.
*/
- public @NonNull
- List<SplitPermissionInfo> getSplitPermissions() {
+ public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
return SPLIT_PERMISSIONS;
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index c0fa1de..3d93afd 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -509,6 +509,100 @@
private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
/**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set as the default value when a call was
+ * not blocked by a CallScreeningService or any other system call blocking method.
+ */
+ public static final int BLOCK_REASON_NOT_BLOCKED = 0;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked by a
+ * CallScreeningService. The {@link CallLog.Calls#CALL_SCREENING_COMPONENT_NAME} and
+ * {@link CallLog.Calls#CALL_SCREENING_APP_NAME} columns will indicate which call screening
+ * service was responsible for blocking the call.
+ */
+ public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+ * configured a contact to be sent directly to voicemail.
+ */
+ public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because it is
+ * in the BlockedNumbers provider.
+ */
+ public static final int BLOCK_REASON_BLOCKED_NUMBER = 3;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+ * has chosen to block all calls from unknown numbers.
+ */
+ public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+ * has chosen to block all calls from restricted numbers.
+ */
+ public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+ * has chosen to block all calls from pay phones.
+ */
+ public static final int BLOCK_REASON_PAY_PHONE = 6;
+
+ /**
+ * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+ * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+ * has chosen to block all calls from numbers not in their contacts.
+ */
+ public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7;
+
+ /**
+ * The ComponentName of the CallScreeningService which blocked this call. Will be
+ * populated when the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name";
+
+ /**
+ * The name of the app which blocked a call. Will be populated when the
+ * {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. Provided as a
+ * convenience so that the call log can still indicate which app blocked a call, even if
+ * that app is no longer installed.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CALL_SCREENING_APP_NAME = "call_screening_app_name";
+
+ /**
+ * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE},
+ * indicates the reason why a call is blocked.
+ * <P>Type: INTEGER</P>
+ *
+ * <p>
+ * Allowed values:
+ * <ul>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_BLOCKED}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_DIRECT_TO_VOICEMAIL}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_BLOCKED_NUMBER}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_UNKNOWN_NUMBER}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_RESTRICTED_NUMBER}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_PAY_PHONE}</li>
+ * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_IN_CONTACTS}</li>
+ * </ul>
+ * </p>
+ */
+ public static final String BLOCK_REASON = "block_reason";
+
+ /**
* Adds a call to the call log.
*
* @param ci the CallerInfo object to get the target contact from. Can be null
@@ -530,12 +624,14 @@
* {@hide}
*/
public static Uri addCall(CallerInfo ci, Context context, String number,
- int presentation, int callType, int features, PhoneAccountHandle accountHandle,
+ int presentation, int callType, int features,
+ PhoneAccountHandle accountHandle,
long start, int duration, Long dataUsage) {
- return addCall(ci, context, number, /* postDialDigits =*/ "", /* viaNumber =*/ "",
- presentation, callType, features, accountHandle, start, duration,
- dataUsage, /* addForAllUsers =*/ false, /* userToBeInsertedTo =*/ null,
- /* is_read =*/ false);
+ return addCall(ci, context, number, "" /* postDialDigits */, "" /* viaNumber */,
+ presentation, callType, features, accountHandle, start, duration,
+ dataUsage, false /* addForAllUsers */, null /* userToBeInsertedTo */,
+ false /* isRead */, Calls.BLOCK_REASON_NOT_BLOCKED /* callBlockReason */,
+ null /* callScreeningAppName */, null /* callScreeningComponentName */);
}
@@ -572,8 +668,10 @@
int features, PhoneAccountHandle accountHandle, long start, int duration,
Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo) {
return addCall(ci, context, number, postDialDigits, viaNumber, presentation, callType,
- features, accountHandle, start, duration, dataUsage, addForAllUsers,
- userToBeInsertedTo, /* is_read =*/ false);
+ features, accountHandle, start, duration, dataUsage, addForAllUsers,
+ userToBeInsertedTo, false /* isRead */ , Calls.BLOCK_REASON_NOT_BLOCKED
+ /* callBlockReason */, null /* callScreeningAppName */,
+ null /* callScreeningComponentName */);
}
/**
@@ -602,8 +700,11 @@
* @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
* inserted to. null if it is inserted to the current user. The
* value is ignored if @{link addForAllUsers} is true.
- * @param is_read Flag to show if the missed call log has been read by the user or not.
+ * @param isRead Flag to show if the missed call log has been read by the user or not.
* Used for call log restore of missed calls.
+ * @param callBlockReason The reason why the call is blocked.
+ * @param callScreeningAppName The call screening application name which block the call.
+ * @param callScreeningComponentName The call screening component name which block the call.
*
* @result The URI of the call log entry belonging to the user that made or received this
* call. This could be of the shadow provider. Do not return it to non-system apps,
@@ -615,7 +716,8 @@
String postDialDigits, String viaNumber, int presentation, int callType,
int features, PhoneAccountHandle accountHandle, long start, int duration,
Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo,
- boolean is_read) {
+ boolean isRead, int callBlockReason, String callScreeningAppName,
+ String callScreeningComponentName) {
if (VERBOSE_LOG) {
Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
number, userToBeInsertedTo, addForAllUsers));
@@ -690,9 +792,13 @@
values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
if (callType == MISSED_TYPE) {
- values.put(IS_READ, Integer.valueOf(is_read ? 1 : 0));
+ values.put(IS_READ, Integer.valueOf(isRead ? 1 : 0));
}
+ values.put(BLOCK_REASON, callBlockReason);
+ values.put(CALL_SCREENING_APP_NAME, callScreeningAppName);
+ values.put(CALL_SCREENING_COMPONENT_NAME, callScreeningComponentName);
+
if ((ci != null) && (ci.contactIdOrZero > 0)) {
// Update usage information for the number associated with the contact ID.
// We need to use both the number and the ID for obtaining a data ID since other
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 689f975..7a444e0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1600,8 +1600,11 @@
* Applications typically use this action to ask the user to revert the "Do not ask again"
* status of directory access requests made by
* {@link android.os.storage.StorageVolume#createAccessIntent(String)}.
+ * @deprecated use {@link #ACTION_APPLICATION_DETAILS_SETTINGS} to manage storage permissions
+ * for a specific application
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @Deprecated
public static final String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS =
"android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
@@ -4892,6 +4895,7 @@
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_NETWORK_SHOW_RSSI);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_ON);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED);
+ MOVED_TO_GLOBAL.add(Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET);
MOVED_TO_GLOBAL.add(Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON);
MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_ENABLE);
MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_TIMEOUT);
@@ -6564,23 +6568,22 @@
public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout";
/**
- * Whether the user specifies a minimum ui timeout to override minimum ui timeout of
- * accessibility service
+ * Setting that specifies recommended timeout in milliseconds for controls
+ * which don't need user's interactions.
*
- * Type: int (0 for false, 1 for true)
* @hide
*/
- public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED =
- "accessibility_minimum_ui_timeout_enabled";
+ public static final String ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS =
+ "accessibility_non_interactive_ui_timeout_ms";
/**
- * Setting that specifies ui minimum timeout in milliseconds.
+ * Setting that specifies recommended timeout in milliseconds for controls
+ * which need user's interactions.
*
- * @see #ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED
* @hide
*/
- public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS =
- "accessibility_minimum_ui_timeout_ms";
+ public static final String ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS =
+ "accessibility_interactive_ui_timeout_ms";
/**
* List of the enabled print services.
@@ -8198,6 +8201,12 @@
"packages_to_clear_data_before_full_restore";
/**
+ * Setting to determine whether to use the new notification priority handling features.
+ * @hide
+ */
+ public static final String NOTIFICATION_NEW_INTERRUPTION_MODEL = "new_interruption_model";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -8309,8 +8318,9 @@
ZEN_SETTINGS_SUGGESTION_VIEWED,
CHARGING_SOUNDS_ENABLED,
CHARGING_VIBRATION_ENABLED,
- ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED,
- ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS,
+ ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
+ ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
+ NOTIFICATION_NEW_INTERRUPTION_MODEL,
};
/**
@@ -8466,10 +8476,12 @@
VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR);
VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
+ NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(NOTIFICATION_NEW_INTERRUPTION_MODEL, BOOLEAN_VALIDATOR);
}
/**
@@ -9162,6 +9174,13 @@
public static final String DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT
= "enable_freeform_support";
+ /**
+ * Whether to enable experimental desktop mode on secondary displays.
+ * @hide
+ */
+ public static final String DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS =
+ "force_desktop_mode_on_external_displays";
+
/**
* Whether user has enabled development settings.
*/
@@ -9984,6 +10003,15 @@
"wifi_rtt_background_exec_gap_ms";
/**
+ * Indicate whether factory reset request is pending.
+ *
+ * Type: int (0 for false, 1 for true)
+ * @hide
+ */
+ public static final String WIFI_P2P_PENDING_FACTORY_RESET =
+ "wifi_p2p_pending_factory_reset";
+
+ /**
* Whether soft AP will shut down after a timeout period when no devices are connected.
*
* Type: int (0 for false, 1 for true)
@@ -11499,6 +11527,24 @@
public static final String NETWORK_WATCHLIST_ENABLED = "network_watchlist_enabled";
/**
+ * Whether or not show hidden launcher icon apps feature is enabled.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED =
+ "show_hidden_icon_apps_enabled";
+
+ /**
+ * Whether or not show new app installed notification is enabled.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED =
+ "show_new_app_installed_notification_enabled";
+
+ /**
* Flag to keep background restricted profiles running after exiting. If disabled,
* the restricted profile can be put into stopped state as soon as the user leaves it.
* Type: int (0 for false, 1 for true)
@@ -12490,6 +12536,17 @@
"privileged_device_identifier_target_q_behavior_enabled";
/**
+ * If set to 1, the device identifier check will be relaxed to the previous READ_PHONE_STATE
+ * permission check for 3P apps.
+ *
+ * STOPSHIP: Remove this once we ship with the new device identifier check enabled.
+ *
+ * @hide
+ */
+ public static final String PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED =
+ "privileged_device_identifier_3p_check_relaxed";
+
+ /**
* If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will be ignored
* and restoring to lower version of platform API will be skipped.
*
diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl
index ee93326..bacad8b 100644
--- a/core/java/android/service/intelligence/IIntelligenceService.aidl
+++ b/core/java/android/service/intelligence/IIntelligenceService.aidl
@@ -19,6 +19,11 @@
import android.service.intelligence.InteractionSessionId;
import android.service.intelligence.InteractionContext;
+import android.view.intelligence.ContentCaptureEvent;
+
+import java.util.List;
+
+
/**
* Interface from the system to an intelligence service.
*
@@ -28,4 +33,7 @@
// Called when session is created (context not null) or destroyed (context null)
void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId);
+
+ void onContentCaptureEvents(in InteractionSessionId sessionId,
+ in List<ContentCaptureEvent> events);
}
diff --git a/core/java/android/service/intelligence/IntelligenceService.java b/core/java/android/service/intelligence/IntelligenceService.java
index ce0a88a..a2b60f0 100644
--- a/core/java/android/service/intelligence/IntelligenceService.java
+++ b/core/java/android/service/intelligence/IntelligenceService.java
@@ -70,6 +70,14 @@
IntelligenceService.this, sessionId));
}
}
+ @Override
+ public void onContentCaptureEvents(InteractionSessionId sessionId,
+ List<ContentCaptureEvent> events) {
+ mHandler.sendMessage(
+ obtainMessage(IntelligenceService::onContentCaptureEvent,
+ IntelligenceService.this, sessionId, events));
+
+ }
};
@CallSuper
@@ -105,6 +113,7 @@
* @param sessionId the session's Id
* @param events the events
*/
+ // TODO(b/111276913): rename to onContentCaptureEvents
public abstract void onContentCaptureEvent(@NonNull InteractionSessionId sessionId,
@NonNull List<ContentCaptureEvent> events);
diff --git a/core/java/android/service/intelligence/InteractionSessionId.java b/core/java/android/service/intelligence/InteractionSessionId.java
index ca68f8e..667193b 100644
--- a/core/java/android/service/intelligence/InteractionSessionId.java
+++ b/core/java/android/service/intelligence/InteractionSessionId.java
@@ -16,43 +16,85 @@
package android.service.intelligence;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.PrintWriter;
+import java.util.UUID;
// TODO(b/111276913): add javadocs / implement equals/hashcode/string
/** @hide */
@SystemApi
public final class InteractionSessionId implements Parcelable {
- private final int mGlobalId;
+ private final @NonNull String mValue;
- // TODO(b/111276913): remove if not needed
- private final int mLocalId;
-
- /** @hide */
- public InteractionSessionId(int globalId, int localId) {
- mGlobalId = globalId;
- mLocalId = localId;
+ /**
+ * Creates a new instance.
+ *
+ * @hide
+ */
+ public InteractionSessionId() {
+ this(UUID.randomUUID().toString());
}
- /** @hide */
- public int getGlobalId() {
- return mGlobalId;
+ /**
+ * Creates a new instance.
+ *
+ * @param value The internal value.
+ *
+ * @hide
+ */
+ public InteractionSessionId(@NonNull String value) {
+ mValue = value;
+ }
+
+ /**
+ * @hide
+ */
+ public String getValue() {
+ return mValue;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mValue == null) ? 0 : mValue.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ final InteractionSessionId other = (InteractionSessionId) obj;
+ if (mValue == null) {
+ if (other.mValue != null) return false;
+ } else if (!mValue.equals(other.mValue)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p><b>NOTE: </b>this method is only useful for debugging purposes and is not guaranteed to
+ * be stable, hence it should not be used to identify the session.
+ */
+ @Override
+ public String toString() {
+ return mValue;
}
/** @hide */
// TODO(b/111276913): dump to proto as well
public void dump(PrintWriter pw) {
- pw.print("globalId="); pw.print(mGlobalId);
- pw.print("localId="); pw.print(mLocalId);
- }
-
- @Override
- public String toString() {
- return "SessionId[globalId=" + mGlobalId + ", localId=" + mLocalId + "]";
+ pw.print(mValue);
}
@Override
@@ -62,8 +104,7 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(mGlobalId);
- parcel.writeInt(mLocalId);
+ parcel.writeString(mValue);
}
public static final Parcelable.Creator<InteractionSessionId> CREATOR =
@@ -71,9 +112,7 @@
@Override
public InteractionSessionId createFromParcel(Parcel parcel) {
- final int globalId = parcel.readInt();
- final int localId = parcel.readInt();
- return new InteractionSessionId(globalId, localId);
+ return new InteractionSessionId(parcel.readString());
}
@Override
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b8e0387..64eae0c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1461,6 +1461,8 @@
private boolean mShowBadge;
private @UserSentiment int mUserSentiment = USER_SENTIMENT_NEUTRAL;
private boolean mHidden;
+ private boolean mAudiblyAlerted;
+ private boolean mNoisy;
private ArrayList<Notification.Action> mSmartActions;
private ArrayList<CharSequence> mSmartReplies;
@@ -1627,6 +1629,20 @@
}
/**
+ * Returns whether this notification alerted the user via sound or vibration.
+ *
+ * @return true if the notification alerted the user, false otherwise.
+ */
+ public boolean audiblyAlerted() {
+ return mAudiblyAlerted;
+ }
+
+ /** @hide */
+ public boolean isNoisy() {
+ return mNoisy;
+ }
+
+ /**
* @hide
*/
@VisibleForTesting
@@ -1635,7 +1651,8 @@
CharSequence explanation, String overrideGroupKey,
NotificationChannel channel, ArrayList<String> overridePeople,
ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
- int userSentiment, boolean hidden, ArrayList<Notification.Action> smartActions,
+ int userSentiment, boolean hidden, boolean audiblyAlerted,
+ boolean noisy, ArrayList<Notification.Action> smartActions,
ArrayList<CharSequence> smartReplies) {
mKey = key;
mRank = rank;
@@ -1652,6 +1669,8 @@
mShowBadge = showBadge;
mUserSentiment = userSentiment;
mHidden = hidden;
+ mAudiblyAlerted = audiblyAlerted;
+ mNoisy = noisy;
mSmartActions = smartActions;
mSmartReplies = smartReplies;
}
@@ -1703,6 +1722,8 @@
private ArrayMap<String, Boolean> mShowBadge;
private ArrayMap<String, Integer> mUserSentiment;
private ArrayMap<String, Boolean> mHidden;
+ private ArrayMap<String, Boolean> mAudiblyAlerted;
+ private ArrayMap<String, Boolean> mNoisy;
private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
@@ -1733,7 +1754,8 @@
getVisibilityOverride(key), getSuppressedVisualEffects(key),
getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
- getShowBadge(key), getUserSentiment(key), getHidden(key), getSmartActions(key),
+ getShowBadge(key), getUserSentiment(key), getHidden(key),
+ getAudiblyAlerted(key), getNoisy(key), getSmartActions(key),
getSmartReplies(key));
return rank >= 0;
}
@@ -1872,6 +1894,26 @@
return hidden == null ? false : hidden.booleanValue();
}
+ private boolean getAudiblyAlerted(String key) {
+ synchronized (this) {
+ if (mAudiblyAlerted == null) {
+ buildAudiblyAlertedLocked();
+ }
+ }
+ Boolean audiblyAlerted = mAudiblyAlerted.get(key);
+ return audiblyAlerted == null ? false : audiblyAlerted.booleanValue();
+ }
+
+ private boolean getNoisy(String key) {
+ synchronized (this) {
+ if (mNoisy == null) {
+ buildNoisyLocked();
+ }
+ }
+ Boolean noisy = mNoisy.get(key);
+ return noisy == null ? false : noisy.booleanValue();
+ }
+
private ArrayList<Notification.Action> getSmartActions(String key) {
synchronized (this) {
if (mSmartActions == null) {
@@ -2007,6 +2049,16 @@
}
// Locked by 'this'
+ private void buildAudiblyAlertedLocked() {
+ mAudiblyAlerted = buildBooleanMapFromBundle(mRankingUpdate.getAudiblyAlerted());
+ }
+
+ // Locked by 'this'
+ private void buildNoisyLocked() {
+ mNoisy = buildBooleanMapFromBundle(mRankingUpdate.getNoisy());
+ }
+
+ // Locked by 'this'
private void buildSmartActions() {
Bundle smartActions = mRankingUpdate.getSmartActions();
mSmartActions = new ArrayMap<>(smartActions.size());
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index c67fad0..f80df93 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -39,13 +39,15 @@
private final Bundle mHidden;
private final Bundle mSmartActions;
private final Bundle mSmartReplies;
+ private final Bundle mAudiblyAlerted;
+ private final Bundle mNoisy;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
Bundle visibilityOverrides, Bundle suppressedVisualEffects,
int[] importance, Bundle explanation, Bundle overrideGroupKeys,
Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
- Bundle smartReplies) {
+ Bundle smartReplies, Bundle audiblyAlerted, Bundle noisy) {
mKeys = keys;
mInterceptedKeys = interceptedKeys;
mVisibilityOverrides = visibilityOverrides;
@@ -61,6 +63,8 @@
mHidden = hidden;
mSmartActions = smartActions;
mSmartReplies = smartReplies;
+ mAudiblyAlerted = audiblyAlerted;
+ mNoisy = noisy;
}
public NotificationRankingUpdate(Parcel in) {
@@ -80,6 +84,8 @@
mHidden = in.readBundle();
mSmartActions = in.readBundle();
mSmartReplies = in.readBundle();
+ mAudiblyAlerted = in.readBundle();
+ mNoisy = in.readBundle();
}
@Override
@@ -104,6 +110,8 @@
out.writeBundle(mHidden);
out.writeBundle(mSmartActions);
out.writeBundle(mSmartReplies);
+ out.writeBundle(mAudiblyAlerted);
+ out.writeBundle(mNoisy);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -176,4 +184,12 @@
public Bundle getSmartReplies() {
return mSmartReplies;
}
+
+ public Bundle getAudiblyAlerted() {
+ return mAudiblyAlerted;
+ }
+
+ public Bundle getNoisy() {
+ return mNoisy;
+ }
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 769dd1b..67505e5 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -42,11 +42,10 @@
private static final Map<String, String> DEFAULT_FLAGS;
static {
DEFAULT_FLAGS = new HashMap<>();
- DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put("settings_dynamic_homepage", "false");
- DEFAULT_FLAGS.put("settings_mobile_network_v2", "false");
+ DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
DEFAULT_FLAGS.put("settings_seamless_transfer", "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a872776..96ef8ba 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -21,6 +21,7 @@
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.graphics.FrameInfo;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 597089b..0f38e84 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -40,8 +40,9 @@
@UnsupportedAppUsage
private FrameMetrics mFrameMetrics;
- /* package */ Window.OnFrameMetricsAvailableListener mListener;
- /* package */ VirtualRefBasePtr mNative;
+ /* pacage */ Window.OnFrameMetricsAvailableListener mListener;
+ /** @hide */
+ public VirtualRefBasePtr mNative;
/**
* Creates a FrameMetricsObserver
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f8bdfe2..5c07f44 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -111,9 +111,6 @@
// caller must call setNewConfiguration() sometime later.
Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
IBinder freezeThisOneIfNeeded, int displayId);
- // Notify window manager of the new display override configuration. Returns an array of stack
- // ids that were affected by the update, ActivityManager should resize these stacks.
- int[] setNewDisplayOverrideConfiguration(in Configuration overrideConfig, int displayId);
void startFreezingScreen(int exitAnim, int enterAnim);
void stopFreezingScreen();
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 0a3403b..7e5c149 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2523,10 +2523,11 @@
}
/**
- * Retrieve the repeat count of the event. For both key up and key down
- * events, this is the number of times the key has repeated with the first
- * down starting at 0 and counting up from there. For multiple key
- * events, this is the number of down/up pairs that have occurred.
+ * Retrieve the repeat count of the event. For key down events,
+ * this is the number of times the key has repeated with the first
+ * down starting at 0 and counting up from there. For key up events,
+ * this is always equal to zero. For multiple key events,
+ * this is the number of down/up pairs that have occurred.
*
* @return The number of times the key has repeated.
*/
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 81da76d..fa30221 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -61,6 +61,7 @@
private View mCameraIcon;
private View mMicIcon;
private View mAppOps;
+ private View mAudiblyAlertedIcon;
private int mIconColor;
private int mOriginalNotificationColor;
private boolean mExpanded;
@@ -121,6 +122,7 @@
mMicIcon = findViewById(com.android.internal.R.id.mic);
mOverlayIcon = findViewById(com.android.internal.R.id.overlay);
mAppOps = findViewById(com.android.internal.R.id.app_ops);
+ mAudiblyAlertedIcon = findViewById(com.android.internal.R.id.alerted_icon);
}
@Override
@@ -216,6 +218,11 @@
layoutRight = end - paddingEnd;
end = layoutLeft = layoutRight - child.getMeasuredWidth();
}
+ if (child == mAudiblyAlertedIcon) {
+ int paddingEnd = mContentEndMargin;
+ layoutRight = end - paddingEnd;
+ end = layoutLeft = layoutRight - child.getMeasuredWidth();
+ }
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
int ltrLeft = layoutLeft;
layoutLeft = getWidth() - layoutRight;
@@ -337,6 +344,11 @@
? View.VISIBLE : View.GONE);
}
+ /** Updates icon visibility based on the noisiness of the notification. */
+ public void setAudiblyAlerted(boolean audiblyAlerted) {
+ mAudiblyAlertedIcon.setVisibility(audiblyAlerted ? View.VISIBLE : View.GONE);
+ }
+
private void updateExpandButton() {
int drawableId;
int contentDescriptionId;
diff --git a/core/java/android/view/TextureLayer.java b/core/java/android/view/TextureLayer.java
index d89d634..46dd436 100644
--- a/core/java/android/view/TextureLayer.java
+++ b/core/java/android/view/TextureLayer.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;
@@ -32,10 +33,10 @@
* @hide
*/
public final class TextureLayer {
- private ThreadedRenderer mRenderer;
+ private HardwareRenderer mRenderer;
private VirtualRefBasePtr mFinalizer;
- private TextureLayer(ThreadedRenderer renderer, long deferredUpdater) {
+ private TextureLayer(HardwareRenderer renderer, long deferredUpdater) {
if (renderer == null || deferredUpdater == 0) {
throw new IllegalArgumentException("Either hardware renderer: " + renderer
+ " or deferredUpdater: " + deferredUpdater + " is invalid");
@@ -139,7 +140,8 @@
mRenderer.pushLayerUpdate(this);
}
- static TextureLayer adoptTextureLayer(ThreadedRenderer renderer, long layer) {
+ /** @hide */
+ public static TextureLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
return new TextureLayer(renderer, layer);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f0f4c1c..bac0154 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,36 +16,24 @@
package android.view;
-import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
import android.graphics.Point;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RenderNode;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.Trace;
-import android.util.Log;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
import android.view.animation.AnimationUtils;
import com.android.internal.R;
-import com.android.internal.util.VirtualRefBasePtr;
-import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
/**
* Threaded renderer that proxies the rendering to a render thread. Most calls
@@ -66,15 +54,7 @@
*
* @hide
*/
-public final class ThreadedRenderer {
- private static final String LOG_TAG = "ThreadedRenderer";
-
- /**
- * Name of the file that holds the shaders cache.
- */
- private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
- private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
-
+public final class ThreadedRenderer extends HardwareRenderer {
/**
* System property used to enable or disable threaded rendering profiling.
* The default value of this property is assumed to be false.
@@ -271,21 +251,6 @@
}
/**
- * Sets the directory to use as a persistent storage for threaded rendering
- * resources.
- *
- * @param cacheDir A directory the current process can write to
- *
- * @hide
- */
- @UnsupportedAppUsage
- public static void setupDiskCache(File cacheDir) {
- ThreadedRenderer.setupShadersDiskCache(
- new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
- new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
- }
-
- /**
* Creates a threaded renderer using OpenGL.
*
* @param translucent True if the surface is translucent, false otherwise
@@ -300,55 +265,10 @@
return renderer;
}
- /**
- * Invoke this method when the system is running out of memory. This
- * method will attempt to recover as much memory as possible, based on
- * the specified hint.
- *
- * @param level Hint about the amount of memory that should be trimmed,
- * see {@link android.content.ComponentCallbacks}
- */
- public static void trimMemory(int level) {
- nTrimMemory(level);
- }
-
- public static void overrideProperty(@NonNull String name, @NonNull String value) {
- if (name == null || value == null) {
- throw new IllegalArgumentException("name and value must be non-null");
- }
- nOverrideProperty(name, value);
- }
-
- // Keep in sync with DrawFrameTask.h SYNC_* flags
- // Nothing interesting to report
- private static final int SYNC_OK = 0;
- // Needs a ViewRoot invalidate
- private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
- // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
- private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
- // setStopped is true, drawing is false
- // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
- // This flag isn't really used as there's nothing that we care to do
- // in response, so it really just exists to differentiate from LOST_SURFACE
- // but possibly both can just be deleted.
- private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
- private static final int SYNC_FRAME_DROPPED = 1 << 3;
-
private static final String[] VISUALIZERS = {
PROFILE_PROPERTY_VISUALIZE_BARS,
};
- private static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
- private static final int FLAG_DUMP_RESET = 1 << 1;
- private static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
-
- @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
- FLAG_DUMP_FRAMESTATS,
- FLAG_DUMP_RESET
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface DumpFlags {}
-
// Size of the rendered content.
private int mWidth, mHeight;
@@ -362,51 +282,37 @@
// Whether the surface has insets. Used to protect opacity.
private boolean mHasInsets;
- // Light and shadow properties specified by the theme.
+ // Light properties specified by the theme.
private final float mLightY;
private final float mLightZ;
private final float mLightRadius;
- private final int mAmbientShadowAlpha;
- private final int mSpotShadowAlpha;
- private long mNativeProxy;
private boolean mInitialized = false;
- private RenderNode mRootNode;
private boolean mRootNodeNeedsUpdate;
private boolean mEnabled;
private boolean mRequested = true;
- private boolean mIsOpaque = false;
ThreadedRenderer(Context context, boolean translucent, String name) {
+ super();
+ setName(name);
+ setOpaque(!translucent);
+
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
- mAmbientShadowAlpha =
- (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
- mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+ float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+ float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
a.recycle();
-
- long rootNodePtr = nCreateRootRenderNode();
- mRootNode = RenderNode.adopt(rootNodePtr);
- mRootNode.setClipToBounds(false);
- mIsOpaque = !translucent;
- mNativeProxy = nCreateProxy(translucent, rootNodePtr);
- nSetName(mNativeProxy, name);
-
- ProcessInitializer.sInstance.init(context, mNativeProxy);
-
- loadSystemProperties();
+ setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
}
- /**
- * Destroys the threaded rendering context.
- */
- void destroy() {
+ @Override
+ public void destroy() {
mInitialized = false;
updateEnabledState(null);
- nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+ super.destroy();
}
/**
@@ -464,7 +370,7 @@
boolean status = !mInitialized;
mInitialized = true;
updateEnabledState(surface);
- nInitialize(mNativeProxy, surface);
+ setSurface(surface);
return status;
}
@@ -505,26 +411,18 @@
*/
void updateSurface(Surface surface) throws OutOfResourcesException {
updateEnabledState(surface);
- nUpdateSurface(mNativeProxy, surface);
+ setSurface(surface);
}
- /**
- * Halts any current rendering into the surface. Use this if it is unclear whether
- * or not the surface used by the ThreadedRenderer will be changing. It
- * Suspends any rendering into the surface, but will not do any destruction.
- *
- * Any subsequent draws will override the pause, resuming normal operation.
- */
- boolean pauseSurface(Surface surface) {
- return nPauseSurface(mNativeProxy, surface);
- }
-
- /**
- * Hard stops or resumes rendering into the surface. This flag is used to
- * determine whether or not it is safe to use the given surface *at all*
- */
- void setStopped(boolean stopped) {
- nSetStopped(mNativeProxy, stopped);
+ @Override
+ public void setSurface(Surface surface) {
+ // TODO: Do we ever pass a non-null but isValid() = false surface?
+ // This is here to be super conservative for ViewRootImpl
+ if (surface != null && surface.isValid()) {
+ super.setSurface(surface);
+ } else {
+ super.setSurface(null);
+ }
}
/**
@@ -535,7 +433,7 @@
*/
void destroyHardwareResources(View view) {
destroyResources(view);
- nDestroyHardwareResources(mNativeProxy);
+ destroyHardwareResources();
}
private static void destroyResources(View view) {
@@ -543,14 +441,6 @@
}
/**
- * Detaches the layer's surface texture from the GL context and releases
- * the texture id
- */
- void detachSurfaceTexture(long hardwareLayer) {
- nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
- }
-
- /**
* Sets up the renderer for drawing.
*
* @param width The width of the drawing surface.
@@ -581,8 +471,6 @@
}
mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
- nSetup(mNativeProxy, mLightRadius,
- mAmbientShadowAlpha, mSpotShadowAlpha);
setLightCenter(attachInfo);
}
@@ -598,27 +486,7 @@
attachInfo.mDisplay.getRealSize(displaySize);
final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
final float lightY = mLightY - attachInfo.mWindowTop;
-
- nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
- }
-
- /**
- * Change the ThreadedRenderer's opacity
- */
- void setOpaque(boolean opaque) {
- mIsOpaque = opaque && !mHasInsets;
- nSetOpaque(mNativeProxy, mIsOpaque);
- }
-
- boolean isOpaque() {
- return mIsOpaque;
- }
-
- /**
- * Enable/disable wide gamut rendering on this renderer.
- */
- void setWideGamut(boolean wideGamut) {
- nSetWideGamut(mNativeProxy, wideGamut);
+ setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
}
/**
@@ -663,18 +531,12 @@
break;
}
}
- nDumpProfileInfo(mNativeProxy, fd, flags);
+ dumpProfileInfo(fd, flags);
}
- /**
- * Loads system properties used by the renderer. This method is invoked
- * whenever system properties are modified. Implementations can use this
- * to trigger live updates of the renderer based on properties.
- *
- * @return True if a property has changed.
- */
- boolean loadSystemProperties() {
- boolean changed = nLoadSystemProperties(mNativeProxy);
+ @Override
+ public boolean loadSystemProperties() {
+ boolean changed = super.loadSystemProperties();
if (changed) {
invalidateRoot();
}
@@ -695,72 +557,27 @@
updateViewTreeDisplayList(view);
if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
- RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+ RecordingCanvas canvas = mRootNode.startRecording(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
callbacks.onPreDraw(canvas);
- canvas.insertReorderBarrier();
+ canvas.enableZ();
canvas.drawRenderNode(view.updateDisplayListIfDirty());
- canvas.insertInorderBarrier();
+ canvas.disableZ();
callbacks.onPostDraw(canvas);
canvas.restoreToCount(saveCount);
mRootNodeNeedsUpdate = false;
} finally {
- mRootNode.end(canvas);
+ mRootNode.endRecording();
}
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
/**
- * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
- * rendernode of the UI thread.
- * @param node The node to add.
- * @param placeFront If true, the render node will be placed in front of the content node,
- * otherwise behind the content node.
- */
- @UnsupportedAppUsage
- public void addRenderNode(RenderNode node, boolean placeFront) {
- nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
- }
-
- /**
- * Only especially added render nodes can be removed.
- * @param node The node which was added via addRenderNode which should get removed again.
- */
- @UnsupportedAppUsage
- public void removeRenderNode(RenderNode node) {
- nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
- }
-
- /**
- * Draws a particular render node. If the node is not the content node, only the additional
- * nodes will get drawn and the content remains untouched.
- * @param node The node to be drawn.
- */
- @UnsupportedAppUsage
- public void drawRenderNode(RenderNode node) {
- nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
- }
-
- /**
- * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
- * will be prevented to overdraw this area. It will be synchronized with the draw call.
- * This should be updated in the content view's draw call.
- * @param left The left side of the protected bounds.
- * @param top The top side of the protected bounds.
- * @param right The right side of the protected bounds.
- * @param bottom The bottom side of the protected bounds.
- */
- @UnsupportedAppUsage
- public void setContentDrawBounds(int left, int top, int right, int bottom) {
- nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
- }
-
- /**
* Interface used to receive callbacks whenever a view is drawn by
* a threaded renderer instance.
*/
@@ -819,11 +636,10 @@
attachInfo.mPendingAnimatingRenderNodes = null;
}
- final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
if (frameDrawingCallback != null) {
- nSetFrameCallback(mNativeProxy, frameDrawingCallback);
+ setFrameCallback(frameDrawingCallback);
}
- int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
+ int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release();
@@ -831,207 +647,40 @@
// if it is still needed or do nothing if we are no longer drawing
attachInfo.mViewRootImpl.invalidate();
}
- if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+ if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
attachInfo.mViewRootImpl.invalidate();
}
}
- void setFrameCompleteCallback(FrameCompleteCallback callback) {
- nSetFrameCompleteCallback(mNativeProxy, callback);
- }
-
- static void invokeFunctor(long functor, boolean waitForCompletion) {
- nInvokeFunctor(functor, waitForCompletion);
- }
-
- /**
- * Creates a new hardware layer. A hardware layer built by calling this
- * method will be treated as a texture layer, instead of as a render target.
- *
- * @return A hardware layer
- */
- TextureLayer createTextureLayer() {
- long layer = nCreateTextureLayer(mNativeProxy);
- return TextureLayer.adoptTextureLayer(this, layer);
- }
-
-
- void buildLayer(RenderNode node) {
- if (node.hasDisplayList()) {
- nBuildLayer(mNativeProxy, node.mNativeRenderNode);
- }
- }
-
-
- boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
- return nCopyLayerInto(mNativeProxy,
- layer.getDeferredLayerUpdater(), bitmap);
- }
-
- /**
- * Indicates that the specified hardware layer needs to be updated
- * as soon as possible.
- *
- * @param layer The hardware layer that needs an update
- */
- void pushLayerUpdate(TextureLayer layer) {
- nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
- }
-
- /**
- * Tells the HardwareRenderer that the layer is destroyed. The renderer
- * should remove the layer from any update queues.
- */
- void onLayerDestroyed(TextureLayer layer) {
- nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
- }
-
- /**
- * Blocks until all previously queued work has completed.
- */
- void fence() {
- nFence(mNativeProxy);
- }
-
- /**
- * Prevents any further drawing until draw() is called. This is a signal
- * that the contents of the RenderNode tree are no longer safe to play back.
- * In practice this usually means that there are Functor pointers in the
- * display list that are no longer valid.
- */
- void stopDrawing() {
- nStopDrawing(mNativeProxy);
- }
-
- /**
- * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
- */
- public void notifyFramePending() {
- nNotifyFramePending(mNativeProxy);
- }
-
-
- void registerAnimatingRenderNode(RenderNode animator) {
- nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
- }
-
- void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
- nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
- animator.getAnimatorNativePtr());
- }
-
- public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
- if (srcRect == null) {
- // Empty rect means entire surface
- return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
- } else {
- return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
- srcRect.right, srcRect.bottom, bitmap);
- }
- }
-
- /**
- * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
- * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
- * not the RenderNode from a View.
- **/
- @UnsupportedAppUsage
- public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
- return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
- }
-
- /**
- * Sets whether or not high contrast text rendering is enabled. The setting is global
- * but only affects content rendered after the change is made.
- */
- public static void setHighContrastText(boolean highContrastText) {
- nSetHighContrastText(highContrastText);
- }
-
- /**
- * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
- */
- public static void setIsolatedProcess(boolean isIsolated) {
- nSetIsolatedProcess(isIsolated);
- }
-
- /**
- * If set extra graphics debugging abilities will be enabled such as dumping skp
- */
- public static void setDebuggingEnabled(boolean enable) {
- nSetDebuggingEnabled(enable);
- }
-
- void allocateBuffers(Surface surface) {
- nAllocateBuffers(mNativeProxy, surface);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- nDeleteProxy(mNativeProxy);
- mNativeProxy = 0;
- } finally {
- super.finalize();
- }
- }
-
/** The root of everything */
public @NonNull RenderNode getRootNode() {
return mRootNode;
}
- private boolean mForceDark = false;
-
- /**
- * Whether or not the force-dark feature should be used for this renderer.
- */
- public boolean setForceDark(boolean enable) {
- if (mForceDark != enable) {
- mForceDark = enable;
- nSetForceDark(mNativeProxy, enable);
- return true;
- }
- return false;
- }
-
/**
* Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
* TODO: deduplicate against ThreadedRenderer.
*
* @hide
*/
- public static class SimpleRenderer {
- private final RenderNode mRootNode;
- private long mNativeProxy;
- private final float mLightY, mLightZ;
- private Surface mSurface;
- private final FrameInfo mFrameInfo = new FrameInfo();
+ public static class SimpleRenderer extends HardwareRenderer {
+ private final float mLightY, mLightZ, mLightRadius;
public SimpleRenderer(final Context context, final String name, final Surface surface) {
+ super();
+ setName(name);
+ setOpaque(false);
+ setSurface(surface);
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
- final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+ mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
final int ambientShadowAlpha =
(int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
final int spotShadowAlpha =
(int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
a.recycle();
-
- final long rootNodePtr = nCreateRootRenderNode();
- mRootNode = RenderNode.adopt(rootNodePtr);
- mRootNode.setClipToBounds(false);
- mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
- nSetName(mNativeProxy, name);
-
- ProcessInitializer.sInstance.init(context, mNativeProxy);
- nLoadSystemProperties(mNativeProxy);
-
- nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
-
- mSurface = surface;
- nUpdateSurface(mNativeProxy, surface);
+ setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
}
/**
@@ -1045,7 +694,7 @@
final float lightX = displaySize.x / 2f - windowLeft;
final float lightY = mLightY - windowTop;
- nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
+ setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
}
public RenderNode getRootNode() {
@@ -1057,222 +706,10 @@
*/
public void draw(final FrameDrawingCallback callback) {
final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
- mFrameInfo.setVsync(vsync, vsync);
- mFrameInfo.addFlags(1 << 2 /* VSYNC */);
if (callback != null) {
- nSetFrameCallback(mNativeProxy, callback);
+ setFrameCallback(callback);
}
- nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
- }
-
- /**
- * Destroy the renderer.
- */
- public void destroy() {
- mSurface = null;
- nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- nDeleteProxy(mNativeProxy);
- mNativeProxy = 0;
- } finally {
- super.finalize();
- }
+ syncAndDrawFrame(vsync);
}
}
-
- /**
- * Interface used to receive callbacks when a frame is being drawn.
- */
- public interface FrameDrawingCallback {
- /**
- * Invoked during a frame drawing.
- *
- * @param frame The id of the frame being drawn.
- */
- void onFrameDraw(long frame);
- }
-
- /**
- * Interface used to be notified when a frame has finished rendering
- */
- public interface FrameCompleteCallback {
- /**
- * Invoked after a frame draw
- *
- * @param frameNr The id of the frame that was drawn.
- */
- void onFrameComplete(long frameNr);
- }
-
- private static class ProcessInitializer {
- static ProcessInitializer sInstance = new ProcessInitializer();
-
- private boolean mInitialized = false;
-
- private Context mAppContext;
- private IGraphicsStats mGraphicsStatsService;
- private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
- @Override
- public void onRotateGraphicsStatsBuffer() throws RemoteException {
- rotateBuffer();
- }
- };
-
- private ProcessInitializer() {}
-
- synchronized void init(Context context, long renderProxy) {
- if (mInitialized) return;
- mInitialized = true;
- mAppContext = context.getApplicationContext();
-
- initSched(renderProxy);
-
- if (mAppContext != null) {
- initGraphicsStats();
- }
- }
-
- private void initSched(long renderProxy) {
- try {
- int tid = nGetRenderThreadTid(renderProxy);
- ActivityManager.getService().setRenderThread(tid);
- } catch (Throwable t) {
- Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
- }
- }
-
- private void initGraphicsStats() {
- try {
- IBinder binder = ServiceManager.getService("graphicsstats");
- if (binder == null) return;
- mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
- requestBuffer();
- } catch (Throwable t) {
- Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
- }
- }
-
- private void rotateBuffer() {
- nRotateProcessStatsBuffer();
- requestBuffer();
- }
-
- private void requestBuffer() {
- try {
- final String pkg = mAppContext.getApplicationInfo().packageName;
- ParcelFileDescriptor pfd = mGraphicsStatsService
- .requestBufferForProcess(pkg, mGraphicsStatsCallback);
- nSetProcessStatsBuffer(pfd.getFd());
- pfd.close();
- } catch (Throwable t) {
- Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
- }
- }
- }
-
- void addFrameMetricsObserver(FrameMetricsObserver observer) {
- long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
- observer.mNative = new VirtualRefBasePtr(nativeObserver);
- }
-
- void removeFrameMetricsObserver(FrameMetricsObserver observer) {
- nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
- observer.mNative = null;
- }
-
- /** b/68769804: For low FPS experiments. */
- public static void setFPSDivisor(int divisor) {
- nHackySetRTAnimationsEnabled(divisor <= 1);
- }
-
- /**
- * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
- * called before any OpenGL context is created.
- *
- * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
- */
- public static void setContextPriority(int priority) {
- nSetContextPriority(priority);
- }
-
- /** Not actually public - internal use only. This doc to make lint happy */
- public static native void disableVsync();
-
- static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
-
- private static native void nRotateProcessStatsBuffer();
- private static native void nSetProcessStatsBuffer(int fd);
- private static native int nGetRenderThreadTid(long nativeProxy);
-
- private static native long nCreateRootRenderNode();
- private static native long nCreateProxy(boolean translucent, long rootRenderNode);
- private static native void nDeleteProxy(long nativeProxy);
-
- private static native boolean nLoadSystemProperties(long nativeProxy);
- private static native void nSetName(long nativeProxy, String name);
-
- private static native void nInitialize(long nativeProxy, Surface window);
- private static native void nUpdateSurface(long nativeProxy, Surface window);
- private static native boolean nPauseSurface(long nativeProxy, Surface window);
- private static native void nSetStopped(long nativeProxy, boolean stopped);
- private static native void nSetup(long nativeProxy,
- float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
- private static native void nSetLightCenter(long nativeProxy,
- float lightX, float lightY, float lightZ);
- private static native void nSetOpaque(long nativeProxy, boolean opaque);
- private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
- private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
- private static native void nDestroy(long nativeProxy, long rootRenderNode);
- private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
- private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
-
- private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
-
- private static native long nCreateTextureLayer(long nativeProxy);
- private static native void nBuildLayer(long nativeProxy, long node);
- private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
- private static native void nPushLayerUpdate(long nativeProxy, long layer);
- private static native void nCancelLayerUpdate(long nativeProxy, long layer);
- private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
-
- private static native void nDestroyHardwareResources(long nativeProxy);
- private static native void nTrimMemory(int level);
- private static native void nOverrideProperty(String name, String value);
-
- private static native void nFence(long nativeProxy);
- private static native void nStopDrawing(long nativeProxy);
- private static native void nNotifyFramePending(long nativeProxy);
-
- private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
- @DumpFlags int dumpFlags);
-
- private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
- boolean placeFront);
- private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
- private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
- private static native void nSetContentDrawBounds(long nativeProxy, int left,
- int top, int right, int bottom);
- private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
- private static native void nSetFrameCompleteCallback(long nativeProxy,
- FrameCompleteCallback callback);
-
- private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
- private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
-
- private static native int nCopySurfaceInto(Surface surface,
- int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
-
- private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
- private static native void nSetHighContrastText(boolean enabled);
- // For temporary experimentation b/66945974
- private static native void nHackySetRTAnimationsEnabled(boolean enabled);
- private static native void nSetDebuggingEnabled(boolean enabled);
- private static native void nSetIsolatedProcess(boolean enabled);
- private static native void nSetContextPriority(int priority);
- private static native void nAllocateBuffers(long nativeProxy, Surface window);
- private static native void nSetForceDark(long nativeProxy, boolean enabled);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 43fcce3..453d788 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9852,12 +9852,12 @@
// We weren't called from within a direct call to fitSystemWindows,
// call into it as a fallback in case we're in a class that overrides it
// and has logic to perform.
- if (fitSystemWindows(insets.getSystemWindowInsets())) {
+ if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
return insets.consumeSystemWindowInsets();
}
} else {
// We were called from within a direct call to fitSystemWindows.
- if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
+ if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
return insets.consumeSystemWindowInsets();
}
}
@@ -9960,7 +9960,7 @@
protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
outLocalInsets);
- inoutInsets.set(innerInsets.getSystemWindowInsets());
+ inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
return innerInsets.isSystemWindowInsetsConsumed();
}
@@ -9979,7 +9979,7 @@
|| mAttachInfo == null
|| ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
&& !mAttachInfo.mOverscanRequested)) {
- outLocalInsets.set(in.getSystemWindowInsets());
+ outLocalInsets.set(in.getSystemWindowInsetsAsRect());
return in.consumeSystemWindowInsets().inset(outLocalInsets);
} else {
// The application wants to take care of fitting system window for
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dd1f640..a23d68b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -46,6 +46,8 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.FrameInfo;
+import android.graphics.HardwareRenderer.FrameDrawingCallback;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -84,7 +86,6 @@
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl.Transaction;
-import android.view.ThreadedRenderer.FrameDrawingCallback;
import android.view.View.AttachInfo;
import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
@@ -2148,7 +2149,7 @@
// relayoutWindow may decide to destroy mSurface. As that decision
// happens in WindowManager service, we need to be defensive here
// and stop using the surface in case it gets destroyed.
- if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
+ if (mAttachInfo.mThreadedRenderer.pause()) {
// Animations were running so we need to push a frame
// to resume them
mDirty.set(0, 0, mWidth, mHeight);
@@ -2266,7 +2267,7 @@
& View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
// Don't pre-allocate if transparent regions
// are requested as they may not be needed
- mAttachInfo.mThreadedRenderer.allocateBuffers(mSurface);
+ mAttachInfo.mThreadedRenderer.allocateBuffers();
}
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 8628da3..4a7e783 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,8 +17,10 @@
package android.view;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
+import android.graphics.Insets;
import android.graphics.Rect;
import com.android.internal.util.Preconditions;
@@ -43,26 +45,24 @@
*/
public final class WindowInsets {
- private Rect mSystemWindowInsets;
- private Rect mWindowDecorInsets;
- private Rect mStableInsets;
- private Rect mTempRect;
- private boolean mIsRound;
- private DisplayCutout mDisplayCutout;
+ @NonNull private final Insets mSystemWindowInsets;
+ @NonNull private final Insets mWindowDecorInsets;
+ @NonNull private final Insets mStableInsets;
+ @Nullable private Rect mTempRect;
+ private final boolean mIsRound;
+ @Nullable private final DisplayCutout mDisplayCutout;
/**
* In multi-window we force show the navigation bar. Because we don't want that the surface size
* changes in this mode, we instead have a flag whether the navigation bar size should always
* be consumed, so the app is treated like there is no virtual navigation bar at all.
*/
- private boolean mAlwaysConsumeNavBar;
+ private final boolean mAlwaysConsumeNavBar;
- private boolean mSystemWindowInsetsConsumed = false;
- private boolean mWindowDecorInsetsConsumed = false;
- private boolean mStableInsetsConsumed = false;
- private boolean mDisplayCutoutConsumed = false;
-
- private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
+ private final boolean mSystemWindowInsetsConsumed;
+ private final boolean mWindowDecorInsetsConsumed;
+ private final boolean mStableInsetsConsumed;
+ private final boolean mDisplayCutoutConsumed;
/**
* Since new insets may be added in the future that existing apps couldn't
@@ -74,21 +74,27 @@
public static final WindowInsets CONSUMED;
static {
- CONSUMED = new WindowInsets(null, null, null, false, false, null);
+ CONSUMED = new WindowInsets((Insets) null, null, null, false, false, null);
}
/** @hide */
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
+ this(Insets.of(systemWindowInsets), Insets.of(windowDecorInsets), Insets.of(stableInsets),
+ isRound, alwaysConsumeNavBar, displayCutout);
+ }
+
+ private WindowInsets(Insets systemWindowInsets, Insets windowDecorInsets,
+ Insets stableInsets, boolean isRound, boolean alwaysConsumeNavBar,
+ DisplayCutout displayCutout) {
mSystemWindowInsetsConsumed = systemWindowInsets == null;
- mSystemWindowInsets = mSystemWindowInsetsConsumed
- ? EMPTY_RECT : new Rect(systemWindowInsets);
+ mSystemWindowInsets = mSystemWindowInsetsConsumed ? Insets.NONE : systemWindowInsets;
mWindowDecorInsetsConsumed = windowDecorInsets == null;
- mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : new Rect(windowDecorInsets);
+ mWindowDecorInsets = mWindowDecorInsetsConsumed ? Insets.NONE : windowDecorInsets;
mStableInsetsConsumed = stableInsets == null;
- mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : new Rect(stableInsets);
+ mStableInsets = mStableInsetsConsumed ? Insets.NONE : stableInsets;
mIsRound = isRound;
mAlwaysConsumeNavBar = alwaysConsumeNavBar;
@@ -104,16 +110,21 @@
* @param src Source to copy insets from
*/
public WindowInsets(WindowInsets src) {
- mSystemWindowInsets = src.mSystemWindowInsets;
- mWindowDecorInsets = src.mWindowDecorInsets;
- mStableInsets = src.mStableInsets;
- mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed;
- mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed;
- mStableInsetsConsumed = src.mStableInsetsConsumed;
- mIsRound = src.mIsRound;
- mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar;
- mDisplayCutout = src.mDisplayCutout;
- mDisplayCutoutConsumed = src.mDisplayCutoutConsumed;
+ this(src.mSystemWindowInsetsConsumed ? null : src.mSystemWindowInsets,
+ src.mWindowDecorInsetsConsumed ? null : src.mWindowDecorInsets,
+ src.mStableInsetsConsumed ? null : src.mStableInsets,
+ src.mIsRound, src.mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(src));
+ }
+
+ private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
+ if (w.mDisplayCutoutConsumed) {
+ return null;
+ } else if (w.mDisplayCutout == null) {
+ return DisplayCutout.NO_CUTOUT;
+ } else {
+ return w.mDisplayCutout;
+ }
}
/** @hide */
@@ -126,22 +137,35 @@
* Used to provide a safe copy of the system window insets to pass through
* to the existing fitSystemWindows method and other similar internals.
* @hide
+ *
+ * @deprecated use {@link #getSystemWindowInsets()} instead.
*/
- @UnsupportedAppUsage
- public Rect getSystemWindowInsets() {
+ @Deprecated
+ @NonNull
+ public Rect getSystemWindowInsetsAsRect() {
if (mTempRect == null) {
mTempRect = new Rect();
}
- if (mSystemWindowInsets != null) {
- mTempRect.set(mSystemWindowInsets);
- } else {
- // If there were no system window insets, this is just empty.
- mTempRect.setEmpty();
- }
+ mTempRect.set(mSystemWindowInsets.left, mSystemWindowInsets.top,
+ mSystemWindowInsets.right, mSystemWindowInsets.bottom);
return mTempRect;
}
/**
+ * Returns the system window insets in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return The system window insets
+ */
+ @NonNull
+ public Insets getSystemWindowInsets() {
+ return mSystemWindowInsets;
+ }
+
+ /**
* Returns the left system window inset in pixels.
*
* <p>The system window inset represents the area of a full-screen window that is
@@ -304,11 +328,13 @@
*
* @return A modified copy of this WindowInsets
*/
+ @NonNull
public WindowInsets consumeDisplayCutout() {
- final WindowInsets result = new WindowInsets(this);
- result.mDisplayCutout = null;
- result.mDisplayCutoutConsumed = true;
- return result;
+ return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ null /* displayCutout */);
}
@@ -349,101 +375,95 @@
*
* @return A modified copy of this WindowInsets
*/
+ @NonNull
public WindowInsets consumeSystemWindowInsets() {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = EMPTY_RECT;
- result.mSystemWindowInsetsConsumed = true;
- return result;
+ return new WindowInsets(null /* systemWindowInsets */,
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
- /**
- * Returns a copy of this WindowInsets with selected system window insets fully consumed.
- *
- * @param left true to consume the left system window inset
- * @param top true to consume the top system window inset
- * @param right true to consume the right system window inset
- * @param bottom true to consume the bottom system window inset
- * @return A modified copy of this WindowInsets
- * @hide pending API
- */
- public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
- boolean right, boolean bottom) {
- if (left || top || right || bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(
- left ? 0 : mSystemWindowInsets.left,
- top ? 0 : mSystemWindowInsets.top,
- right ? 0 : mSystemWindowInsets.right,
- bottom ? 0 : mSystemWindowInsets.bottom);
- return result;
- }
- return this;
- }
-
+ // TODO(b/119190588): replace @code with @link below
/**
* Returns a copy of this WindowInsets with selected system window insets replaced
* with new values.
*
+ * <p>Note: If the system window insets are already consumed, this method will return them
+ * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
+ * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
+ * whether they were consumed, and this method returns invalid non-zero consumed insets.
+ *
* @param left New left inset in pixels
* @param top New top inset in pixels
* @param right New right inset in pixels
* @param bottom New bottom inset in pixels
* @return A modified copy of this WindowInsets
+ * @deprecated use {@code Builder#Builder(WindowInsets)} with
+ * {@link Builder#setSystemWindowInsets(Insets)} instead.
*/
- public WindowInsets replaceSystemWindowInsets(int left, int top,
- int right, int bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(left, top, right, bottom);
- return result;
+ @Deprecated
+ @NonNull
+ public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) {
+ // Compat edge case: what should this do if the insets have already been consumed?
+ // On platforms prior to Q, the behavior was to override the insets with non-zero values,
+ // but leave them consumed, which is invalid (consumed insets must be zero).
+ // The behavior is now keeping them consumed and discarding the new insets.
+ if (mSystemWindowInsetsConsumed) {
+ return this;
+ }
+ return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build();
}
+ // TODO(b/119190588): replace @code with @link below
/**
* Returns a copy of this WindowInsets with selected system window insets replaced
* with new values.
*
+ * <p>Note: If the system window insets are already consumed, this method will return them
+ * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
+ * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
+ * whether they were consumed, and this method returns invalid non-zero consumed insets.
+ *
* @param systemWindowInsets New system window insets. Each field is the inset in pixels
* for that edge
* @return A modified copy of this WindowInsets
+ * @deprecated use {@code Builder#Builder(WindowInsets)} with
+ * {@link Builder#setSystemWindowInsets(Insets)} instead.
*/
+ @Deprecated
+ @NonNull
public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(systemWindowInsets);
- return result;
+ return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top,
+ systemWindowInsets.right, systemWindowInsets.bottom);
}
/**
* @hide
*/
+ @NonNull
public WindowInsets consumeWindowDecorInsets() {
- final WindowInsets result = new WindowInsets(this);
- result.mWindowDecorInsets.set(0, 0, 0, 0);
- result.mWindowDecorInsetsConsumed = true;
- return result;
+ return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+ null /* windowDecorInsets */,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
/**
- * @hide
+ * Returns the stable insets in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The stable insets
*/
- public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
- boolean right, boolean bottom) {
- if (left || top || right || bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left,
- top ? 0 : mWindowDecorInsets.top,
- right ? 0 : mWindowDecorInsets.right,
- bottom ? 0 : mWindowDecorInsets.bottom);
- return result;
- }
- return this;
- }
-
- /**
- * @hide
- */
- public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mWindowDecorInsets = new Rect(left, top, right, bottom);
- return result;
+ @NonNull
+ public Insets getStableInsets() {
+ return mStableInsets;
}
/**
@@ -527,11 +547,13 @@
*
* @return A modified copy of this WindowInsets
*/
+ @NonNull
public WindowInsets consumeStableInsets() {
- final WindowInsets result = new WindowInsets(this);
- result.mStableInsets = EMPTY_RECT;
- result.mStableInsetsConsumed = true;
- return result;
+ return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ null /* stableInsets */,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
/**
@@ -555,8 +577,11 @@
* Returns a copy of this instance inset in the given directions.
*
* @see #inset(int, int, int, int)
+ * @deprecated use {@link #inset(Insets)}
* @hide
*/
+ @Deprecated
+ @NonNull
public WindowInsets inset(Rect r) {
return inset(r.left, r.top, r.right, r.bottom);
}
@@ -564,6 +589,17 @@
/**
* Returns a copy of this instance inset in the given directions.
*
+ * @see #inset(int, int, int, int)
+ * @hide
+ */
+ @NonNull
+ public WindowInsets inset(Insets insets) {
+ return inset(insets.left, insets.top, insets.right, insets.bottom);
+ }
+
+ /**
+ * Returns a copy of this instance inset in the given directions.
+ *
* This is intended for dispatching insets to areas of the window that are smaller than the
* current area.
*
@@ -579,35 +615,27 @@
* @param bottom the amount of insets to remove from the bottom. Must be non-negative.
*
* @return the inset insets
- *
- * @hide pending API
*/
- @UnsupportedAppUsage
+ @NonNull
public WindowInsets inset(int left, int top, int right, int bottom) {
Preconditions.checkArgumentNonnegative(left);
Preconditions.checkArgumentNonnegative(top);
Preconditions.checkArgumentNonnegative(right);
Preconditions.checkArgumentNonnegative(bottom);
- WindowInsets result = new WindowInsets(this);
- if (!result.mSystemWindowInsetsConsumed) {
- result.mSystemWindowInsets =
- insetInsets(result.mSystemWindowInsets, left, top, right, bottom);
- }
- if (!result.mWindowDecorInsetsConsumed) {
- result.mWindowDecorInsets =
- insetInsets(result.mWindowDecorInsets, left, top, right, bottom);
- }
- if (!result.mStableInsetsConsumed) {
- result.mStableInsets = insetInsets(result.mStableInsets, left, top, right, bottom);
- }
- if (mDisplayCutout != null) {
- result.mDisplayCutout = result.mDisplayCutout.inset(left, top, right, bottom);
- if (result.mDisplayCutout.isEmpty()) {
- result.mDisplayCutout = null;
- }
- }
- return result;
+ return new WindowInsets(
+ mSystemWindowInsetsConsumed ? null :
+ insetInsets(mSystemWindowInsets, left, top, right, bottom),
+ mWindowDecorInsetsConsumed ? null :
+ insetInsets(mWindowDecorInsets, left, top, right, bottom),
+ mStableInsetsConsumed ? null :
+ insetInsets(mStableInsets, left, top, right, bottom),
+ mIsRound, mAlwaysConsumeNavBar,
+ mDisplayCutoutConsumed
+ ? null :
+ mDisplayCutout == null
+ ? DisplayCutout.NO_CUTOUT
+ : mDisplayCutout.inset(left, top, right, bottom));
}
@Override
@@ -634,7 +662,7 @@
mWindowDecorInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed);
}
- private static Rect insetInsets(Rect insets, int left, int top, int right, int bottom) {
+ private static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) {
int newLeft = Math.max(0, insets.left - left);
int newTop = Math.max(0, insets.top - top);
int newRight = Math.max(0, insets.right - right);
@@ -642,7 +670,7 @@
if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
return insets;
}
- return new Rect(newLeft, newTop, newRight, newBottom);
+ return Insets.of(newLeft, newTop, newRight, newBottom);
}
/**
@@ -651,4 +679,122 @@
boolean isSystemWindowInsetsConsumed() {
return mSystemWindowInsetsConsumed;
}
+
+ /**
+ * Builder for WindowInsets.
+ */
+ public static class Builder {
+
+ private Insets mSystemWindowInsets;
+ private Insets mStableInsets;
+ private DisplayCutout mDisplayCutout;
+
+ private Insets mWindowDecorInsets;
+ private boolean mIsRound;
+ private boolean mAlwaysConsumeNavBar;
+
+ /**
+ * Creates a builder where all insets are initially consumed.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Creates a builder where all insets are initialized from {@link WindowInsets}.
+ *
+ * @param insets the instance to initialize from.
+ */
+ public Builder(WindowInsets insets) {
+ mSystemWindowInsets = insets.mSystemWindowInsetsConsumed ? null
+ : insets.mSystemWindowInsets;
+ mStableInsets = insets.mStableInsetsConsumed ? null : insets.mStableInsets;
+ mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
+ mWindowDecorInsets = insets.mWindowDecorInsetsConsumed ? null
+ : insets.mWindowDecorInsets;
+ mIsRound = insets.mIsRound;
+ mAlwaysConsumeNavBar = insets.mAlwaysConsumeNavBar;
+ }
+
+ /**
+ * Sets system window insets in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system
+ * windows.</p>
+ *
+ * @see #getSystemWindowInsets()
+ * @return itself
+ */
+ @NonNull
+ public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) {
+ Preconditions.checkNotNull(systemWindowInsets);
+ mSystemWindowInsets = systemWindowInsets;
+ return this;
+ }
+
+ /**
+ * Sets the stable insets in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @see #getStableInsets()
+ * @return itself
+ */
+ @NonNull
+ public Builder setStableInsets(@NonNull Insets stableInsets) {
+ Preconditions.checkNotNull(stableInsets);
+ mStableInsets = stableInsets;
+ return this;
+ }
+
+ /**
+ * Sets the display cutout.
+ *
+ * @see #getDisplayCutout()
+ * @param displayCutout the display cutout or null if there is none
+ * @return itself
+ */
+ @NonNull
+ public Builder setDisplayCutout(@Nullable DisplayCutout displayCutout) {
+ mDisplayCutout = displayCutout != null ? displayCutout : DisplayCutout.NO_CUTOUT;
+ return this;
+ }
+
+ /** @hide */
+ @NonNull
+ public Builder setWindowDecorInsets(@NonNull Insets windowDecorInsets) {
+ Preconditions.checkNotNull(windowDecorInsets);
+ mWindowDecorInsets = windowDecorInsets;
+ return this;
+ }
+
+ /** @hide */
+ @NonNull
+ public Builder setRound(boolean round) {
+ mIsRound = round;
+ return this;
+ }
+
+ /** @hide */
+ @NonNull
+ public Builder setAlwaysConsumeNavBar(boolean alwaysConsumeNavBar) {
+ mAlwaysConsumeNavBar = alwaysConsumeNavBar;
+ return this;
+ }
+
+ /**
+ * Builds a {@link WindowInsets} instance.
+ *
+ * @return the {@link WindowInsets} instance.
+ */
+ @NonNull
+ public WindowInsets build() {
+ return new WindowInsets(mSystemWindowInsets, mWindowDecorInsets, mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar, mDisplayCutout);
+ }
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index a7d0cfb..88b9c80 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -21,6 +21,7 @@
import android.Manifest;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -54,6 +55,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IntPair;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -117,6 +120,39 @@
public static final String ACTION_CHOOSE_ACCESSIBILITY_BUTTON =
"com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON";
+ /**
+ * Annotations for content flag of UI.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "FLAG_CONTENT_" }, value = {
+ FLAG_CONTENT_ICONS,
+ FLAG_CONTENT_TEXT,
+ FLAG_CONTENT_CONTROLS
+ })
+ public @interface ContentFlag {}
+
+ /**
+ * Use this flag to indicate the content of a UI that times out contains icons.
+ *
+ * @see #getRecommendedTimeoutMillis(int, int)
+ */
+ public static final int FLAG_CONTENT_ICONS = 1;
+
+ /**
+ * Use this flag to indicate the content of a UI that times out contains text.
+ *
+ * @see #getRecommendedTimeoutMillis(int, int)
+ */
+ public static final int FLAG_CONTENT_TEXT = 2;
+
+ /**
+ * Use this flag to indicate the content of a UI that times out contains interactive controls.
+ *
+ * @see #getRecommendedTimeoutMillis(int, int)
+ */
+ public static final int FLAG_CONTENT_CONTROLS = 4;
+
@UnsupportedAppUsage
static final Object sInstanceSync = new Object();
@@ -142,7 +178,8 @@
int mRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK;
- int mMinimumUiTimeout;
+ int mInteractiveUiTimeout;
+ int mNonInteractiveUiTimeout;
boolean mIsTouchExplorationEnabled;
@@ -304,7 +341,9 @@
}
@Override
- public void notifyServicesStateChanged() {
+ public void notifyServicesStateChanged(long updatedUiTimeout) {
+ updateUiTimeout(updatedUiTimeout);
+
final ArrayMap<AccessibilityServicesStateChangeListener, Handler> listeners;
synchronized (mLock) {
if (mServicesStateChangeListeners.isEmpty()) {
@@ -326,11 +365,6 @@
public void setRelevantEventTypes(int eventTypes) {
mRelevantEventTypes = eventTypes;
}
-
- @Override
- public void setMinimumUiTimeout(int uiTimeout) {
- mMinimumUiTimeout = uiTimeout;
- }
};
/**
@@ -840,16 +874,35 @@
}
/**
- * Get the minimum timeout for changes to the UI needed by this user. Controls should remain
+ * Get the recommended timeout for changes to the UI needed by this user. Controls should remain
* on the screen for at least this long to give users time to react. Some users may need
* extra time to review the controls, or to reach them, or to activate assistive technology
* to activate the controls automatically.
+ * <p>
+ * Use the combination of content flags to indicate contents of UI. For example, use
+ * {@code FLAG_CONTENT_ICONS | FLAG_CONTENT_TEXT} for message notification which contains
+ * icons and text, or use {@code FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS} for button dialog
+ * which contains text and button controls.
+ * <p/>
*
- * @return The minimum ui timeout for the current user in milliseconds.
- * {@link Integer#MAX_VALUE} if timeout is infinite.
+ * @param originalTimeout The timeout appropriate for users with no accessibility needs.
+ * @param uiContentFlags The combination of flags {@link #FLAG_CONTENT_ICONS},
+ * {@link #FLAG_CONTENT_TEXT} or {@link #FLAG_CONTENT_CONTROLS} to
+ * indicate the contents of UI.
+ * @return The recommended UI timeout for the current user in milliseconds.
*/
- public int getMinimumUiTimeoutMillis() {
- return mMinimumUiTimeout;
+ public int getRecommendedTimeoutMillis(int originalTimeout, @ContentFlag int uiContentFlags) {
+ boolean hasControls = (uiContentFlags & FLAG_CONTENT_CONTROLS) != 0;
+ boolean hasIconsOrText = (uiContentFlags & FLAG_CONTENT_ICONS) != 0
+ || (uiContentFlags & FLAG_CONTENT_TEXT) != 0;
+ int recommendedTimeout = originalTimeout;
+ if (hasControls) {
+ recommendedTimeout = Math.max(recommendedTimeout, mInteractiveUiTimeout);
+ }
+ if (hasIconsOrText) {
+ recommendedTimeout = Math.max(recommendedTimeout, mNonInteractiveUiTimeout);
+ }
+ return recommendedTimeout;
}
/**
@@ -1192,7 +1245,7 @@
final long userStateAndRelevantEvents = service.addClient(mClient, mUserId);
setStateLocked(IntPair.first(userStateAndRelevantEvents));
mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents);
- mMinimumUiTimeout = service.getMinimumUiTimeout();
+ updateUiTimeout(service.getRecommendedTimeoutMillis());
mService = service;
} catch (RemoteException re) {
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
@@ -1266,6 +1319,17 @@
}
/**
+ * Update interactive and non-interactive UI timeout.
+ *
+ * @param uiTimeout A pair of {@code int}s. First integer for interactive one, and second
+ * integer for non-interactive one.
+ */
+ private void updateUiTimeout(long uiTimeout) {
+ mInteractiveUiTimeout = IntPair.first(uiTimeout);
+ mNonInteractiveUiTimeout = IntPair.second(uiTimeout);
+ }
+
+ /**
* Determines if the accessibility button within the system navigation area is supported.
*
* @return {@code true} if the accessibility button is supported on this device,
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 61a8a1da..2767a82 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -76,5 +76,5 @@
// System process only
boolean sendFingerprintGesture(int gestureKeyCode);
- int getMinimumUiTimeout();
+ long getRecommendedTimeoutMillis();
}
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index d2ddca3..94b9ad1 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -26,9 +26,7 @@
void setState(int stateFlags);
- void notifyServicesStateChanged();
+ void notifyServicesStateChanged(long updatedUiTimeout);
void setRelevantEventTypes(int eventTypes);
-
- void setMinimumUiTimeout(int uiTimeout);
}
diff --git a/core/java/android/view/inspector/ChildTraverser.java b/core/java/android/view/inspector/ChildTraverser.java
new file mode 100644
index 0000000..b775de5
--- /dev/null
+++ b/core/java/android/view/inspector/ChildTraverser.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+
+/**
+ * Interface for visiting all the child nodes of an inspectable object.
+ *
+ * Inspectable objects may return a collection of children as an array, an {@link Iterable} or an
+ * {@link java.util.Iterator}. This provides a unified API for traversing across all the children
+ * of an inspectable node.
+ *
+ * This interface is consumed by {@link InspectionHelper#traverseChildren(Object, ChildTraverser)}
+ * and may be implemented as a lambda.
+ *
+ * @see InspectionHelper#traverseChildren(Object, ChildTraverser)
+ * @hide
+ */
+@FunctionalInterface
+public interface ChildTraverser {
+ /**
+ * Visit one child object of a parent inspectable object.
+ *
+ * The iteration interface will filter null values out before passing them to this method, but
+ * some child objects may not be inspectable. It is up to the implementor to determine their
+ * inspectablity and what to do with them.
+ *
+ * @param child A child object, guaranteed not to be null.
+ */
+ void traverseChild(@NonNull Object child);
+}
diff --git a/core/java/android/view/inspector/InspectableChildren.java b/core/java/android/view/inspector/InspectableChildren.java
new file mode 100644
index 0000000..de8fa29
--- /dev/null
+++ b/core/java/android/view/inspector/InspectableChildren.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a getter for an inspectable node's inspectable children.
+ *
+ * This annotation can be applied to any getter that returns a collection of objects, either an
+ * array, an {@link Iterable} or a {@link java.util.Iterator}. The getter may return null, which
+ * will be treated as an empty collection. Additionally, the inspector will discard any null
+ * entries in the collection.
+ *
+ * By default, this annotation is inherited. At runtime, the inspector introspects on the class
+ * hierachy and uses the annotated getter from the bottommost class, if different from any
+ * annoated getters of the parent class. If a class inherits from a parent class with an annotated
+ * getter, but does not include this annotation, the child class will be traversed using the
+ * getter annotated on the parent. This holds true even if the child class overrides the getter.
+ *
+ * @see InspectionHelper#traverseChildren(Object, ChildTraverser)
+ * @see InspectionHelper#hasChildTraversal()
+ * @hide
+ */
+@Target({METHOD})
+@Retention(SOURCE)
+public @interface InspectableChildren {
+}
diff --git a/core/java/android/view/inspector/InspectableNodeName.java b/core/java/android/view/inspector/InspectableNodeName.java
new file mode 100644
index 0000000..716409c
--- /dev/null
+++ b/core/java/android/view/inspector/InspectableNodeName.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks the node name to display to a developer in the inspection tree.
+ *
+ * This annotation is optional to marking a class as inspectable. If it is omitted, the node name
+ * will be inferred using the semantics of {@link Class#getSimpleName()}. The fully qualified class
+ * name is always available in the tree, this is for display purposes only. If a class is inflated
+ * from XML and the tag it inflates from does not match its simple name, this annotation should be
+ * used to inform the inspector to display the XML tag name in the inspection tree view.
+ *
+ * This annotation does not inherit. If a class extends an annotated parent class, but does not
+ * annotate itself, its node name will be inferred from its Java name.
+ *
+ * @see InspectionHelper#getNodeName()
+ * @hide
+ */
+@Target({TYPE})
+@Retention(SOURCE)
+public @interface InspectableNodeName {
+ /**
+ * The display name for nodes of this type.
+ *
+ * @return The name for nodes of this type
+ */
+ String value();
+}
diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java
new file mode 100644
index 0000000..b0fd503
--- /dev/null
+++ b/core/java/android/view/inspector/InspectableProperty.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a getter of a property on an inspectable node.
+ *
+ * This annotation is inherited by default. If a child class doesn't add it to a getter, but a
+ * parent class does, the property will be inspected, even if the child overrides the definition
+ * of the getter. If a child class defines a property of the same name of a property on the parent
+ * but on a different getter, the inspector will use the child's getter when inspecting instances
+ * of the child, and the parent's otherwise.
+ *
+ * @see InspectionHelper#mapProperties(PropertyMapper)
+ * @see InspectionHelper#readProperties(Object, PropertyReader)
+ * @hide
+ */
+@Target({METHOD})
+@Retention(SOURCE)
+public @interface InspectableProperty {
+ /**
+ * The name of the property.
+ *
+ * If left empty (the default), the property name will be inferred from the name of the getter
+ * method.
+ *
+ * @return The name of the property.
+ */
+ String value() default "";
+}
diff --git a/core/java/android/view/inspector/InspectionHelper.java b/core/java/android/view/inspector/InspectionHelper.java
new file mode 100644
index 0000000..27a9704
--- /dev/null
+++ b/core/java/android/view/inspector/InspectionHelper.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * An interface for companion objects used to inspect views.
+ *
+ * Inspection helpers only need to handle the properties, name and traversal of the specific class
+ * they are defined for, not anything from a parent class. At runtime, the inspector instantiates
+ * one instance of each inspection helper, and handles visiting them in the correct inheritance
+ * order for each type it inspects.
+ *
+ * Properties are read from the top of the type tree to the bottom, so that classes that override
+ * a property in their parent class can overwrite it in the reader. In general, properties will
+ * cleanly inherit through their getters, and the inspector runtime will read the properties of a
+ * parent class via the parent's inspection helper, and the child helper will only read properties
+ * added or changed since the parent was defined.
+ *
+ * Only one child traversal is considered for each class. If a descendant class defines a
+ * different child traversal than its parent, only the bottom traversal is used. If a class does
+ * not define its own child traversal, but one of its ancestors does, the bottom-most ancestor's
+ * traversal will be used.
+ *
+ * @param <T> The type of inspectable this helper operates on
+ * @hide
+ */
+public interface InspectionHelper<T> {
+ /**
+ * Map the string names of the properties this helper knows about to integer IDs.
+ *
+ * Each helper is responsible for storing the integer IDs of all its properties. This is the
+ * only method that is allowed to modify the stored IDs.
+ *
+ * Calling {@link #readProperties(T, PropertyReader)} before calling this results in
+ * undefined behavior.
+ *
+ * @param propertyMapper A {@link PropertyMapper} or lambda which maps string names to IDs.
+ */
+ void mapProperties(@NonNull PropertyMapper propertyMapper);
+
+ /**
+ * Read the values of an instance of this helper's type into a {@link PropertyReader}.
+ *
+ * This method needs to return the property IDs stored by
+ * {@link #mapProperties(PropertyMapper)}. Implementations should track if their properties
+ * have been mapped and throw a {@link UninitializedPropertyMapException} if this method is
+ * called before {mapProperties}.
+ *
+ * @param inspectable A object of type {@link T} to read the properties of.
+ * @param propertyReader An object which receives the property IDs and values.
+ */
+ void readProperties(@NonNull T inspectable, @NonNull PropertyReader propertyReader);
+
+ /**
+ * Query if this inspectable type can potentially have child nodes.
+ *
+ * E.g.: any descendant of {@link android.view.ViewGroup} can have child nodes, but a leaf
+ * view like {@link android.widget.ImageView} may not.
+ *
+ * The default implementation always returns false. If an implementing class overrides this, it
+ * should also define {@link #traverseChildren(T, ChildTraverser)}.
+ *
+ * @return True if this inspectable type can potentially have child nodes, false otherwise.
+ */
+ default boolean hasChildTraversal() {
+ return false;
+ }
+
+ /**
+ * Traverse the child nodes of an instance of this helper's type into a {@link ChildTraverser}.
+ *
+ * This provides the ability to traverse over a variety of collection APIs (e.g.: arrays,
+ * {@link Iterable}, or {@link java.util.Iterator}) in a uniform fashion. The traversal must be
+ * in the order defined by this helper's type. If the getter returns null, the helper must
+ * treat it as an empty collection.
+ *
+ * The default implementation throws a {@link NoChildTraversalException}. If
+ * {@link #hasChildTraversal()} returns is overriden to return true, it is expected that the
+ * implementing class will also override this method and provide a traversal.
+ *
+ * @param inspectable An object of type {@link T} to traverse the child nodes of.
+ * @param childTraverser A {@link ChildTraverser} or lamba to receive the children in order.
+ * @throws NoChildTraversalException If there is no defined child traversal
+ */
+ default void traverseChildren(
+ @NonNull T inspectable,
+ @SuppressWarnings("unused") @NonNull ChildTraverser childTraverser) {
+ throw new NoChildTraversalException(inspectable.getClass());
+ }
+
+ /**
+ * Get an optional name to display to developers for inspection nodes of this helper's type.
+ *
+ * The default implementation returns null, which will cause the runtime to use the class's
+ * simple name as defined by {@link Class#getSimpleName()} as the node name.
+ *
+ * If the type of this helper is inflated from XML, this method should be overridden to return
+ * the string used as the tag name for this type in XML.
+ *
+ * @return A string to use as the node name, or null to use the simple class name fallback.
+ */
+ @Nullable
+ default String getNodeName() {
+ return null;
+ }
+
+ /**
+ * Thrown by {@link #readProperties(Object, PropertyReader)} if called before
+ * {@link #mapProperties(PropertyMapper)}.
+ */
+ class UninitializedPropertyMapException extends RuntimeException {
+ public UninitializedPropertyMapException() {
+ super("Unable to read properties of an inspectable before mapping their IDs.");
+ }
+ }
+
+ /**
+ * Thrown by {@link #traverseChildren(Object, ChildTraverser)} if no child traversal exists.
+ */
+ class NoChildTraversalException extends RuntimeException {
+ public NoChildTraversalException(Class cls) {
+ super(String.format(
+ "Class %s does not have a defined child traversal. Cannot traverse children.",
+ cls.getCanonicalName()
+ ));
+ }
+ }
+}
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
new file mode 100644
index 0000000..0473f54
--- /dev/null
+++ b/core/java/android/view/inspector/OWNERS
@@ -0,0 +1,3 @@
+alanv@google.com
+ashleyrose@google.com
+aurimas@google.com
\ No newline at end of file
diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java
new file mode 100644
index 0000000..35550bd
--- /dev/null
+++ b/core/java/android/view/inspector/PropertyMapper.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+
+/**
+ * An interface for mapping the string names of inspectable properties to integer identifiers.
+ *
+ * This interface is consumed by {@link InspectionHelper#mapProperties(PropertyMapper)}.
+ *
+ * Mapping properties to IDs enables quick comparisons against shadow copies of inspectable
+ * objects without performing a large number of string comparisons.
+ *
+ * @see InspectionHelper#mapProperties(PropertyMapper)
+ * @hide
+ */
+public interface PropertyMapper {
+ /**
+ * Map a string name to an integer ID for a primitive boolean property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapBoolean(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive byte property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapByte(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive char property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapChar(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive double property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapDouble(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive float property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapFloat(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive int property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapInt(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive long property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapLong(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for a primitive short property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapShort(@NonNull String name);
+
+ /**
+ * Map a string name to an integer ID for an object property.
+ *
+ * @param name The name of the property
+ * @return An integer ID for the property
+ * @throws PropertyConflictException If the property name is already mapped as another type.
+ */
+ int mapObject(@NonNull String name);
+
+ /**
+ * Thrown from a map method if a property name is already mapped as different type.
+ */
+ class PropertyConflictException extends RuntimeException {
+ public PropertyConflictException(
+ @NonNull String name,
+ @NonNull String newPropertyType,
+ @NonNull String existingPropertyType) {
+ super(String.format(
+ "Attempted to map property \"%s\" as type %s, but it is already mapped as %s.",
+ name,
+ newPropertyType,
+ existingPropertyType
+ ));
+ }
+ }
+}
diff --git a/core/java/android/view/inspector/PropertyReader.java b/core/java/android/view/inspector/PropertyReader.java
new file mode 100644
index 0000000..df81c10
--- /dev/null
+++ b/core/java/android/view/inspector/PropertyReader.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * An interface for reading the properties of an inspectable object.
+ *
+ * Used as the parameter for {@link InspectionHelper#readProperties(Object, PropertyReader)}.
+ * It has separate methods for all primitive types to avoid autoboxing overhead if a concrete
+ * implementation is able to work with primitives. Implementations should be prepared to accept
+ * {null} as the value of {@link PropertyReader#readObject(int, Object)}.
+ *
+ * @see InspectionHelper#readProperties(Object, PropertyReader)
+ * @hide
+ */
+public interface PropertyReader {
+ /**
+ * Read a primitive boolean property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {boolean}
+ */
+ void readBoolean(int id, boolean value);
+
+ /**
+ * Read a primitive byte property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {byte}
+ */
+ void readByte(int id, byte value);
+
+ /**
+ * Read a primitive character property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {char}
+ */
+ void readChar(int id, char value);
+
+ /**
+ * Read a read a primitive double property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {double}
+ */
+ void readDouble(int id, double value);
+
+ /**
+ * Read a primitive float property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {float}
+ */
+ void readFloat(int id, float value);
+
+ /**
+ * Read a primitive integer property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as an {int}
+ */
+ void readInt(int id, int value);
+
+ /**
+ * Read a primitive long property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {long}
+ */
+ void readLong(int id, long value);
+
+ /**
+ * Read a primitive short property.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as a {short}
+ */
+ void readShort(int id, short value);
+
+ /**
+ * Read any object as a property.
+ *
+ * If value is null, the property is marked as empty.
+ *
+ * @param id Identifier of the property from a {@link PropertyMapper}
+ * @param value Value of the property
+ * @throws PropertyTypeMismatchException If the property ID is not mapped as an object
+ */
+ void readObject(int id, @Nullable Object value);
+
+ /**
+ * Thrown if a client calls a typed read method for a property of a different type.
+ */
+ class PropertyTypeMismatchException extends RuntimeException {
+ public PropertyTypeMismatchException(
+ int id,
+ @NonNull String expectedPropertyType,
+ @NonNull String actualPropertyType,
+ @Nullable String propertyName) {
+ super(formatMessage(id, expectedPropertyType, actualPropertyType, propertyName));
+ }
+
+ public PropertyTypeMismatchException(
+ int id,
+ @NonNull String expectedPropertyType,
+ @NonNull String actualPropertyType) {
+ super(formatMessage(id, expectedPropertyType, actualPropertyType, null));
+ }
+
+ private static @NonNull String formatMessage(
+ int id,
+ @NonNull String expectedPropertyType,
+ @NonNull String actualPropertyType,
+ @Nullable String propertyName) {
+
+ if (propertyName == null) {
+ return String.format(
+ "Attempted to read property with ID 0x%08X as type %s, "
+ + "but the ID is of type %s.",
+ id,
+ expectedPropertyType,
+ actualPropertyType
+ );
+ } else {
+ return String.format(
+ "Attempted to read property \"%s\" with ID 0x%08X as type %s, "
+ + "but the ID is of type %s.",
+ propertyName,
+ id,
+ expectedPropertyType,
+ actualPropertyType
+ );
+ }
+ }
+ }
+}
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/core/java/android/view/intelligence/ContentCaptureEvent.aidl
new file mode 100644
index 0000000..c66a6cb
--- /dev/null
+++ b/core/java/android/view/intelligence/ContentCaptureEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.intelligence;
+
+parcelable ContentCaptureEvent;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/intelligence/ContentCaptureEvent.java
index d6aec34..2530ae3 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/intelligence/ContentCaptureEvent.java
@@ -30,6 +30,11 @@
@SystemApi
public final class ContentCaptureEvent implements Parcelable {
+ /** @hide */
+ public static final int TYPE_ACTIVITY_DESTROYED = -2;
+ /** @hide */
+ public static final int TYPE_ACTIVITY_CREATED = -1;
+
/**
* Called when the activity is started.
*/
@@ -85,10 +90,18 @@
TYPE_VIEW_TEXT_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
- @interface EventType{}
+ public @interface EventType{}
+
+ private final int mType;
+ private final long mEventTime;
+ private final int mFlags;
+
/** @hide */
- ContentCaptureEvent() {
+ public ContentCaptureEvent(int type, long eventTime, int flags) {
+ mType = type;
+ mEventTime = eventTime;
+ mFlags = flags;
}
/**
@@ -99,14 +112,14 @@
* {@link #TYPE_VIEW_ADDED}, {@link #TYPE_VIEW_REMOVED}, or {@link #TYPE_VIEW_TEXT_CHANGED}.
*/
public @EventType int getType() {
- return 42;
+ return mType;
}
/**
* Gets when the event was generated, in ms.
*/
public long getEventTime() {
- return 48151623;
+ return mEventTime;
}
/**
@@ -116,7 +129,7 @@
* {@link android.view.intelligence.IntelligenceManager#FLAG_USER_INPUT}.
*/
public int getFlags() {
- return 0;
+ return mFlags;
}
/**
@@ -150,13 +163,25 @@
}
@Override
+ public String toString() {
+ final StringBuilder string = new StringBuilder("ContentCaptureEvent[type=")
+ .append(getTypeAsString(mType)).append(", time=").append(mEventTime);
+ if (mFlags > 0) {
+ string.append(", flags=").append(mFlags);
+ }
+ return string.append(']').toString();
+ }
+
+ @Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
- // TODO(b/111276913): implement
+ parcel.writeInt(mType);
+ parcel.writeLong(mEventTime);
+ parcel.writeInt(mFlags);
}
public static final Parcelable.Creator<ContentCaptureEvent> CREATOR =
@@ -164,8 +189,10 @@
@Override
public ContentCaptureEvent createFromParcel(Parcel parcel) {
- // TODO(b/111276913): implement
- return null;
+ final int type = parcel.readInt();
+ final long eventTime = parcel.readLong();
+ final int flags = parcel.readInt();
+ return new ContentCaptureEvent(type, eventTime, flags);
}
@Override
@@ -173,4 +200,27 @@
return new ContentCaptureEvent[size];
}
};
+
+
+ /** @hide */
+ public static String getTypeAsString(@EventType int type) {
+ switch (type) {
+ case TYPE_ACTIVITY_STARTED:
+ return "ACTIVITY_STARTED";
+ case TYPE_ACTIVITY_RESUMED:
+ return "ACTIVITY_RESUMED";
+ case TYPE_ACTIVITY_PAUSED:
+ return "ACTIVITY_PAUSED";
+ case TYPE_ACTIVITY_STOPPED:
+ return "ACTIVITY_STOPPED";
+ case TYPE_VIEW_ADDED:
+ return "VIEW_ADDED";
+ case TYPE_VIEW_REMOVED:
+ return "VIEW_REMOVED";
+ case TYPE_VIEW_TEXT_CHANGED:
+ return "VIEW_TEXT_CHANGED";
+ default:
+ return "UKNOWN_TYPE: " + type;
+ }
+ }
}
diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl
index f4901c3..2f128de 100644
--- a/core/java/android/view/intelligence/IIntelligenceManager.aidl
+++ b/core/java/android/view/intelligence/IIntelligenceManager.aidl
@@ -18,8 +18,13 @@
import android.content.ComponentName;
import android.os.IBinder;
+import android.service.intelligence.InteractionSessionId;
+import android.view.intelligence.ContentCaptureEvent;
+
import com.android.internal.os.IResultReceiver;
+import java.util.List;
+
/**
* {@hide}
*/
@@ -28,11 +33,16 @@
* Starts a session, sending the "remote" sessionId to the receiver.
*/
void startSession(int userId, IBinder activityToken, in ComponentName componentName,
- int localSessionId, int flags, in IResultReceiver result);
+ in InteractionSessionId sessionId, int flags, in IResultReceiver result);
/**
* Finishes a session.
*/
- void finishSession(int userId, IBinder activityToken, in ComponentName componentName,
- int localSessionId, int globalSessionId);
+ void finishSession(int userId, in InteractionSessionId sessionId);
+
+ /**
+ * Sends a batch of events
+ */
+ void sendEvents(int userId, in InteractionSessionId sessionId,
+ in List<ContentCaptureEvent> events);
}
diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java
index b1d06f7..9bf6c2c 100644
--- a/core/java/android/view/intelligence/IntelligenceManager.java
+++ b/core/java/android/view/intelligence/IntelligenceManager.java
@@ -24,13 +24,18 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.intelligence.InteractionSessionId;
import android.util.Log;
+import android.view.intelligence.ContentCaptureEvent.EventType;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
import java.util.Set;
/**
@@ -51,9 +56,6 @@
public static final int FLAG_USER_INPUT = 0x1;
- /** @hide */
- public static final int NO_SESSION = 0;
-
/**
* Initial state, when there is no session.
*
@@ -62,11 +64,11 @@
public static final int STATE_UNKNOWN = 0;
/**
- * Service's startSession() was called, but remote session id was not returned yet.
+ * Service's startSession() was called, but server didn't confirm it was created yet.
*
* @hide
*/
- public static final int STATE_WAITING_FOR_SESSION_ID = 1;
+ public static final int STATE_WAITING_FOR_SERVER = 1;
/**
* Session is active.
@@ -75,8 +77,6 @@
*/
public static final int STATE_ACTIVE = 2;
- private static int sNextSessionId;
-
private final Context mContext;
@Nullable
@@ -84,14 +84,9 @@
private final Object mLock = new Object();
- // TODO(b/111276913): localSessionId might be an overkill, perhaps just the global id is enough.
- // Let's keep both for now, and revisit once we decide whether the session id will be persisted
- // when the activity's process is killed
+ @Nullable
@GuardedBy("mLock")
- private int mLocalSessionId = NO_SESSION;
-
- @GuardedBy("mLock")
- private int mRemoteSessionId = NO_SESSION;
+ private InteractionSessionId mId;
@GuardedBy("mLock")
private int mState = STATE_UNKNOWN;
@@ -120,27 +115,25 @@
+ getStateAsStringLocked());
return;
}
- mState = STATE_WAITING_FOR_SESSION_ID;
- mLocalSessionId = ++sNextSessionId;
- mRemoteSessionId = NO_SESSION;
+ mState = STATE_WAITING_FOR_SERVER;
+ mId = new InteractionSessionId();
mApplicationToken = token;
mComponentName = componentName;
if (VERBOSE) {
Log.v(TAG, "onActivityStarted(): token=" + token + ", act=" + componentName
- + ", localSessionId=" + mLocalSessionId);
+ + ", id=" + mId);
}
final int flags = 0; // TODO(b/111276913): get proper flags
try {
mService.startSession(mContext.getUserId(), mApplicationToken, componentName,
- mLocalSessionId, flags, new IResultReceiver.Stub() {
+ mId, flags, new IResultReceiver.Stub() {
@Override
public void send(int resultCode, Bundle resultData)
throws RemoteException {
synchronized (mLock) {
if (resultCode > 0) {
- mRemoteSessionId = resultCode;
mState = STATE_ACTIVE;
} else {
// TODO(b/111276913): handle other cases like disabled by
@@ -149,7 +142,7 @@
}
if (VERBOSE) {
Log.v(TAG, "onActivityStarted() result: code=" + resultCode
- + ", remoteSession=" + mRemoteSessionId
+ + ", id=" + mId
+ ", state=" + getStateAsStringLocked());
}
}
@@ -161,6 +154,37 @@
}
}
+ /**
+ * Used for intermediate events (i.e, other than created and destroyed).
+ *
+ * @hide
+ */
+ public void onActivityLifecycleEvent(@EventType int type) {
+ if (!isContentCaptureEnabled()) return;
+
+ //TODO(b/111276913): should buffer event (and call service on handler thread), instead of
+ // calling right away
+ final ContentCaptureEvent event = new ContentCaptureEvent(type, SystemClock.uptimeMillis(),
+ 0);
+ final List<ContentCaptureEvent> events = Arrays.asList(event);
+
+ synchronized (mLock) {
+ //TODO(b/111276913): check session state; for example, how to handle if it's waiting for
+ // remote id
+
+ if (VERBOSE) {
+ Log.v(TAG, "onActivityLifecycleEvent() for " + mComponentName.flattenToShortString()
+ + ": " + ContentCaptureEvent.getTypeAsString(type));
+ }
+
+ try {
+ mService.sendEvents(mContext.getUserId(), mId, events);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
/** @hide */
public void onActivityDestroyed() {
if (!isContentCaptureEnabled()) return;
@@ -171,15 +195,13 @@
if (VERBOSE) {
Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsStringLocked()
- + ", localSessionId=" + mLocalSessionId
- + ", mRemoteSessionId=" + mRemoteSessionId);
+ + ", mId=" + mId);
}
try {
- mService.finishSession(mContext.getUserId(), mApplicationToken, mComponentName,
- mLocalSessionId, mRemoteSessionId);
+ mService.finishSession(mContext.getUserId(), mId);
mState = STATE_UNKNOWN;
- mLocalSessionId = mRemoteSessionId = NO_SESSION;
+ mId = null;
mApplicationToken = null;
mComponentName = null;
} catch (RemoteException e) {
@@ -298,12 +320,11 @@
pw.print(prefix2); pw.print("mService: "); pw.println(mService);
pw.print(prefix2); pw.print("user: "); pw.println(mContext.getUserId());
pw.print(prefix2); pw.print("enabled: "); pw.println(isContentCaptureEnabled());
- pw.print(prefix2); pw.print("mLocalSessionId: "); pw.println(mLocalSessionId);
- pw.print(prefix2); pw.print("mRemoteSessionId: "); pw.println(mRemoteSessionId);
- pw.print(prefix2); pw.print("mState: "); pw.print(mState); pw.print(" (");
+ pw.print(prefix2); pw.print("id: "); pw.println(mId);
+ pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
pw.print(getStateAsStringLocked()); pw.println(")");
- pw.print(prefix2); pw.print("mAppToken: "); pw.println(mApplicationToken);
- pw.print(prefix2); pw.print("mComponentName: "); pw.println(mComponentName);
+ pw.print(prefix2); pw.print("appToken: "); pw.println(mApplicationToken);
+ pw.print(prefix2); pw.print("componentName: "); pw.println(mComponentName);
}
}
@@ -317,8 +338,8 @@
switch (state) {
case STATE_UNKNOWN:
return "UNKNOWN";
- case STATE_WAITING_FOR_SESSION_ID:
- return "WAITING_FOR_SESSION_ID";
+ case STATE_WAITING_FOR_SERVER:
+ return "WAITING_FOR_SERVER";
case STATE_ACTIVE:
return "ACTIVE";
default:
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f96f088..5b1544b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3928,6 +3928,7 @@
SelectionModifierCursorController selectionController = getSelectionController();
if (selectionController.mStartHandle == null) {
// As these are for initializing selectionController, hide() must be called.
+ loadHandleDrawables(false /* overwrite */);
selectionController.initHandles();
selectionController.hide();
}
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 6a3fc0f..9da2a43 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -28,6 +28,7 @@
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
+import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PixelFormat;
@@ -568,7 +569,7 @@
private Point getCurrentClampedWindowCoordinates() {
final Rect windowBounds;
if (mParentSurface.mIsMainWindowSurface) {
- final Rect systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
+ final Insets systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
windowBounds = new Rect(systemInsets.left, systemInsets.top,
mParentSurface.mWidth - systemInsets.right,
mParentSurface.mHeight - systemInsets.bottom);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index aa7bdb6..e2c23de 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1001,7 +1001,7 @@
insets.getSystemWindowInsetRight(), 0);
}
}
- mFrameOffsets.set(insets.getSystemWindowInsets());
+ mFrameOffsets.set(insets.getSystemWindowInsetsAsRect());
insets = updateColorViews(insets, true /* animate */);
insets = updateStatusGuard(insets);
if (getForeground() != null) {
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 4a1c955..ba0ff01 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -313,8 +313,7 @@
pullChildren();
final int vis = getWindowSystemUiVisibility();
- final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
- final Rect systemInsets = insets.getSystemWindowInsets();
+ final Rect systemInsets = insets.getSystemWindowInsetsAsRect();
// The top and bottom action bars are always within the content area.
boolean changed = applyInsets(mActionBarTop, systemInsets, true, true, false, true);
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index e07a208..2e7501f 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -83,7 +83,8 @@
return 0;
}
std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
- builder->langId, builder->variant, std::move(builder->fonts));
+ builder->langId, builder->variant, std::move(builder->fonts),
+ true /* isCustomFallback */);
if (family->getCoverage().length() == 0) {
return 0;
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index d391de7..a8b0640 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -28,6 +28,7 @@
#include "SkBlurDrawLooper.h"
#include "SkColorFilter.h"
+#include "SkFontTypes.h"
#include "SkMaskFilter.h"
#include "SkPath.h"
#include "SkPathEffect.h"
@@ -684,13 +685,13 @@
}
static jint getHinting(jlong paintHandle) {
- return reinterpret_cast<Paint*>(paintHandle)->getHinting()
- == Paint::kNo_Hinting ? 0 : 1;
+ return (SkFontHinting)reinterpret_cast<Paint*>(paintHandle)->getHinting()
+ == kNo_SkFontHinting ? 0 : 1;
}
static void setHinting(jlong paintHandle, jint mode) {
reinterpret_cast<Paint*>(paintHandle)->setHinting(
- mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting);
+ mode == 0 ? kNo_SkFontHinting : kNormal_SkFontHinting);
}
static void setAntiAlias(jlong paintHandle, jboolean aa) {
diff --git a/core/jni/android/graphics/fonts/FontFamily.cpp b/core/jni/android/graphics/fonts/FontFamily.cpp
index 767e068..249e4f3 100644
--- a/core/jni/android/graphics/fonts/FontFamily.cpp
+++ b/core/jni/android/graphics/fonts/FontFamily.cpp
@@ -57,7 +57,7 @@
// Regular JNI
static jlong FontFamily_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr,
- jstring langTags, jint variant) {
+ jstring langTags, jint variant, jboolean isCustomFallback) {
std::unique_ptr<NativeFamilyBuilder> builder(toBuilder(builderPtr));
uint32_t localeId;
if (langTags == nullptr) {
@@ -67,7 +67,8 @@
localeId = minikin::registerLocaleList(str.c_str());
}
std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
- localeId, static_cast<minikin::FamilyVariant>(variant), std::move(builder->fonts));
+ localeId, static_cast<minikin::FamilyVariant>(variant), std::move(builder->fonts),
+ isCustomFallback);
if (family->getCoverage().length() == 0) {
// No coverage means minikin rejected given font for some reasons.
jniThrowException(env, "java/lang/IllegalArgumentException",
@@ -87,7 +88,7 @@
static const JNINativeMethod gFontFamilyBuilderMethods[] = {
{ "nInitBuilder", "()J", (void*) FontFamily_Builder_initBuilder },
{ "nAddFont", "(JJ)V", (void*) FontFamily_Builder_addFont },
- { "nBuild", "(JLjava/lang/String;I)J", (void*) FontFamily_Builder_build },
+ { "nBuild", "(JLjava/lang/String;IZ)J", (void*) FontFamily_Builder_build },
{ "nGetReleaseNativeFamily", "()J", (void*) FontFamily_Builder_GetReleaseFunc },
};
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 80572f3..b1a9866 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,16 +32,15 @@
android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
}
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn,
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jboolean devOptIn,
jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
ScopedUtfChars pathChars(env, path);
ScopedUtfChars appNameChars(env, appName);
- ScopedUtfChars appPrefChars(env, appPref);
int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd);
android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
- appPrefChars.c_str(), devOptIn, rulesFd_native, rulesOffset, rulesLength);
+ devOptIn, rulesFd_native, rulesOffset, rulesLength);
}
void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
@@ -68,7 +67,7 @@
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
- { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
+ { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
{ "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
{ "setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayersGLES_native) },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f512ce4..b8139a7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -556,18 +556,18 @@
proxy->setWideGamut(true);
}
proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
- proxy->initialize(surface);
+ proxy->setSurface(surface);
// Shadows can't be used via this interface, so just set the light source
// to all 0s.
- proxy->setup(0, 0, 0);
- proxy->setLightCenter((Vector3){0, 0, 0});
+ proxy->setLightAlpha(0, 0);
+ proxy->setLightGeometry((Vector3){0, 0, 0}, 0);
return (jlong) proxy;
}
static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
- proxy->updateSurface(surface);
+ proxy->setSurface(surface);
}
static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7a5b604..702741e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -686,31 +686,20 @@
env->ReleaseStringUTFChars(jname, name);
}
-static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject jsurface) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
- proxy->initialize(surface);
-}
-
-static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jsurface) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
sp<Surface> surface;
if (jsurface) {
surface = android_view_Surface_getSurface(env, jsurface);
}
- proxy->updateSurface(surface);
+ proxy->setSurface(surface);
}
-static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject jsurface) {
+static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- sp<Surface> surface;
- if (jsurface) {
- surface = android_view_Surface_getSurface(env, jsurface);
- }
- return proxy->pauseSurface(surface);
+ return proxy->pause();
}
static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
@@ -719,16 +708,16 @@
proxy->setStopped(stopped);
}
-static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
- jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
+static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
+ jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
+ proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
}
-static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
+static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
+ proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
}
static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -990,13 +979,12 @@
{
ContextFactory factory;
RenderProxy proxy{true, renderNode, &factory};
- proxy.loadSystemProperties();
proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
- proxy.initialize(surface);
+ proxy.setSurface(surface);
// Shadows can't be used via this interface, so just set the light source
// to all 0s.
- proxy.setup(0, 0, 0);
- proxy.setLightCenter((Vector3){0, 0, 0});
+ proxy.setLightAlpha(0, 0);
+ proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
UiFrameInfoBuilder(proxy.frameInfo())
.setVsync(vsync, vsync)
@@ -1058,10 +1046,9 @@
}
static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject jsurface) {
+ jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
- proxy->allocateBuffers(surface);
+ proxy->allocateBuffers();
}
static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
@@ -1118,7 +1105,7 @@
// JNI Glue
// ----------------------------------------------------------------------------
-const char* const kClassPathName = "android/view/ThreadedRenderer";
+const char* const kClassPathName = "android/graphics/HardwareRenderer";
static const JNINativeMethod gMethods[] = {
{ "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
@@ -1129,12 +1116,11 @@
{ "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
{ "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
{ "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
- { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
- { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
- { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
+ { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface },
+ { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause },
{ "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
- { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
- { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
+ { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha },
+ { "nSetLightGeometry", "(JFFFF)V", (void*) android_view_ThreadedRenderer_setLightGeometry },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
{ "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
{ "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
@@ -1161,9 +1147,9 @@
{ "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
{ "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
- { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
+ { "nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCallback},
- { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
+ { "nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
{ "nAddFrameMetricsObserver",
"(JLandroid/view/FrameMetricsObserver;)J",
@@ -1182,7 +1168,7 @@
{ "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
{ "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
{ "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
- { "nAllocateBuffers", "(JLandroid/view/Surface;)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
+ { "nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
{ "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
};
@@ -1215,12 +1201,12 @@
env, metricsClass, "mTimingData", "[J");
jclass frameCallbackClass = FindClassOrDie(env,
- "android/view/ThreadedRenderer$FrameDrawingCallback");
+ "android/graphics/HardwareRenderer$FrameDrawingCallback");
gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
"onFrameDraw", "(J)V");
jclass frameCompleteClass = FindClassOrDie(env,
- "android/view/ThreadedRenderer$FrameCompleteCallback");
+ "android/graphics/HardwareRenderer$FrameCompleteCallback");
gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
"onFrameComplete", "(J)V");
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4e20e29..8e9a0bf 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -20,7 +20,9 @@
#include <sys/mount.h>
#include <linux/fs.h>
+#include <functional>
#include <list>
+#include <optional>
#include <sstream>
#include <string>
@@ -70,6 +72,8 @@
namespace {
+using namespace std::placeholders;
+
using android::String8;
using android::base::StringAppendF;
using android::base::StringPrintf;
@@ -651,12 +655,12 @@
static FileDescriptorTable* gOpenFdTable = NULL;
static bool FillFileDescriptorVector(JNIEnv* env,
- jintArray java_fds,
+ jintArray managed_fds,
std::vector<int>* fds,
std::string* error_msg) {
CHECK(fds != nullptr);
- if (java_fds != nullptr) {
- ScopedIntArrayRO ar(env, java_fds);
+ if (managed_fds != nullptr) {
+ ScopedIntArrayRO ar(env, managed_fds);
if (ar.get() == nullptr) {
*error_msg = "Bad fd array";
return false;
@@ -669,246 +673,46 @@
return true;
}
-// Utility routine to specialize a zygote child process.
-static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
- jint runtime_flags, jobjectArray javaRlimits,
- jlong permittedCapabilities, jlong effectiveCapabilities,
- jint mount_external, jstring java_se_info, jstring java_se_name,
- bool is_system_server, bool is_child_zygote, jstring instructionSet,
- jstring dataDir, jstring packageName, jobjectArray packagesForUid,
- jobjectArray visibleVolIds) {
- std::string error_msg;
-
- auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
- __attribute__ ((noreturn)) {
- const char* se_name_c_str = nullptr;
- std::unique_ptr<ScopedUtfChars> se_name;
- if (java_se_name != nullptr) {
- se_name.reset(new ScopedUtfChars(env, java_se_name));
- se_name_c_str = se_name->c_str();
- }
- if (se_name_c_str == nullptr && is_system_server) {
- se_name_c_str = "system_server";
- }
- const std::string& error_msg = (se_name_c_str == nullptr)
- ? msg
- : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
- env->FatalError(error_msg.c_str());
- __builtin_unreachable();
- };
-
- // Keep capabilities across UID change, unless we're staying root.
- if (uid != 0) {
- if (!EnableKeepCapabilities(&error_msg)) {
- fail_fn(error_msg);
+[[noreturn]]
+static void ZygoteFailure(JNIEnv* env,
+ const char* process_name,
+ jstring managed_process_name,
+ const std::string& msg) {
+ std::unique_ptr<ScopedUtfChars> scoped_managed_process_name_ptr = nullptr;
+ if (managed_process_name != nullptr) {
+ scoped_managed_process_name_ptr.reset(new ScopedUtfChars(env, managed_process_name));
+ if (scoped_managed_process_name_ptr->c_str() != nullptr) {
+ process_name = scoped_managed_process_name_ptr->c_str();
}
}
- if (!SetInheritable(permittedCapabilities, &error_msg)) {
- fail_fn(error_msg);
- }
- if (!DropCapabilitiesBoundingSet(&error_msg)) {
- fail_fn(error_msg);
- }
+ const std::string& error_msg =
+ (process_name == nullptr) ? msg : StringPrintf("(%s) %s", process_name, msg.c_str());
- bool use_native_bridge = !is_system_server && (instructionSet != NULL)
- && android::NativeBridgeAvailable();
- if (use_native_bridge) {
- ScopedUtfChars isa_string(env, instructionSet);
- use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
- }
- if (use_native_bridge && dataDir == NULL) {
- // dataDir should never be null if we need to use a native bridge.
- // In general, dataDir will never be null for normal applications. It can only happen in
- // special cases (for isolated processes which are not associated with any app). These are
- // launched by the framework and should not be emulated anyway.
- use_native_bridge = false;
- ALOGW("Native bridge will not be used because dataDir == NULL.");
- }
+ env->FatalError(error_msg.c_str());
+ __builtin_unreachable();
+}
- std::string package_name_str("");
- if (packageName != nullptr) {
- ScopedUtfChars package(env, packageName);
- package_name_str = package.c_str();
- } else if (is_system_server) {
- package_name_str = "android";
- }
- std::vector<std::string> packages_for_uid;
- if (packagesForUid != nullptr) {
- jsize count = env->GetArrayLength(packagesForUid);
- for (jsize i = 0; i < count; ++i) {
- jstring package_for_uid = (jstring) env->GetObjectArrayElement(packagesForUid, i);
- ScopedUtfChars package(env, package_for_uid);
- packages_for_uid.push_back(package.c_str());
- }
- }
- std::vector<std::string> visible_vol_ids;
- if (visibleVolIds != nullptr) {
- jsize count = env->GetArrayLength(visibleVolIds);
- for (jsize i = 0; i < count; ++i) {
- jstring visible_vol_id = (jstring) env->GetObjectArrayElement(visibleVolIds, i);
- ScopedUtfChars vol(env, visible_vol_id);
- visible_vol_ids.push_back(vol.c_str());
- }
- }
- bool success = MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg,
- package_name_str, packages_for_uid, visible_vol_ids);
- if (!success) {
- ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
- if (errno == ENOTCONN || errno == EROFS) {
- // When device is actively encrypting, we get ENOTCONN here
- // since FUSE was mounted before the framework restarted.
- // When encrypted device is booting, we get EROFS since
- // FUSE hasn't been created yet by init.
- // In either case, continue without external storage.
+static std::optional<std::string> ExtractJString(JNIEnv* env,
+ const char* process_name,
+ jstring managed_process_name,
+ jstring managed_string) {
+ if (managed_string == nullptr) {
+ return std::optional<std::string>();
+ } else {
+ ScopedUtfChars scoped_string_chars(env, managed_string);
+
+ if (scoped_string_chars.c_str() != nullptr) {
+ return std::optional<std::string>(scoped_string_chars.c_str());
} else {
- fail_fn(error_msg);
+ ZygoteFailure(env, process_name, managed_process_name, "Failed to extract JString.");
}
}
-
- // If this zygote isn't root, it won't be able to create a process group,
- // since the directory is owned by root.
- if (!is_system_server && getuid() == 0) {
- int rc = createProcessGroup(uid, getpid());
- if (rc != 0) {
- if (rc == -EROFS) {
- ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
- } else {
- ALOGE("createProcessGroup(%d, %d) failed: %s", uid, 0/*pid*/, strerror(-rc));
- }
- }
- }
-
- if (!SetGids(env, javaGids, &error_msg)) {
- fail_fn(error_msg);
- }
-
- if (!SetRLimits(env, javaRlimits, &error_msg)) {
- fail_fn(error_msg);
- }
-
- if (use_native_bridge) {
- ScopedUtfChars isa_string(env, instructionSet);
- ScopedUtfChars data_dir(env, dataDir);
- android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
- }
-
- int rc = setresgid(gid, gid, gid);
- if (rc == -1) {
- fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
- }
-
- // Must be called when the new process still has CAP_SYS_ADMIN, in this case, before changing
- // uid from 0, which clears capabilities. The other alternative is to call
- // prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see
- // b/71859146). As the result, privileged syscalls used below still need to be accessible in
- // app process.
- SetUpSeccompFilter(uid);
-
- rc = setresuid(uid, uid, uid);
- if (rc == -1) {
- fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
- }
-
- // The "dumpable" flag of a process, which controls core dump generation, is
- // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective
- // user or group ID changes. See proc(5) for possible values. In most cases,
- // the value is 0, so core dumps are disabled for zygote children. However,
- // when running in a Chrome OS container, the value is already set to 2,
- // which allows the external crash reporter to collect all core dumps. Since
- // only system crashes are interested, core dump is disabled for app
- // processes. This also ensures compliance with CTS.
- int dumpable = prctl(PR_GET_DUMPABLE);
- if (dumpable == -1) {
- ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
- }
- if (dumpable == 2 && uid >= AID_APP) {
- if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
- ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
- RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed");
- }
- }
-
- if (NeedsNoRandomizeWorkaround()) {
- // Work around ARM kernel ASLR lossage (http://b/5817320).
- int old_personality = personality(0xffffffff);
- int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
- if (new_personality == -1) {
- ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
- }
- }
-
- if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
- &error_msg)) {
- fail_fn(error_msg);
- }
-
- if (!SetSchedulerPolicy(&error_msg)) {
- fail_fn(error_msg);
- }
-
- const char* se_info_c_str = NULL;
- ScopedUtfChars* se_info = NULL;
- if (java_se_info != NULL) {
- se_info = new ScopedUtfChars(env, java_se_info);
- se_info_c_str = se_info->c_str();
- if (se_info_c_str == NULL) {
- fail_fn("se_info_c_str == NULL");
- }
- }
- const char* se_name_c_str = NULL;
- ScopedUtfChars* se_name = NULL;
- if (java_se_name != NULL) {
- se_name = new ScopedUtfChars(env, java_se_name);
- se_name_c_str = se_name->c_str();
- if (se_name_c_str == NULL) {
- fail_fn("se_name_c_str == NULL");
- }
- }
- rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
- if (rc == -1) {
- fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
- is_system_server, se_info_c_str, se_name_c_str));
- }
-
- // Make it easier to debug audit logs by setting the main thread's name to the
- // nice name rather than "app_process".
- if (se_name_c_str == NULL && is_system_server) {
- se_name_c_str = "system_server";
- }
- if (se_name_c_str != NULL) {
- SetThreadName(se_name_c_str);
- }
-
- delete se_info;
- delete se_name;
-
- // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
- UnsetChldSignalHandler();
-
- if (is_system_server) {
- env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
- if (env->ExceptionCheck()) {
- fail_fn("Error calling post fork system server hooks.");
- }
- // TODO(oth): Remove hardcoded label here (b/117874058).
- static const char* kSystemServerLabel = "u:r:system_server:s0";
- if (selinux_android_setcon(kSystemServerLabel) != 0) {
- fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
- }
- }
-
- env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
- is_system_server, is_child_zygote, instructionSet);
- if (env->ExceptionCheck()) {
- fail_fn("Error calling post fork hooks.");
- }
}
-// Utility routine to fork zygote and specialize the child process.
-static pid_t ForkCommon(JNIEnv* env, jstring java_se_name, bool is_system_server,
- jintArray fdsToClose, jintArray fdsToIgnore) {
+// Utility routine to fork a zygote.
+static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
+ jintArray managed_fds_to_close, jintArray managed_fds_to_ignore) {
SetSignalHandlers();
// Block SIGCHLD prior to fork.
@@ -916,23 +720,9 @@
sigemptyset(&sigchld);
sigaddset(&sigchld, SIGCHLD);
- auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
- __attribute__ ((noreturn)) {
- const char* se_name_c_str = nullptr;
- std::unique_ptr<ScopedUtfChars> se_name;
- if (java_se_name != nullptr) {
- se_name.reset(new ScopedUtfChars(env, java_se_name));
- se_name_c_str = se_name->c_str();
- }
- if (se_name_c_str == nullptr && is_system_server) {
- se_name_c_str = "system_server";
- }
- const std::string& error_msg = (se_name_c_str == nullptr)
- ? msg
- : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
- env->FatalError(error_msg.c_str());
- __builtin_unreachable();
- };
+ // Curry a failure function.
+ auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
+ nullptr, _1);
// Temporarily block SIGCHLD during forks. The SIGCHLD handler might
// log, which would result in the logging FDs we close being reopened.
@@ -948,18 +738,18 @@
__android_log_close();
stats_log_close();
+ // If this is the first fork for this zygote, create the open FD table. If
+ // it isn't, we just need to check whether the list of open files has changed
+ // (and it shouldn't in the normal case).
std::string error_msg;
-
- // If this is the first fork for this zygote, create the open FD table.
- // If it isn't, we just need to check whether the list of open files has
- // changed (and it shouldn't in the normal case).
std::vector<int> fds_to_ignore;
- if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
+ if (!FillFileDescriptorVector(env, managed_fds_to_ignore, &fds_to_ignore, &error_msg)) {
fail_fn(error_msg);
}
- if (gOpenFdTable == NULL) {
+
+ if (gOpenFdTable == nullptr) {
gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
- if (gOpenFdTable == NULL) {
+ if (gOpenFdTable == nullptr) {
fail_fn(error_msg);
}
} else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
@@ -975,7 +765,7 @@
PreApplicationInit();
// Clean up any descriptors which must be closed immediately
- if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
+ if (!DetachDescriptors(env, managed_fds_to_close, &error_msg)) {
fail_fn(error_msg);
}
@@ -993,9 +783,236 @@
if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
}
+
return pid;
}
+// Utility routine to specialize a zygote child process.
+static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
+ jint runtime_flags, jobjectArray rlimits,
+ jlong permitted_capabilities, jlong effective_capabilities,
+ jint mount_external, jstring managed_se_info,
+ jstring managed_nice_name, bool is_system_server,
+ bool is_child_zygote, jstring managed_instruction_set,
+ jstring managed_app_data_dir, jstring managed_package_name,
+ jobjectArray managed_pacakges_for_uid,
+ jobjectArray managed_visible_vol_ids) {
+ auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
+ managed_nice_name, _1);
+ auto extract_fn = std::bind(ExtractJString, env, is_system_server ? "system_server" : "zygote",
+ managed_nice_name, _1);
+
+ auto se_info = extract_fn(managed_se_info);
+ auto nice_name = extract_fn(managed_nice_name);
+ auto instruction_set = extract_fn(managed_instruction_set);
+ auto app_data_dir = extract_fn(managed_app_data_dir);
+ auto package_name = extract_fn(managed_package_name);
+
+ std::string error_msg;
+
+ // Keep capabilities across UID change, unless we're staying root.
+ if (uid != 0) {
+ if (!EnableKeepCapabilities(&error_msg)) {
+ fail_fn(error_msg);
+ }
+ }
+
+ if (!SetInheritable(permitted_capabilities, &error_msg)) {
+ fail_fn(error_msg);
+ }
+
+ if (!DropCapabilitiesBoundingSet(&error_msg)) {
+ fail_fn(error_msg);
+ }
+
+ bool use_native_bridge = !is_system_server &&
+ instruction_set.has_value() &&
+ android::NativeBridgeAvailable() &&
+ android::NeedsNativeBridge(instruction_set.value().c_str());
+
+ if (use_native_bridge && !app_data_dir.has_value()) {
+ // The app_data_dir variable should never be empty if we need to use a
+ // native bridge. In general, app_data_dir will never be empty for normal
+ // applications. It can only happen in special cases (for isolated
+ // processes which are not associated with any app). These are launched by
+ // the framework and should not be emulated anyway.
+ use_native_bridge = false;
+ ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
+ }
+
+ if (!package_name.has_value()) {
+ if (is_system_server) {
+ package_name.emplace("android");
+ } else {
+ package_name.emplace("");
+ }
+ }
+
+ std::vector<std::string> packages_for_uid;
+ if (managed_pacakges_for_uid != nullptr) {
+ jsize count = env->GetArrayLength(managed_pacakges_for_uid);
+ for (jsize package_index = 0; package_index < count; ++package_index) {
+ jstring managed_package_for_uid =
+ (jstring) env->GetObjectArrayElement(managed_pacakges_for_uid, package_index);
+
+ auto package_for_uid = extract_fn(managed_package_for_uid);
+ if (LIKELY(package_for_uid.has_value())) {
+ packages_for_uid.emplace_back(std::move(package_for_uid.value()));
+ } else {
+ fail_fn("Null string found in managed packages_for_uid.");
+ }
+ }
+ }
+
+ std::vector<std::string> visible_vol_ids;
+ if (managed_visible_vol_ids != nullptr) {
+ jsize count = env->GetArrayLength(managed_visible_vol_ids);
+ for (jsize vol_id_index = 0; vol_id_index < count; ++vol_id_index) {
+ jstring managed_visible_vol_id =
+ (jstring) env->GetObjectArrayElement(managed_visible_vol_ids, vol_id_index);
+
+ auto visible_vol_id = extract_fn(managed_visible_vol_id);
+ if (LIKELY(visible_vol_id.has_value())) {
+ visible_vol_ids.emplace_back(std::move(visible_vol_id.value()));
+ } else {
+ fail_fn("Null string found in managed visible_vol_ids.");
+ }
+ }
+ }
+
+ if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg,
+ package_name.value(), packages_for_uid, visible_vol_ids)) {
+ ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
+ if (errno == ENOTCONN || errno == EROFS) {
+ // When device is actively encrypting, we get ENOTCONN here
+ // since FUSE was mounted before the framework restarted.
+ // When encrypted device is booting, we get EROFS since
+ // FUSE hasn't been created yet by init.
+ // In either case, continue without external storage.
+ } else {
+ fail_fn(error_msg);
+ }
+ }
+
+ // If this zygote isn't root, it won't be able to create a process group,
+ // since the directory is owned by root.
+ if (!is_system_server && getuid() == 0) {
+ int rc = createProcessGroup(uid, getpid());
+ if (rc == -EROFS) {
+ ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
+ } else if (rc != 0) {
+ ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
+ }
+ }
+
+ if (!SetGids(env, gids, &error_msg)) {
+ fail_fn(error_msg);
+ }
+
+ if (!SetRLimits(env, rlimits, &error_msg)) {
+ fail_fn(error_msg);
+ }
+
+ if (use_native_bridge) {
+ // Due to the logic behind use_native_bridge we know that both app_data_dir
+ // and instruction_set contain values.
+ android::PreInitializeNativeBridge(app_data_dir.value().c_str(),
+ instruction_set.value().c_str());
+ }
+
+ if (setresgid(gid, gid, gid) == -1) {
+ fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
+ }
+
+ // Must be called when the new process still has CAP_SYS_ADMIN, in this case,
+ // before changing uid from 0, which clears capabilities. The other
+ // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that
+ // breaks SELinux domain transition (see b/71859146). As the result,
+ // privileged syscalls used below still need to be accessible in app process.
+ SetUpSeccompFilter(uid);
+
+ if (setresuid(uid, uid, uid) == -1) {
+ fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
+ }
+
+ // The "dumpable" flag of a process, which controls core dump generation, is
+ // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective
+ // user or group ID changes. See proc(5) for possible values. In most cases,
+ // the value is 0, so core dumps are disabled for zygote children. However,
+ // when running in a Chrome OS container, the value is already set to 2,
+ // which allows the external crash reporter to collect all core dumps. Since
+ // only system crashes are interested, core dump is disabled for app
+ // processes. This also ensures compliance with CTS.
+ int dumpable = prctl(PR_GET_DUMPABLE);
+ if (dumpable == -1) {
+ ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
+ RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
+ }
+
+ if (dumpable == 2 && uid >= AID_APP) {
+ if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
+ ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
+ RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed");
+ }
+ }
+
+ if (NeedsNoRandomizeWorkaround()) {
+ // Work around ARM kernel ASLR lossage (http://b/5817320).
+ int old_personality = personality(0xffffffff);
+ int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+ if (new_personality == -1) {
+ ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
+ }
+ }
+
+ if (!SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
+ &error_msg)) {
+ fail_fn(error_msg);
+ }
+
+ if (!SetSchedulerPolicy(&error_msg)) {
+ fail_fn(error_msg);
+ }
+
+ const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
+ const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
+
+ if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
+ fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed",
+ uid, is_system_server, se_info_ptr, nice_name_ptr));
+ }
+
+ // Make it easier to debug audit logs by setting the main thread's name to the
+ // nice name rather than "app_process".
+ if (nice_name.has_value()) {
+ SetThreadName(nice_name.value().c_str());
+ } else if (is_system_server) {
+ SetThreadName("system_server");
+ }
+
+ // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
+ UnsetChldSignalHandler();
+
+ if (is_system_server) {
+ env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
+ if (env->ExceptionCheck()) {
+ fail_fn("Error calling post fork system server hooks.");
+ }
+ // TODO(oth): Remove hardcoded label here (b/117874058).
+ static const char* kSystemServerLabel = "u:r:system_server:s0";
+ if (selinux_android_setcon(kSystemServerLabel) != 0) {
+ fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
+ }
+ }
+
+ env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
+ is_system_server, is_child_zygote, managed_instruction_set);
+
+ if (env->ExceptionCheck()) {
+ fail_fn("Error calling post fork hooks.");
+ }
+}
+
static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) {
__user_cap_header_struct capheader;
memset(&capheader, 0, sizeof(capheader));
@@ -1008,16 +1025,82 @@
RuntimeAbort(env, __LINE__, "capget failed");
}
- return capdata[0].effective |
- (static_cast<uint64_t>(capdata[1].effective) << 32);
+ return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32);
+}
+
+static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids,
+ bool is_child_zygote) {
+ jlong capabilities = 0;
+
+ /*
+ * Grant the following capabilities to the Bluetooth user:
+ * - CAP_WAKE_ALARM
+ * - CAP_NET_RAW
+ * - CAP_NET_BIND_SERVICE (for DHCP client functionality)
+ * - CAP_SYS_NICE (for setting RT priority for audio-related threads)
+ */
+
+ if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
+ capabilities |= (1LL << CAP_WAKE_ALARM);
+ capabilities |= (1LL << CAP_NET_RAW);
+ capabilities |= (1LL << CAP_NET_BIND_SERVICE);
+ capabilities |= (1LL << CAP_SYS_NICE);
+ }
+
+ /*
+ * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
+ */
+
+ bool gid_wakelock_found = false;
+ if (gid == AID_WAKELOCK) {
+ gid_wakelock_found = true;
+ } else if (gids != nullptr) {
+ jsize gids_num = env->GetArrayLength(gids);
+ ScopedIntArrayRO native_gid_proxy(env, gids);
+
+ if (native_gid_proxy.get() == nullptr) {
+ RuntimeAbort(env, __LINE__, "Bad gids array");
+ }
+
+ for (int gid_index = gids_num; --gids_num >= 0;) {
+ if (native_gid_proxy[gid_index] == AID_WAKELOCK) {
+ gid_wakelock_found = true;
+ break;
+ }
+ }
+ }
+
+ if (gid_wakelock_found) {
+ capabilities |= (1LL << CAP_BLOCK_SUSPEND);
+ }
+
+ /*
+ * Grant child Zygote processes the following capabilities:
+ * - CAP_SETUID (change UID of child processes)
+ * - CAP_SETGID (change GID of child processes)
+ * - CAP_SETPCAP (change capabilities of child processes)
+ */
+
+ if (is_child_zygote) {
+ capabilities |= (1LL << CAP_SETUID);
+ capabilities |= (1LL << CAP_SETGID);
+ capabilities |= (1LL << CAP_SETPCAP);
+ }
+
+ /*
+ * Containers run without some capabilities, so drop any caps that are not
+ * available.
+ */
+
+ return capabilities & GetEffectiveCapabilityMask(env);
}
} // anonymous namespace
namespace android {
static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
- // security_getenforce is not allowed on app process. Initialize and cache the value before
- // zygote forks.
+ // security_getenforce is not allowed on app process. Initialize and cache
+ // the value before zygote forks.
g_is_security_enforced = security_getenforce();
}
@@ -1028,78 +1111,35 @@
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
- jint mount_external, jstring se_info, jstring se_name,
- jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
- jstring instructionSet, jstring appDataDir, jstring packageName,
- jobjectArray packagesForUid, jobjectArray visibleVolIds) {
- jlong capabilities = 0;
+ jint mount_external, jstring se_info, jstring nice_name,
+ jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote,
+ jstring instruction_set, jstring app_data_dir, jstring package_name,
+ jobjectArray packages_for_uid, jobjectArray visible_vol_ids) {
+ jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
- // Grant CAP_WAKE_ALARM to the Bluetooth process.
- // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client.
- // Grant CAP_SYS_NICE to allow Bluetooth to set RT priority for
- // audio-related threads.
- // TODO: consider making such functionality an RPC to netd.
- if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
- capabilities |= (1LL << CAP_WAKE_ALARM);
- capabilities |= (1LL << CAP_NET_RAW);
- capabilities |= (1LL << CAP_NET_BIND_SERVICE);
- capabilities |= (1LL << CAP_SYS_NICE);
- }
-
- // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
- bool gid_wakelock_found = false;
- if (gid == AID_WAKELOCK) {
- gid_wakelock_found = true;
- } else if (gids != NULL) {
- jsize gids_num = env->GetArrayLength(gids);
- ScopedIntArrayRO ar(env, gids);
- if (ar.get() == NULL) {
- RuntimeAbort(env, __LINE__, "Bad gids array");
- }
- for (int i = 0; i < gids_num; i++) {
- if (ar[i] == AID_WAKELOCK) {
- gid_wakelock_found = true;
- break;
- }
- }
- }
- if (gid_wakelock_found) {
- capabilities |= (1LL << CAP_BLOCK_SUSPEND);
- }
-
- // If forking a child zygote process, that zygote will need to be able to change
- // the UID and GID of processes it forks, as well as drop those capabilities.
- if (is_child_zygote) {
- capabilities |= (1LL << CAP_SETUID);
- capabilities |= (1LL << CAP_SETGID);
- capabilities |= (1LL << CAP_SETPCAP);
- }
-
- // Containers run without some capabilities, so drop any caps that are not
- // available.
- capabilities &= GetEffectiveCapabilityMask(env);
-
- pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore);
+ pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
- mount_external, se_info, se_name, false,
- is_child_zygote == JNI_TRUE, instructionSet, appDataDir, packageName,
- packagesForUid, visibleVolIds);
+ mount_external, se_info, nice_name, false,
+ is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
+ package_name, packages_for_uid, visible_vol_ids);
}
return pid;
}
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
- jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
- jlong effectiveCapabilities) {
- pid_t pid = ForkCommon(env, NULL, true, NULL, NULL);
+ jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
+ jlong effective_capabilities) {
+ pid_t pid = ForkCommon(env, true,
+ /* managed_fds_to_close= */ nullptr,
+ /* managed_fds_to_ignore= */ nullptr);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
- permittedCapabilities, effectiveCapabilities,
- MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true,
- false, NULL, NULL, nullptr, nullptr, nullptr);
+ permitted_capabilities, effective_capabilities,
+ MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
+ false, nullptr, nullptr, nullptr, nullptr, nullptr);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -1133,7 +1173,7 @@
ScopedUtfChars path_native(env, path);
const char* path_cstr = path_native.c_str();
if (!path_cstr) {
- RuntimeAbort(env, __LINE__, "path_cstr == NULL");
+ RuntimeAbort(env, __LINE__, "path_cstr == nullptr");
}
FileDescriptorWhitelist::Get()->Allow(path_cstr);
}
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 2ace1ac..480b1ea 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -11,6 +11,9 @@
yaochen@google.com
yro@google.com
+# Settings UI
+per-file settings_enums.proto=zhfan@google.com
+
# Frameworks
ogunwale@google.com
jjaggi@google.com
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 5433393..3a908dc 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -64,5 +64,8 @@
// OPEN: Biometric Enrollment (android.settings.BIOMETRIC_ENROLL action intent)
BIOMETRIC_ENROLL_ACTIVITY = 1586;
+
+ // OPEN: Settings > Privacy
+ TOP_LEVEL_PRIVACY = 1587;
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 3072977..e0e7b6f 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -270,6 +270,7 @@
optional SettingProto enable_freeform_windows_support = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto force_rtl = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto emulate_display_cutout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto force_desktop_mode_on_external_displays = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Development development = 39;
@@ -725,8 +726,10 @@
optional SettingProto set_install_location = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto shortcut_manager_constants = 104;
optional SettingProto show_first_crash_dialog = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_hidden_launcher_icon_apps_enabled = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto show_restart_in_crash_dialog = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto show_mute_in_crash_dialog = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_new_app_installed_notification_enabled = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
message SmartSelection {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -966,5 +969,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 141;
+ // Next tag = 143;
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 3ead633..f8acc33 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -72,8 +72,10 @@
// List of the accessibility services to which the user has granted
// permission to put the device into touch exploration mode.
optional SettingProto touch_exploration_granted_accessibility_services = 31;
- optional SettingProto minimum_ui_timeout_enabled = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto minimum_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ reserved 32; // minimum_ui_timeout_enabled
+ reserved 33; // minimum_ui_timeout_ms
+ optional SettingProto non_interactive_ui_timeout_ms = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto interactive_ui_timeout_ms = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
diff --git a/core/res/TEST_MAPPING b/core/res/TEST_MAPPING
new file mode 100644
index 0000000..1d22d782
--- /dev/null
+++ b/core/res/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsPermission2TestCases",
+ "options": [
+ {
+ "include-filter": "android.permission2.cts.PermissionPolicyTest#testPlatformPermissionPolicyUnaltered"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_notifications_alerted.xml b/core/res/res/drawable/ic_notifications_alerted.xml
new file mode 100644
index 0000000..4bfac37
--- /dev/null
+++ b/core/res/res/drawable/ic_notifications_alerted.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2018 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 8b1f28b..4ee9731 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -126,6 +126,19 @@
android:visibility="gone"
android:contentDescription="@string/notification_work_profile_content_description"
/>
+ <ImageView
+ android:id="@+id/alerted_icon"
+ android:layout_width="@dimen/notification_alerted_size"
+ android:layout_height="@dimen/notification_alerted_size"
+ android:layout_gravity="center"
+ android:layout_marginStart="4dp"
+ android:paddingTop="1dp"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ android:contentDescription="@string/notification_alerted_content_description"
+ android:src="@drawable/ic_notifications_alerted"
+ android:tint="@color/notification_secondary_text_color_light"
+ />
<LinearLayout
android:id="@+id/app_ops"
android:layout_height="match_parent"
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 36efd0a..c26bebe 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -33,7 +33,7 @@
<item>LPP_PROFILE=3</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index a11dd95..96338b58 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -30,7 +30,7 @@
<item>LPP_PROFILE=3</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 8d29ec1..79f4bb6 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -34,7 +34,7 @@
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 650aa62..10b007e 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -32,7 +32,7 @@
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 4bb68dc..657d1e7 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -28,7 +28,7 @@
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index 735a8c8..ba8c75a 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -34,7 +34,7 @@
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a25c998..68ec342 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3587,11 +3587,22 @@
{@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
<attr name="notificationTimeout" format="integer" />
- <!-- The minimum timeout in milliseconds that UI controls need to remain on the screen.
+ <!-- A recommended timeout in milliseconds used in
+ {@link android.view.accessibility.AccessibilityManager#getRecommendedTimeoutMillis(int, int)
+ android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int)}
+ to return a suitable value for UIs that do not include interactive controls.
This setting can be changed at runtime by calling
{@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
- <attr name="minimumUiTimeout" format="integer" />
+ <attr name="nonInteractiveUiTimeout" format="integer" />
+ <!-- A recommended timeout in milliseconds used in
+ {@link android.view.accessibility.AccessibilityManager#getRecommendedTimeoutMillis(int, int)
+ android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int)}
+ to return a suitable value for interactive controls.
+ This setting can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+ android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <attr name="interactiveUiTimeout" format="integer" />
<!-- Additional flags as specified in
{@link android.accessibilityservice.AccessibilityServiceInfo}.
This setting can be changed at runtime by calling
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a8c78a6..bca72f4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2793,7 +2793,7 @@
<item>LPP_PROFILE=0</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>GPS_LOCK=0</item>
+ <item>GPS_LOCK=3</item>
</string-array>
<!-- Sprint need a 70 ms delay for 3way call -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index ba483fb..b65c0fd 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -426,6 +426,9 @@
<!-- Size of the profile badge for notifications -->
<dimen name="notification_badge_size">12dp</dimen>
+ <!-- Size of the alerted icon for notifications -->
+ <dimen name="notification_alerted_size">18dp</dimen>
+
<!-- Keyguard dimensions -->
<!-- TEMP -->
<dimen name="kg_security_panel_height">600dp</dimen>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index a0c02ed..c1ca33e 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -44,9 +44,10 @@
<dimen name="car_headline3_size">24sp</dimen>
<dimen name="car_headline4_size">20sp</dimen>
<dimen name="car_body1_size">32sp</dimen>
- <dimen name="car_body2_size">26sp</dimen>
- <dimen name="car_body3_size">16sp</dimen>
- <dimen name="car_body4_size">14sp</dimen>
+ <dimen name="car_body2_size">28sp</dimen>
+ <dimen name="car_body3_size">26sp</dimen>
+ <dimen name="car_body4_size">24sp</dimen>
+ <!-- car_body5_size is deprecated -->
<dimen name="car_body5_size">18sp</dimen>
<dimen name="car_label1_size">26sp</dimen>
<dimen name="car_label2_size">64sp</dimen>
@@ -85,6 +86,7 @@
<dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
<dimen name="car_button_radius">@dimen/car_radius_1</dimen>
<dimen name="car_pill_button_size">56dp</dimen>
+ <dimen name="car_touch_target_size">76dp</dimen>
<!-- Seekbar -->
<dimen name="car_seekbar_height">6dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e1c5df3..15f29ce 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2912,12 +2912,13 @@
<public name="supportsAmbientMode" />
<!-- @hide For use by platform and tools only. Developers should not specify this value. -->
<public name="usesNonSdkApi" />
- <public name="minimumUiTimeout" />
+ <public name="nonInteractiveUiTimeout" />
<public name="isLightTheme" />
<public name="isSplitRequired" />
<public name="textLocale" />
<public name="settingsSliceUri" />
<public name="shell" />
+ <public name="interactiveUiTimeout" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8b7cafb..200c35d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -248,6 +248,10 @@
<item>@string/wfcSpnFormat_spn_wifi</item>
<item>@string/wfcSpnFormat_wifi_calling_bar_spn</item>
<item>@string/wfcSpnFormat_spn_vowifi</item>
+ <item>@string/wfcSpnFormat_wifi_calling</item>
+ <item>@string/wfcSpnFormat_wifi</item>
+ <item>@string/wfcSpnFormat_wifi_calling_wo_hyphen</item>
+ <item>@string/wfcSpnFormat_vowifi</item>
</string-array>
<!-- Spn during Wi-Fi Calling: "<operator>" -->
@@ -264,6 +268,14 @@
<string name="wfcSpnFormat_wifi_calling_bar_spn">WiFi Calling | <xliff:g id="spn" example="Operator">%s</xliff:g></string>
<!-- Spn during Wi-Fi Calling: "<operator> VoWifi" -->
<string name="wfcSpnFormat_spn_vowifi"><xliff:g id="spn" example="Operator">%s</xliff:g> VoWifi</string>
+ <!-- Spn during Wi-Fi Calling: "Wi-Fi Calling" -->
+ <string name="wfcSpnFormat_wifi_calling">Wi-Fi Calling</string>
+ <!-- Spn during Wi-Fi Calling: "Wi-Fi" -->
+ <string name="wfcSpnFormat_wifi">Wi-Fi</string>
+ <!-- Spn during Wi-Fi Calling: "WiFi Calling" (without hyphen) -->
+ <string name="wfcSpnFormat_wifi_calling_wo_hyphen">WiFi Calling</string>
+ <!-- Spn during Wi-Fi Calling: "VoWifi" -->
+ <string name="wfcSpnFormat_vowifi">VoWifi</string>
<!-- WFC, summary for Disabled -->
<string name="wifi_calling_off_summary">Off</string>
@@ -4820,6 +4832,9 @@
<!-- Content description of the work profile icon in the notification. -->
<string name="notification_work_profile_content_description">Work profile</string>
+ <!-- Content description of the alerting icon in the notification. [CHAR_LIMIT=NONE] -->
+ <string name="notification_alerted_content_description">Alerted</string>
+
<!-- Content description of the expand button icon in the notification when collaped.-->
<string name="expand_button_content_description_collapsed">Expand</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 670a4a2..5418e03 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -215,6 +215,7 @@
<java-symbol type="id" name="pin_error_message" />
<java-symbol type="id" name="timePickerLayout" />
<java-symbol type="id" name="profile_badge" />
+ <java-symbol type="id" name="alerted_icon" />
<java-symbol type="id" name="transitionPosition" />
<java-symbol type="id" name="selection_start_handle" />
<java-symbol type="id" name="selection_end_handle" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 4980210..63dd59a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -197,6 +197,7 @@
Settings.Global.DESK_DOCK_SOUND,
Settings.Global.DESK_UNDOCK_SOUND,
Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
+ Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
Settings.Global.DEVELOPMENT_FORCE_RTL,
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
@@ -370,6 +371,7 @@
Settings.Global.PRIVATE_DNS_DEFAULT_MODE,
Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED,
Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED,
+ Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED,
Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS,
Settings.Global.RADIO_BLUETOOTH,
Settings.Global.RADIO_CELL,
@@ -393,7 +395,9 @@
Settings.Global.SETTINGS_USE_PSD_API,
Settings.Global.SHORTCUT_MANAGER_CONSTANTS,
Settings.Global.SHOW_FIRST_CRASH_DIALOG,
+ Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED,
Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
+ Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED,
Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
Settings.Global.SHOW_TEMPERATURE_WARNING,
@@ -494,6 +498,7 @@
Settings.Global.WIFI_NUM_OPEN_NETWORKS_KEPT,
Settings.Global.WIFI_ON,
Settings.Global.WIFI_P2P_DEVICE_NAME,
+ Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET,
Settings.Global.WIFI_REENABLE_DELAY_MS,
Settings.Global.WIFI_RTT_BACKGROUND_EXEC_GAP_MS,
Settings.Global.WIFI_SAVED_STATE,
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index c8e46fc..ca6d6cfe 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertThat;
import android.content.Context;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
@@ -57,9 +58,8 @@
mViewRootImpl.getAttachInfo().getStableInsets().set(-10, -20, -30 , -40);
final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
- assertThat(insets.getSystemWindowInsets(), equalTo(new Rect()));
- assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
- insets.getStableInsetRight(), insets.getStableInsetBottom()), equalTo(new Rect()));
+ assertThat(insets.getSystemWindowInsets(), equalTo(Insets.NONE));
+ assertThat(insets.getStableInsets(), equalTo(Insets.NONE));
}
@Test
@@ -68,10 +68,8 @@
mViewRootImpl.getAttachInfo().getStableInsets().set(10, -20, 30 , -40);
final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
- assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(0, 20, 0, 40)));
- assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
- insets.getStableInsetRight(), insets.getStableInsetBottom()),
- equalTo(new Rect(10, 0, 30, 0)));
+ assertThat(insets.getSystemWindowInsets(), equalTo(Insets.of(0, 20, 0, 40)));
+ assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 0, 30, 0)));
}
@Test
@@ -80,10 +78,8 @@
mViewRootImpl.getAttachInfo().getStableInsets().set(10, 20, 30 , 40);
final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
- assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(10, 20, 30, 40)));
- assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
- insets.getStableInsetRight(), insets.getStableInsetBottom()),
- equalTo(new Rect(10, 20, 30, 40)));
+ assertThat(insets.getSystemWindowInsets(), equalTo(Insets.of(10, 20, 30, 40)));
+ assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 20, 30, 40)));
}
private static class ViewRootImplAccessor {
diff --git a/core/java/android/view/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
similarity index 70%
rename from core/java/android/view/FrameInfo.java
rename to graphics/java/android/graphics/FrameInfo.java
index 6c5e048..42a5cc4 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.view;
+package android.graphics;
import android.annotation.LongDef;
@@ -33,14 +33,14 @@
* long layout & measure took it's displayListRecordStart - performTraversalsStart.
*
* These constants must be kept in sync with FrameInfo.h in libhwui and are
- * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * used for indexing into AttachInfo's frameInfo long[], which is intended
* to be quick to pass down to native via JNI, hence a pre-packed format
*
* @hide
*/
-final class FrameInfo {
+public final class FrameInfo {
- long[] mFrameInfo = new long[9];
+ public long[] frameInfo = new long[9];
// Various flags set to provide extra metadata about the current frame
private static final int FLAGS = 0;
@@ -48,8 +48,11 @@
// Is this the first-draw following a window layout?
public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
+ // A renderer associated with just a Surface, not with a ViewRootImpl instance.
+ public static final long FLAG_SURFACE_CANVAS = 1 << 2;
+
@LongDef(flag = true, value = {
- FLAG_WINDOW_LAYOUT_CHANGED })
+ FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS })
@Retention(RetentionPolicy.SOURCE)
public @interface FrameInfoFlags {}
@@ -78,41 +81,48 @@
// When View:draw() started
private static final int DRAW_START = 8;
+ /** checkstyle */
public void setVsync(long intendedVsync, long usedVsync) {
- mFrameInfo[INTENDED_VSYNC] = intendedVsync;
- mFrameInfo[VSYNC] = usedVsync;
- mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
- mFrameInfo[NEWEST_INPUT_EVENT] = 0;
- mFrameInfo[FLAGS] = 0;
+ frameInfo[INTENDED_VSYNC] = intendedVsync;
+ frameInfo[VSYNC] = usedVsync;
+ frameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+ frameInfo[NEWEST_INPUT_EVENT] = 0;
+ frameInfo[FLAGS] = 0;
}
+ /** checkstyle */
public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
- if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
- mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+ if (inputEventOldestTime < frameInfo[OLDEST_INPUT_EVENT]) {
+ frameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
}
- if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
- mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+ if (inputEventTime > frameInfo[NEWEST_INPUT_EVENT]) {
+ frameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
}
}
+ /** checkstyle */
public void markInputHandlingStart() {
- mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+ frameInfo[HANDLE_INPUT_START] = System.nanoTime();
}
+ /** checkstyle */
public void markAnimationsStart() {
- mFrameInfo[ANIMATION_START] = System.nanoTime();
+ frameInfo[ANIMATION_START] = System.nanoTime();
}
+ /** checkstyle */
public void markPerformTraversalsStart() {
- mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+ frameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
}
+ /** checkstyle */
public void markDrawStart() {
- mFrameInfo[DRAW_START] = System.nanoTime();
+ frameInfo[DRAW_START] = System.nanoTime();
}
+ /** checkstyle */
public void addFlags(@FrameInfoFlags long flags) {
- mFrameInfo[FLAGS] |= flags;
+ frameInfo[FLAGS] |= flags;
}
}
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
new file mode 100644
index 0000000..e402055
--- /dev/null
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.FrameMetricsObserver;
+import android.view.IGraphicsStats;
+import android.view.IGraphicsStatsCallback;
+import android.view.NativeVectorDrawableAnimator;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.TextureLayer;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import sun.misc.Cleaner;
+
+/**
+ * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
+ * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
+ * HardwareRenderer instances as desired.</p>
+ *
+ * <h3>Threading</h3>
+ * <p>HardwareRenderer is not thread safe. An instance of a HardwareRenderer must only be
+ * created & used from a single thread. It does not matter what thread is used, however
+ * it must have a {@link android.os.Looper}. Multiple instances do not have to share the same
+ * thread, although they can.</p>
+ *
+ * <h3>Resources & lifecycle</h3>
+ * <p>All HardwareRenderer instances share a common render thread. The render thread contains
+ * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
+ * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
+ * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
+ * is to have a HardwareRenderer instance for every active {@link Surface}. For example
+ * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
+ * of which may be drawing at the same time.</p>
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @hide
+ */
+public class HardwareRenderer {
+ private static final String LOG_TAG = "HardwareRenderer";
+
+ // Keep in sync with DrawFrameTask.h SYNC_* flags
+ /**
+ * Nothing interesting to report. Sync & draw kicked off
+ */
+ public static final int SYNC_OK = 0;
+
+ /**
+ * The renderer is requesting a redraw. This can occur if there's an animation that's running
+ * in the RenderNode tree and the hardware renderer is unable to self-animate.
+ *
+ * If this is returned from syncAndDrawFrame the expectation is that syncAndDrawFrame
+ * will be called again on the next vsync signal.
+ */
+ public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
+
+ /**
+ * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
+ * This can happen if {@link Surface#destroy()} was called. The user should no longer
+ * attempt to call syncAndDrawFrame until a new surface has been provided by calling
+ * setSurface.
+ *
+ * Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
+ */
+ public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
+
+ /**
+ * The hardware renderer has been set to a "stopped" state. If this is returned then the
+ * rendering content has been synced, however a frame was not produced.
+ */
+ public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
+
+ /**
+ * The content was synced but the renderer has declined to produce a frame in this vsync
+ * interval. This can happen if a frame was already drawn in this vsync or if the renderer
+ * is outrunning the frame consumer. The renderer will internally re-schedule itself
+ * to render a frame in the next vsync signal, so the caller does not need to do anything
+ * in response to this signal.
+ */
+ public static final int SYNC_FRAME_DROPPED = 1 << 3;
+
+ @IntDef(value = {
+ SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
+ SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SyncAndDrawResult {
+ }
+
+ /** @hide */
+ public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+ /** @hide */
+ public static final int FLAG_DUMP_RESET = 1 << 1;
+ /** @hide */
+ public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
+ FLAG_DUMP_FRAMESTATS,
+ FLAG_DUMP_RESET
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DumpFlags {
+ }
+
+ /**
+ * Name of the file that holds the shaders cache.
+ */
+ private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
+ private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
+
+ private final long mNativeProxy;
+ /** @hide */
+ protected RenderNode mRootNode;
+ private boolean mOpaque = true;
+ private boolean mForceDark = false;
+ private FrameInfo mScratchInfo;
+
+ /**
+ * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
+ * to opaque with no light source configured.
+ */
+ public HardwareRenderer() {
+ mRootNode = RenderNode.adopt(nCreateRootRenderNode());
+ mRootNode.setClipToBounds(false);
+ mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
+ if (mNativeProxy == 0) {
+ throw new OutOfMemoryError("Unable to create hardware renderer");
+ }
+ Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
+ ProcessInitializer.sInstance.init(mNativeProxy);
+ }
+
+ /**
+ * Destroys the rendering context of this HardwareRenderer. This destroys the resources
+ * associated with this renderer and releases the currently set {@link Surface}.
+ *
+ * The renderer may be restored from this state by setting a new {@link Surface}, setting
+ * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
+ * rendering with {@link #syncAndDrawFrame(long)}.
+ *
+ * It is suggested to call this in response to callbacks such as
+ * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
+ *
+ * Note that if there are any outstanding frame commit callbacks they may end up never being
+ * invoked if the frame was deferred to a later vsync.
+ */
+ public void destroy() {
+ nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+ }
+
+ /**
+ * Sets a name for this renderer. This is used to identify this renderer instance
+ * when reporting debug information such as the per-window frame time metrics
+ * reported by 'adb shell dumpsys gfxinfo [package] framestats'
+ *
+ * @param name The debug name to use for this HardwareRenderer instance
+ */
+ public void setName(String name) {
+ nSetName(mNativeProxy, name);
+ }
+
+ /**
+ * Sets the center of the light source. The light source point controls the directionality
+ * and shape of shadows rendered by RenderNode Z & elevation.
+ *
+ * The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
+ * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
+ *
+ * The light source should be setup both as part of initial configuration, and whenever
+ * the window moves to ensure the light source stays anchored in display space instead
+ * of in window space.
+ *
+ * This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
+ * before shadows will work.
+ *
+ * @param lightX The X position of the light source
+ * @param lightY The Y position of the light source
+ * @param lightZ The Z position of the light source. Must be >= 0.
+ * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
+ * larger radius will have softer shadows.
+ */
+ public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
+ float lightRadius) {
+ validateFinite(lightX, "lightX");
+ validateFinite(lightY, "lightY");
+ validatePositive(lightZ, "lightZ");
+ validatePositive(lightRadius, "lightRadius");
+ nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
+ }
+
+ /**
+ * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
+ * has max alpha, and ramps down from the values provided to zero.
+ *
+ * These values are typically provided by the current theme, see
+ * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
+ *
+ * This must be set at least once along with
+ * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
+ *
+ * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
+ * is 0.039f.
+ * @param spotShadowAlpha The alpha for the spot shadow. If unsure, a reasonable default is
+ * 0.19f.
+ */
+ public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
+ @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
+ validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
+ validateAlpha(spotShadowAlpha, "spotShadowAlpha");
+ nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
+ }
+
+ /**
+ * Sets the content root to render. It is not necessary to call this whenever the content
+ * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
+ * contained within the content node, will be applied whenever {@link #syncAndDrawFrame(long)}
+ * is called.
+ *
+ * @param content The content to set as the root RenderNode. If null the content root is removed
+ * and the renderer will draw nothing.
+ */
+ public void setContentRoot(@Nullable RenderNode content) {
+ RecordingCanvas canvas = mRootNode.startRecording();
+ if (content != null) {
+ canvas.drawRenderNode(content);
+ }
+ mRootNode.endRecording();
+ }
+
+ /**
+ * <p>The surface to render into. The surface is assumed to be associated with the display and
+ * as such is still driven by vsync signals such as those from
+ * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
+ * the display's (typically 60hz).</p>
+ *
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @param surface The surface to render into. If null then rendering will be stopped. If
+ * non-null then {@link Surface#isValid()} must be true.
+ */
+ public void setSurface(@Nullable Surface surface) {
+ if (surface != null && !surface.isValid()) {
+ throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
+ }
+ nSetSurface(mNativeProxy, surface);
+ }
+
+ /**
+ * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+ *
+ * @hide
+ */
+ @SyncAndDrawResult
+ public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
+ return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
+ }
+
+ /**
+ * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+ *
+ * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+ * {@link android.view.Choreographer.FrameCallback}. Must be set and be valid
+ * as the renderer uses this time internally to drive animations.
+ * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+ */
+ @SyncAndDrawResult
+ public int syncAndDrawFrame(long vsyncTime) {
+ if (mScratchInfo == null) {
+ mScratchInfo = new FrameInfo();
+ }
+ mScratchInfo.setVsync(vsyncTime, vsyncTime);
+ mScratchInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
+ return syncAndDrawFrame(mScratchInfo);
+ }
+
+ /**
+ * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+ * frameCommitCallback callback will be invoked when the current rendering content has been
+ * rendered into a frame and submitted to the swap chain.
+ *
+ * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+ * {@link android.view.Choreographer.FrameCallback}. Must be set and
+ * be valid as the renderer uses this time internally to drive
+ * animations.
+ * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
+ * Will be invoked on the current {@link android.os.Looper} thread.
+ * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+ */
+ @SyncAndDrawResult
+ public int syncAndDrawFrame(long vsyncTime,
+ @Nullable Runnable frameCommitCallback) {
+ if (frameCommitCallback != null) {
+ setFrameCompleteCallback(frameNr -> frameCommitCallback.run());
+ }
+ return syncAndDrawFrame(vsyncTime);
+ }
+
+ /**
+ * Suspends any current rendering into the surface but do not do any destruction. This
+ * is useful to temporarily suspend using the active Surface in order to do any Surface
+ * mutations necessary.
+ *
+ * Any subsequent draws will override the pause, resuming normal operation.
+ *
+ * @return true if there was an outstanding render request, false otherwise. If this is true
+ * the caller should ensure that {@link #syncAndDrawFrame(long)} is called at the soonest
+ * possible time to resume normal operation.
+ *
+ * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
+ * Surface before getting a new one. However things like SurfaceView will ensure that
+ * the old surface remains un-destroyed until after a new frame has been produced with
+ * the new surface.
+ * @hide
+ */
+ public boolean pause() {
+ return nPause(mNativeProxy);
+ }
+
+ /**
+ * Hard stops rendering into the surface. If the renderer is stopped it will
+ * block any attempt to render. Calls to {@link #syncAndDrawFrame(long)} will still
+ * sync over the latest rendering content, however they will not render and instead
+ * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
+ *
+ * If false is passed then rendering will resume as normal. Any pending rendering requests
+ * will produce a new frame at the next vsync signal.
+ *
+ * This is useful in combination with lifecycle events such as {@link Activity#onStop()}
+ * and {@link Activity#onStart()}.
+ *
+ * @param stopped true to stop all rendering, false to resume
+ */
+ public void setStopped(boolean stopped) {
+ nSetStopped(mNativeProxy, stopped);
+ }
+
+ /**
+ * Destroys all hardware rendering resources associated with the current rendering content.
+ * This includes releasing a reference to the current content root RenderNode. It will
+ * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
+ * rendering after calling this.
+ *
+ * It is recommended, but not necessary, to use this in combination with lifecycle events
+ * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
+ * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
+ * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
+ *
+ * See also {@link #setStopped(boolean)}
+ */
+ public void destroyHardwareResources() {
+ nDestroyHardwareResources(mNativeProxy);
+ }
+
+ /**
+ * Whether or not the force-dark feature should be used for this renderer.
+ */
+ public boolean setForceDark(boolean enable) {
+ if (mForceDark != enable) {
+ mForceDark = enable;
+ nSetForceDark(mNativeProxy, enable);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allocate buffers ahead of time to avoid allocation delays during rendering.
+ *
+ * Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
+ * memory usage of Surfaces that render rarely or never hit triple buffering. However
+ * for UI it can result in a slight bit of jank on first launch. This hint will
+ * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
+ * necessary for typical rendering.
+ *
+ * Must be called after a {@link Surface} has been set.
+ */
+ public void allocateBuffers() {
+ nAllocateBuffers(mNativeProxy);
+ }
+
+ /**
+ * Notifies the hardware renderer that a call to {@link #syncAndDrawFrame(long)} will
+ * be coming soon. This is used to help schedule when RenderThread-driven animations will
+ * happen as the renderer wants to avoid producing more than one frame per vsync signal.
+ */
+ public void notifyFramePending() {
+ nNotifyFramePending(mNativeProxy);
+ }
+
+ /**
+ * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
+ *
+ * If the renderer is set to opaque it is the app's responsibility to ensure that the
+ * content renders to every pixel of the Surface, otherwise corruption may result. Note that
+ * this includes ensuring that the first draw of any given pixel does not attempt to blend
+ * against the destination. If this is false then the hardware renderer will clear to
+ * transparent at the start of every frame.
+ *
+ * @param opaque true if the content rendered is opaque, false if the renderer should clear
+ * to transparent before rendering
+ */
+ public void setOpaque(boolean opaque) {
+ if (mOpaque != opaque) {
+ mOpaque = opaque;
+ nSetOpaque(mNativeProxy, mOpaque);
+ }
+ }
+
+ /**
+ * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
+ *
+ * @return true if the renderer is opaque, false otherwise
+ */
+ public boolean isOpaque() {
+ return mOpaque;
+ }
+
+ /** @hide */
+ public void setFrameCompleteCallback(FrameCompleteCallback callback) {
+ nSetFrameCompleteCallback(mNativeProxy, callback);
+ }
+
+ /**
+ * TODO: Public API this?
+ *
+ * @hide
+ */
+ public void addFrameMetricsObserver(FrameMetricsObserver observer) {
+ long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+ observer.mNative = new VirtualRefBasePtr(nativeObserver);
+ }
+
+ /**
+ * TODO: Public API this?
+ *
+ * @hide
+ */
+ public void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+ nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+ observer.mNative = null;
+ }
+
+ /**
+ * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
+ * will be wide gamut depends on the hardware support for such rendering.
+ *
+ * @param wideGamut true if this renderer should render in wide gamut, false if it should
+ * render in sRGB
+ * TODO: Figure out color...
+ * @hide
+ */
+ public void setWideGamut(boolean wideGamut) {
+ nSetWideGamut(mNativeProxy, wideGamut);
+ }
+
+ /**
+ * Blocks until all previously queued work has completed.
+ *
+ * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
+ * better
+ *
+ * @hide
+ */
+ public void fence() {
+ nFence(mNativeProxy);
+ }
+
+ /** @hide */
+ public void registerAnimatingRenderNode(RenderNode animator) {
+ nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
+ }
+
+ /** @hide */
+ public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
+ nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
+ animator.getAnimatorNativePtr());
+ }
+
+ /**
+ * Prevents any further drawing until {@link #syncAndDrawFrame(long)} is called.
+ * This is a signal that the contents of the RenderNode tree are no longer safe to play back.
+ * In practice this usually means that there are Functor pointers in the
+ * display list that are no longer valid.
+ *
+ * TODO: Can we get webview off of this?
+ *
+ * @hide
+ */
+ public void stopDrawing() {
+ nStopDrawing(mNativeProxy);
+ }
+
+ /**
+ * Creates a new hardware layer. A hardware layer built by calling this
+ * method will be treated as a texture layer, instead of as a render target.
+ *
+ * @return A hardware layer
+ * @hide
+ */
+ public TextureLayer createTextureLayer() {
+ long layer = nCreateTextureLayer(mNativeProxy);
+ return TextureLayer.adoptTextureLayer(this, layer);
+ }
+
+ /**
+ * Detaches the layer's surface texture from the GL context and releases
+ * the texture id
+ *
+ * @hide
+ */
+ public void detachSurfaceTexture(long hardwareLayer) {
+ nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
+ }
+
+
+ /** @hide */
+ public void buildLayer(RenderNode node) {
+ if (node.hasDisplayList()) {
+ nBuildLayer(mNativeProxy, node.mNativeRenderNode);
+ }
+ }
+
+ /** @hide */
+ public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
+ return nCopyLayerInto(mNativeProxy,
+ layer.getDeferredLayerUpdater(), bitmap);
+ }
+
+ /**
+ * Indicates that the specified hardware layer needs to be updated
+ * as soon as possible.
+ *
+ * @param layer The hardware layer that needs an update
+ * @hide
+ */
+ public void pushLayerUpdate(TextureLayer layer) {
+ nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+ }
+
+ /**
+ * Tells the HardwareRenderer that the layer is destroyed. The renderer
+ * should remove the layer from any update queues.
+ *
+ * @hide
+ */
+ public void onLayerDestroyed(TextureLayer layer) {
+ nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+ }
+
+ /** @hide */
+ public void setFrameCallback(FrameDrawingCallback callback) {
+ nSetFrameCallback(mNativeProxy, callback);
+ }
+
+ /**
+ * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+ * rendernode of the UI thread.
+ *
+ * @param node The node to add.
+ * @param placeFront If true, the render node will be placed in front of the content node,
+ * otherwise behind the content node.
+ * @hide
+ */
+ public void addRenderNode(RenderNode node, boolean placeFront) {
+ nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+ }
+
+ /**
+ * Only especially added render nodes can be removed.
+ *
+ * @param node The node which was added via addRenderNode which should get removed again.
+ * @hide
+ */
+ public void removeRenderNode(RenderNode node) {
+ nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+ }
+
+ /**
+ * Draws a particular render node. If the node is not the content node, only the additional
+ * nodes will get drawn and the content remains untouched.
+ *
+ * @param node The node to be drawn.
+ * @hide
+ */
+ public void drawRenderNode(RenderNode node) {
+ nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+ }
+
+ /**
+ * Loads system properties used by the renderer. This method is invoked
+ * whenever system properties are modified. Implementations can use this
+ * to trigger live updates of the renderer based on properties.
+ *
+ * @return True if a property has changed.
+ * @hide
+ */
+ public boolean loadSystemProperties() {
+ return nLoadSystemProperties(mNativeProxy);
+ }
+
+ /**
+ * @hide
+ */
+ public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
+ nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
+ }
+
+ /**
+ * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+ * will be prevented to overdraw this area. It will be synchronized with the draw call.
+ * This should be updated in the content view's draw call.
+ *
+ * @param left The left side of the protected bounds.
+ * @param top The top side of the protected bounds.
+ * @param right The right side of the protected bounds.
+ * @param bottom The bottom side of the protected bounds.
+ * @hide
+ */
+ public void setContentDrawBounds(int left, int top, int right, int bottom) {
+ nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
+ }
+
+ /**
+ * Interface used to receive callbacks when a frame is being drawn.
+ *
+ * @hide
+ */
+ public interface FrameDrawingCallback {
+ /**
+ * Invoked during a frame drawing.
+ *
+ * @param frame The id of the frame being drawn.
+ */
+ void onFrameDraw(long frame);
+ }
+
+ /**
+ * Interface used to be notified when a frame has finished rendering
+ *
+ * @hide
+ */
+ public interface FrameCompleteCallback {
+ /**
+ * Invoked after a frame draw
+ *
+ * @param frameNr The id of the frame that was drawn.
+ */
+ void onFrameComplete(long frameNr);
+ }
+
+ private static void validateAlpha(float alpha, String argumentName) {
+ if (!(alpha >= 0.0f && alpha <= 1.0f)) {
+ throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
+ + alpha + " is not in the range of 0.0f to 1.0f");
+ }
+ }
+
+ private static void validatePositive(float f, String argumentName) {
+ if (!(Float.isFinite(f) && f >= 0.0f)) {
+ throw new IllegalArgumentException(argumentName
+ + " must be a finite positive, given=" + f);
+ }
+ }
+
+ private static void validateFinite(float f, String argumentName) {
+ if (!Float.isFinite(f)) {
+ throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
+ }
+ }
+
+ /** @hide */
+ public static void invokeFunctor(long functor, boolean waitForCompletion) {
+ nInvokeFunctor(functor, waitForCompletion);
+ }
+
+ /**
+ * b/68769804: For low FPS experiments.
+ *
+ * @hide
+ */
+ public static void setFPSDivisor(int divisor) {
+ nHackySetRTAnimationsEnabled(divisor <= 1);
+ }
+
+ /**
+ * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
+ * called before any OpenGL context is created.
+ *
+ * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
+ * @hide
+ */
+ public static void setContextPriority(int priority) {
+ nSetContextPriority(priority);
+ }
+
+ /**
+ * Sets whether or not high contrast text rendering is enabled. The setting is global
+ * but only affects content rendered after the change is made.
+ *
+ * @hide
+ */
+ public static void setHighContrastText(boolean highContrastText) {
+ nSetHighContrastText(highContrastText);
+ }
+
+ /**
+ * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
+ *
+ * @hide
+ */
+ public static void setIsolatedProcess(boolean isIsolated) {
+ nSetIsolatedProcess(isIsolated);
+ }
+
+ /**
+ * If set extra graphics debugging abilities will be enabled such as dumping skp
+ *
+ * @hide
+ */
+ public static void setDebuggingEnabled(boolean enable) {
+ nSetDebuggingEnabled(enable);
+ }
+
+ /** @hide */
+ public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
+ if (srcRect == null) {
+ // Empty rect means entire surface
+ return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
+ } else {
+ return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
+ srcRect.right, srcRect.bottom, bitmap);
+ }
+ }
+
+ /**
+ * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
+ * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
+ * not the RenderNode from a View.
+ *
+ * @hide
+ **/
+ public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
+ return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
+ }
+
+ /**
+ * Invoke this method when the system is running out of memory. This
+ * method will attempt to recover as much memory as possible, based on
+ * the specified hint.
+ *
+ * @param level Hint about the amount of memory that should be trimmed,
+ * see {@link android.content.ComponentCallbacks}
+ * @hide
+ */
+ public static void trimMemory(int level) {
+ nTrimMemory(level);
+ }
+
+ /** @hide */
+ public static void overrideProperty(@NonNull String name, @NonNull String value) {
+ if (name == null || value == null) {
+ throw new IllegalArgumentException("name and value must be non-null");
+ }
+ nOverrideProperty(name, value);
+ }
+
+ /**
+ * Sets the directory to use as a persistent storage for threaded rendering
+ * resources.
+ *
+ * @param cacheDir A directory the current process can write to
+ * @hide
+ */
+ public static void setupDiskCache(File cacheDir) {
+ setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
+ new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
+ }
+
+ /** @hide */
+ public static void setPackageName(String packageName) {
+ ProcessInitializer.sInstance.setPackageName(packageName);
+ }
+
+ private static final class DestroyContextRunnable implements Runnable {
+ private final long mNativeInstance;
+
+ DestroyContextRunnable(long nativeInstance) {
+ mNativeInstance = nativeInstance;
+ }
+
+ @Override
+ public void run() {
+ nDeleteProxy(mNativeInstance);
+ }
+ }
+
+ private static class ProcessInitializer {
+ static ProcessInitializer sInstance = new ProcessInitializer();
+
+ private boolean mInitialized = false;
+
+ private String mPackageName;
+ private IGraphicsStats mGraphicsStatsService;
+ private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+ @Override
+ public void onRotateGraphicsStatsBuffer() throws RemoteException {
+ rotateBuffer();
+ }
+ };
+
+ private ProcessInitializer() {
+ }
+
+ synchronized void setPackageName(String name) {
+ if (mInitialized) return;
+ mPackageName = name;
+ }
+
+ synchronized void init(long renderProxy) {
+ if (mInitialized) return;
+ mInitialized = true;
+
+ initSched(renderProxy);
+ initGraphicsStats();
+ }
+
+ private void initSched(long renderProxy) {
+ try {
+ int tid = nGetRenderThreadTid(renderProxy);
+ ActivityManager.getService().setRenderThread(tid);
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
+ }
+ }
+
+ private void initGraphicsStats() {
+ if (mPackageName == null) return;
+
+ try {
+ IBinder binder = ServiceManager.getService("graphicsstats");
+ if (binder == null) return;
+ mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+ requestBuffer();
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+ }
+ }
+
+ private void rotateBuffer() {
+ nRotateProcessStatsBuffer();
+ requestBuffer();
+ }
+
+ private void requestBuffer() {
+ try {
+ ParcelFileDescriptor pfd = mGraphicsStatsService
+ .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
+ nSetProcessStatsBuffer(pfd.getFd());
+ pfd.close();
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public static native void disableVsync();
+
+ /** @hide */
+ protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
+
+ private static native void nRotateProcessStatsBuffer();
+
+ private static native void nSetProcessStatsBuffer(int fd);
+
+ private static native int nGetRenderThreadTid(long nativeProxy);
+
+ private static native long nCreateRootRenderNode();
+
+ private static native long nCreateProxy(boolean translucent, long rootRenderNode);
+
+ private static native void nDeleteProxy(long nativeProxy);
+
+ private static native boolean nLoadSystemProperties(long nativeProxy);
+
+ private static native void nSetName(long nativeProxy, String name);
+
+ private static native void nSetSurface(long nativeProxy, Surface window);
+
+ private static native boolean nPause(long nativeProxy);
+
+ private static native void nSetStopped(long nativeProxy, boolean stopped);
+
+ private static native void nSetLightGeometry(long nativeProxy,
+ float lightX, float lightY, float lightZ, float lightRadius);
+
+ private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
+ float spotShadowAlpha);
+
+ private static native void nSetOpaque(long nativeProxy, boolean opaque);
+
+ private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
+
+ private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
+
+ private static native void nDestroy(long nativeProxy, long rootRenderNode);
+
+ private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
+ long animatingNode);
+
+ private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
+
+ private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
+
+ private static native long nCreateTextureLayer(long nativeProxy);
+
+ private static native void nBuildLayer(long nativeProxy, long node);
+
+ private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
+
+ private static native void nPushLayerUpdate(long nativeProxy, long layer);
+
+ private static native void nCancelLayerUpdate(long nativeProxy, long layer);
+
+ private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
+
+ private static native void nDestroyHardwareResources(long nativeProxy);
+
+ private static native void nTrimMemory(int level);
+
+ private static native void nOverrideProperty(String name, String value);
+
+ private static native void nFence(long nativeProxy);
+
+ private static native void nStopDrawing(long nativeProxy);
+
+ private static native void nNotifyFramePending(long nativeProxy);
+
+ private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+ @DumpFlags int dumpFlags);
+
+ private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+ boolean placeFront);
+
+ private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+
+ private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+
+ private static native void nSetContentDrawBounds(long nativeProxy, int left,
+ int top, int right, int bottom);
+
+ private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
+
+ private static native void nSetFrameCompleteCallback(long nativeProxy,
+ FrameCompleteCallback callback);
+
+ private static native long nAddFrameMetricsObserver(long nativeProxy,
+ FrameMetricsObserver observer);
+
+ private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+
+ private static native int nCopySurfaceInto(Surface surface,
+ int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
+
+ private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
+
+ private static native void nSetHighContrastText(boolean enabled);
+
+ // For temporary experimentation b/66945974
+ private static native void nHackySetRTAnimationsEnabled(boolean enabled);
+
+ private static native void nSetDebuggingEnabled(boolean enabled);
+
+ private static native void nSetIsolatedProcess(boolean enabled);
+
+ private static native void nSetContextPriority(int priority);
+
+ private static native void nAllocateBuffers(long nativeProxy);
+
+ private static native void nSetForceDark(long nativeProxy, boolean enabled);
+}
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 9546a4a..c580c46 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,8 +16,6 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
-
public class ImageFormat {
/*
* these constants are chosen to be binary compatible with their previous
@@ -92,20 +90,21 @@
* </ul>
* </p>
*
- * <pre> y_size = stride * height </pre>
+ * <pre> size = stride * height </pre>
*
* <p>For example, the {@link android.media.Image} object can provide data
- * in this format from a {@link android.hardware.camera2.CameraDevice}
- * through a {@link android.media.ImageReader} object if this format is
- * supported by {@link android.hardware.camera2.CameraDevice}.</p>
+ * in this format from a {@link android.hardware.camera2.CameraDevice} (if
+ * supported) through a {@link android.media.ImageReader} object. The
+ * {@link android.media.Image#getPlanes() Image#getPlanes()} will return a
+ * single plane containing the pixel data. The pixel stride is always 1 in
+ * {@link android.media.Image.Plane#getPixelStride()}, and the
+ * {@link android.media.Image.Plane#getRowStride()} describes the vertical
+ * neighboring pixel distance (in bytes) between adjacent rows.</p>
*
* @see android.media.Image
* @see android.media.ImageReader
* @see android.hardware.camera2.CameraDevice
- *
- * @hide
*/
- @UnsupportedAppUsage
public static final int Y8 = 0x20203859;
/**
@@ -787,6 +786,7 @@
case DEPTH_POINT_CLOUD:
case PRIVATE:
case RAW_DEPTH:
+ case Y8:
return true;
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index a09b063..7e8bfb3 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -566,7 +566,7 @@
final CustomFallbackBuilder builder = new CustomFallbackBuilder(family)
.setStyle(new FontStyle(weight, slant));
if (mFallbackFamilyName != null) {
- builder.setFallback(mFallbackFamilyName);
+ builder.setSystemFallback(mFallbackFamilyName);
}
final Typeface typeface = builder.build();
if (key != null) {
@@ -584,6 +584,14 @@
/**
* A builder class for creating new Typeface instance.
*
+ * There are two font fallback mechanisms, custom font fallback and system font fallback.
+ * The custom font fallback is a simple ordered list. The text renderer tries to see if it can
+ * render a character with the first font and if that font does not support the character, try
+ * next one and so on. It will keep trying until end of the custom fallback chain. The maximum
+ * length of the custom fallback chain is 64.
+ * The system font fallback is a system pre-defined fallback chain. The system fallback is
+ * processed only when no matching font is found in the custom font fallback.
+ *
* <p>
* Examples,
* 1) Create Typeface from single ttf file.
@@ -617,15 +625,29 @@
* Font font = new Font.Builder("your_font_file.ttf").build();
* FontFamily family = new FontFamily.Builder(font).build();
* Typeface typeface = new Typeface.CustomFallbackBuilder(family)
- * .setFallback("serif") // Set serif font family as the fallback.
+ * .setSystemFallback("serif") // Set serif font family as the fallback.
+ * .build();
+ * </code>
+ * </pre>
+ * 4) Create Typeface from single ttf file and set another ttf file for the fallback.
+ * <pre>
+ * <code>
+ * Font font = new Font.Builder("English.ttf").build();
+ * FontFamily family = new FontFamily.Builder(font).build();
+ *
+ * Font fallbackFont = new Font.Builder("Arabic.ttf").build();
+ * FontFamily fallbackFamily = new FontFamily.Builder(fallbackFont).build();
+ * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
+ * .addCustomFallback(fallbackFamily) // Specify fallback family.
+ * .setSystemFallback("serif") // Set serif font family as the fallback.
* .build();
* </code>
* </pre>
* </p>
*/
public static class CustomFallbackBuilder {
- // TODO: Remove package modifier once android.graphics.FontFamily is deprecated.
- private final android.graphics.fonts.FontFamily mFamily;
+ private static final int MAX_CUSTOM_FALLBACK = 64;
+ private final ArrayList<FontFamily> mFamilies = new ArrayList<>();
private String mFallbackName = null;
private @Nullable FontStyle mStyle;
@@ -634,19 +656,20 @@
*
* @param family a family object
*/
- // TODO: Remove package modifier once android.graphics.FontFamily is deprecated.
- public CustomFallbackBuilder(@NonNull android.graphics.fonts.FontFamily family) {
+ public CustomFallbackBuilder(@NonNull FontFamily family) {
Preconditions.checkNotNull(family);
- mFamily = family;
+ mFamilies.add(family);
}
/**
* Sets a system fallback by name.
*
+ * For more information about fallback, see class description.
+ *
* @param familyName a family name to be used for fallback if the provided fonts can not be
* used
*/
- public CustomFallbackBuilder setFallback(@NonNull String familyName) {
+ public CustomFallbackBuilder setSystemFallback(@NonNull String familyName) {
Preconditions.checkNotNull(familyName);
mFallbackName = familyName;
return this;
@@ -667,19 +690,40 @@
}
/**
+ * Append a font family to the end of the custom font fallback.
+ *
+ * You can set up to 64 custom fallback families including the first font family you passed
+ * to the constructor.
+ * For more information about fallback, see class description.
+ *
+ * @param family a fallback family
+ * @throws IllegalArgumentException if you give more than 64 custom fallback families
+ */
+ public CustomFallbackBuilder addCustomFallback(@NonNull FontFamily family) {
+ Preconditions.checkNotNull(family);
+ Preconditions.checkArgument(mFamilies.size() < MAX_CUSTOM_FALLBACK,
+ "Custom fallback limit exceeded(" + MAX_CUSTOM_FALLBACK + ")");
+ mFamilies.add(family);
+ return this;
+ }
+
+ /**
* Create the Typeface based on the configured values.
*
* @return the Typeface object
*/
public Typeface build() {
+ final int userFallbackSize = mFamilies.size();
final FontFamily[] fallback = SystemFonts.getSystemFallback(mFallbackName);
- final FontFamily[] fullFamilies = new FontFamily[fallback.length + 1];
- final long[] ptrArray = new long[fallback.length + 1];
- ptrArray[0] = mFamily.getNativePtr();
- fullFamilies[0] = mFamily;
+ final FontFamily[] fullFamilies = new FontFamily[fallback.length + userFallbackSize];
+ final long[] ptrArray = new long[fallback.length + userFallbackSize];
+ for (int i = 0; i < userFallbackSize; ++i) {
+ ptrArray[i] = mFamilies.get(i).getNativePtr();
+ fullFamilies[i] = mFamilies.get(i);
+ }
for (int i = 0; i < fallback.length; ++i) {
- ptrArray[i + 1] = fallback[i].getNativePtr();
- fullFamilies[i + 1] = fallback[i];
+ ptrArray[i + userFallbackSize] = fallback[i].getNativePtr();
+ fullFamilies[i + userFallbackSize] = fallback[i];
}
final int weight = mStyle == null ? 400 : mStyle.getWeight();
final int italic =
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 18b41fa..3c44916 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -149,9 +149,13 @@
}
/**
- * Returns the alpha value of this drawable's color.
+ * Returns the alpha value of this drawable's color. Note this may not be the same alpha value
+ * provided in {@link Drawable#setAlpha(int)}. Instead this will return the alpha of the color
+ * combined with the alpha provided by setAlpha
*
* @return A value between 0 and 255.
+ *
+ * @see ColorDrawable#setAlpha(int)
*/
@Override
public int getAlpha() {
@@ -159,7 +163,9 @@
}
/**
- * Sets the color's alpha value.
+ * Applies the given alpha to the underlying color. Note if the color already has
+ * an alpha applied to it, this will apply this alpha to the existing value instead of
+ * overwriting it.
*
* @param alpha The alpha value to set, between 0 and 255.
*/
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e1f7263..caf610b 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -934,11 +934,13 @@
* do account for the value of {@link #setAlpha}, but the general behavior is dependent
* upon the implementation of the subclass.
*
+ * @deprecated This method is no longer used in graphics optimizations
+ *
* @return int The opacity class of the Drawable.
*
* @see android.graphics.PixelFormat
*/
- public abstract @PixelFormat.Opacity int getOpacity();
+ @Deprecated public abstract @PixelFormat.Opacity int getOpacity();
/**
* Return the appropriate opacity value for two source opacities. If
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 14d31d9..c0f1b16 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -108,16 +108,17 @@
* @return a font family
*/
public @NonNull FontFamily build() {
- return build("", FontConfig.Family.VARIANT_DEFAULT);
+ return build("", FontConfig.Family.VARIANT_DEFAULT, true /* isCustomFallback */);
}
/** @hide */
- public @NonNull FontFamily build(@NonNull String langTags, int variant) {
+ public @NonNull FontFamily build(@NonNull String langTags, int variant,
+ boolean isCustomFallback) {
final long builderPtr = nInitBuilder();
for (int i = 0; i < mFonts.size(); ++i) {
nAddFont(builderPtr, mFonts.get(i).getNativePtr());
}
- final long ptr = nBuild(builderPtr, langTags, variant);
+ final long ptr = nBuild(builderPtr, langTags, variant, isCustomFallback);
final FontFamily family = new FontFamily(mFonts, ptr);
sFamilyRegistory.registerNativeAllocation(family, ptr);
return family;
@@ -130,7 +131,8 @@
private static native long nInitBuilder();
@CriticalNative
private static native void nAddFont(long builderPtr, long fontPtr);
- private static native long nBuild(long builderPtr, String langTags, int variant);
+ private static native long nBuild(long builderPtr, String langTags, int variant,
+ boolean isCustomFallback);
@CriticalNative
private static native long nGetReleaseNativeFamily();
}
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 750adb2..4a9cf14 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -208,7 +208,7 @@
b.addFont(font);
}
}
- return b == null ? null : b.build(languageTags, variant);
+ return b == null ? null : b.build(languageTags, variant, false /* isCustomFallback */);
}
private static void appendNamedFamily(@NonNull FontConfig.Family xmlFamily,
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 0a4ac8c..c10e482 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -30,6 +30,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.security.KeyStoreException;
import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
@@ -40,14 +41,21 @@
import android.security.keystore.KeyExpiredException;
import android.security.keystore.KeyNotYetValidException;
import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
import android.security.keystore.StrongBoxUnavailableException;
import android.security.keystore.UserNotAuthenticatedException;
import android.util.Log;
-
+import com.android.org.bouncycastle.asn1.ASN1InputStream;
+import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import java.math.BigInteger;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.security.InvalidKeyException;
import java.util.List;
import java.util.Locale;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
/**
* @hide This should not be made public in its present form because it
@@ -69,6 +77,7 @@
public static final int VALUE_CORRUPTED = 8;
public static final int UNDEFINED_ACTION = 9;
public static final int WRONG_PASSWORD = 10;
+ public static final int KEY_ALREADY_EXISTS = 16;
public static final int CANNOT_ATTEST_IDS = -66;
public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
@@ -239,7 +248,12 @@
if (value == null) {
value = new byte[0];
}
- return mBinder.insert(key, value, uid, flags);
+ int error = mBinder.insert(key, value, uid, flags);
+ if (error == KEY_ALREADY_EXISTS) {
+ mBinder.del(key, uid);
+ error = mBinder.insert(key, value, uid, flags);
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
@@ -366,53 +380,6 @@
return isEmpty(UserHandle.myUserId());
}
- public boolean generate(String key, int uid, int keyType, int keySize, int flags,
- byte[][] args) {
- try {
- return mBinder.generate(key, uid, keyType, keySize, flags,
- new KeystoreArguments(args)) == NO_ERROR;
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot connect to keystore", e);
- return false;
- }
- }
-
- public boolean importKey(String keyName, byte[] key, int uid, int flags) {
- try {
- return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot connect to keystore", e);
- return false;
- }
- }
-
- public byte[] sign(String key, byte[] data) {
- try {
- return mBinder.sign(key, data);
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot connect to keystore", e);
- return null;
- } catch (android.os.ServiceSpecificException e) {
- Log.w(TAG, "KeyStore exception", e);
- return null;
- }
-
- }
-
- public boolean verify(String key, byte[] data, byte[] signature) {
- try {
- signature = signature != null ? signature : new byte[0];
- return mBinder.verify(key, data, signature) == NO_ERROR;
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot connect to keystore", e);
- return false;
- } catch (android.os.ServiceSpecificException e) {
- Log.w(TAG, "KeyStore exception", e);
- return false;
- }
-
- }
-
public String grant(String key, int uid) {
try {
String grantAlias = mBinder.grant(key, uid);
@@ -496,7 +463,12 @@
try {
entropy = entropy != null ? entropy : new byte[0];
args = args != null ? args : new KeymasterArguments();
- return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ if (error == KEY_ALREADY_EXISTS) {
+ mBinder.del(alias, uid);
+ error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
@@ -528,8 +500,14 @@
public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
int uid, int flags, KeyCharacteristics outCharacteristics) {
try {
- return mBinder.importKey(alias, args, format, keyData, uid, flags,
+ int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
outCharacteristics);
+ if (error == KEY_ALREADY_EXISTS) {
+ mBinder.del(alias, uid);
+ error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+ outCharacteristics);
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
@@ -541,13 +519,78 @@
return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
}
+ private String getAlgorithmFromPKCS8(byte[] keyData) {
+ try {
+ final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
+ final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+ final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
+ return new AlgorithmId(new ObjectIdentifier(algOid)).getName();
+ } catch (IOException e) {
+ Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data");
+ Log.e(TAG, Log.getStackTraceString(e));
+ return null;
+ }
+ }
+
+ private KeymasterArguments makeLegacyArguments(String algorithm) {
+ KeymasterArguments args = new KeymasterArguments();
+ args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
+ KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm));
+ args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN);
+ args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY);
+ args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
+ args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
+ args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
+ if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) {
+ args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
+ args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+ args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
+ args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS);
+ }
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
+ args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
+ args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+ args.addUnsignedLong(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+ KeymasterArguments.UINT64_MAX_VALUE);
+ args.addUnsignedLong(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+ KeymasterArguments.UINT64_MAX_VALUE);
+ args.addUnsignedLong(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, BigInteger.ZERO);
+ return args;
+ }
+
+ public boolean importKey(String alias, byte[] keyData, int uid, int flags) {
+ String algorithm = getAlgorithmFromPKCS8(keyData);
+ if (algorithm == null) return false;
+ KeymasterArguments args = makeLegacyArguments(algorithm);
+ KeyCharacteristics out = new KeyCharacteristics();
+ int result = importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid,
+ flags, out);
+ if (result != NO_ERROR) {
+ Log.e(TAG, Log.getStackTraceString(
+ new KeyStoreException(result, "legacy key import failed")));
+ return false;
+ }
+ return true;
+ }
+
public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
String wrappingKeyAlias,
byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
KeyCharacteristics outCharacteristics) {
try {
- return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+ if (error == KEY_ALREADY_EXISTS) {
+ mBinder.del(wrappedKeyAlias, -1);
+ error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
@@ -627,21 +670,6 @@
}
/**
- * Check if the operation referenced by {@code token} is currently authorized.
- *
- * @param token An operation token returned by a call to
- * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
- */
- public boolean isOperationAuthorized(IBinder token) {
- try {
- return mBinder.isOperationAuthorized(token);
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot connect to keystore", e);
- return false;
- }
- }
-
- /**
* Add an authentication record to the keystore authorization table.
*
* @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 288ba32..9e69488 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -162,6 +162,13 @@
LOG(INFO) << base::StringPrintf("PG (%02x): ",
package_group.dynamic_ref_table.mAssignedPackageId)
<< list;
+
+ for (size_t i = 0; i < 256; i++) {
+ if (package_group.dynamic_ref_table.mLookupTable[i] != 0) {
+ LOG(INFO) << base::StringPrintf(" e[0x%02x] -> 0x%02x", (uint8_t) i,
+ package_group.dynamic_ref_table.mLookupTable[i]);
+ }
+ }
}
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index dc4a0a7..388548b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6998,18 +6998,28 @@
}
status_t DynamicRefTable::lookupResourceValue(Res_value* value) const {
- uint8_t resolvedType;
+ uint8_t resolvedType = Res_value::TYPE_REFERENCE;
+ switch (value->dataType) {
+ case Res_value::TYPE_ATTRIBUTE:
+ resolvedType = Res_value::TYPE_ATTRIBUTE;
+ // fallthrough
+ case Res_value::TYPE_REFERENCE:
+ // Only resolve non-dynamic references and attributes if the package is loaded as a
+ // library or if a shared library is attempting to retrieve its own resource
+ if (!(mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) {
+ return NO_ERROR;
+ }
- if (value->dataType == Res_value::TYPE_ATTRIBUTE
- || value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
- resolvedType = Res_value::TYPE_ATTRIBUTE;
-
- } else if (value->dataType == Res_value::TYPE_REFERENCE
- || value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE) {
- resolvedType = Res_value::TYPE_REFERENCE;
-
- } else {
- return NO_ERROR;
+ // If the package is loaded as shared library, the resource reference
+ // also need to be fixed.
+ break;
+ case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
+ resolvedType = Res_value::TYPE_ATTRIBUTE;
+ // fallthrough
+ case Res_value::TYPE_DYNAMIC_REFERENCE:
+ break;
+ default:
+ return NO_ERROR;
}
status_t err = lookupResourceId(&value->data);
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index a028515..59abad45 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1709,13 +1709,13 @@
struct resource_name
{
- const char16_t* package;
+ const char16_t* package = NULL;
size_t packageLen;
- const char16_t* type;
- const char* type8;
+ const char16_t* type = NULL;
+ const char* type8 = NULL;
size_t typeLen;
- const char16_t* name;
- const char* name8;
+ const char16_t* name = NULL;
+ const char* name8 = NULL;
size_t nameLen;
};
diff --git a/libs/androidfw/tests/DynamicRefTable_test.cpp b/libs/androidfw/tests/DynamicRefTable_test.cpp
index df44e34..5acc46a 100644
--- a/libs/androidfw/tests/DynamicRefTable_test.cpp
+++ b/libs/androidfw/tests/DynamicRefTable_test.cpp
@@ -40,6 +40,26 @@
EXPECT_EQ(value2.data, 0x02010000);
};
+TEST(DynamicRefTableTest, LookupSharedLibSelfAttributes) {
+ // Shared library
+ DynamicRefTable shared_table(0x03, /* appAsLib */ false);
+ shared_table.addMapping(0x00, 0x03);
+ Res_value value;
+ value.dataType = Res_value::TYPE_ATTRIBUTE;
+ value.data = 0x00010000;
+ ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR);
+ EXPECT_EQ(value.data, 0x03010000);
+
+ // App loaded as a shared library
+ DynamicRefTable shared_app_table(0x04, /* appAsLib */ true);
+ shared_app_table.addMapping(0x7f, 0x04);
+ Res_value value2;
+ value2.dataType = Res_value::TYPE_ATTRIBUTE;
+ value2.data = 0x7f010000;
+ ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
+ EXPECT_EQ(value2.data, 0x04010000);
+};
+
TEST(DynamicRefTableTest, LookupDynamicReferences) {
// Shared library
DynamicRefTable shared_table(0x2, /* appAsLib */ false);
@@ -51,24 +71,46 @@
ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR);
EXPECT_EQ(value.data, 0x05010000);
- // App loaded as a shared library
- DynamicRefTable shared_app_table(0x2, /* appAsLib */ true);
- shared_app_table.addMapping(0x03, 0x05);
- shared_app_table.addMapping(0x7f, 0x2);
- Res_value value2;
- value2.dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
- value2.data = 0x03010000;
- ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
- EXPECT_EQ(value2.data, 0x05010000);
-
// Regular application
DynamicRefTable app_table(0x7f, /* appAsLib */ false);
app_table.addMapping(0x03, 0x05);
Res_value value3;
- value3.dataType = Res_value::TYPE_REFERENCE;
+ value3.dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
value3.data = 0x03010000;
ASSERT_EQ(app_table.lookupResourceValue(&value3), NO_ERROR);
EXPECT_EQ(value3.data, 0x05010000);
};
+TEST(DynamicRefTableTest, LookupDynamicAttributes) {
+// App loaded as a shared library
+ DynamicRefTable shared_app_table(0x2, /* appAsLib */ true);
+ shared_app_table.addMapping(0x03, 0x05);
+ shared_app_table.addMapping(0x7f, 0x2);
+ Res_value value2;
+ value2.dataType = Res_value::TYPE_DYNAMIC_ATTRIBUTE;
+ value2.data = 0x03010000;
+ ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
+ EXPECT_EQ(value2.data, 0x05010000);
+}
+
+TEST(DynamicRefTableTest, DoNotLookupNonDynamicReferences) {
+ // Regular application
+ DynamicRefTable app_table(0x7f, /* appAsLib */ false);
+ Res_value value;
+ value.dataType = Res_value::TYPE_REFERENCE;
+ value.data = 0x03010000;
+ ASSERT_EQ(app_table.lookupResourceValue(&value), NO_ERROR);
+ EXPECT_EQ(value.data, 0x03010000);
+};
+
+TEST(DynamicRefTableTest, DoNotLookupNonDynamicAttributes) {
+ // App with custom package id
+ DynamicRefTable custom_app_table(0x8f, /* appAsLib */ false);
+ Res_value value2;
+ value2.dataType = Res_value::TYPE_ATTRIBUTE;
+ value2.data = 0x03010000;
+ ASSERT_EQ(custom_app_table.lookupResourceValue(&value2), NO_ERROR);
+ EXPECT_EQ(value2.data, 0x03010000);
+};
+
} // namespace android
\ No newline at end of file
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 9eb4a13..26d2896 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -94,15 +94,15 @@
target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
ResTable::resource_name res_name;
- ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, false, &res_name));
+ ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, true, &res_name));
ASSERT_TRUE(res_name.package != NULL);
ASSERT_TRUE(res_name.type != NULL);
- ASSERT_TRUE(res_name.name != NULL);
+ ASSERT_TRUE(res_name.name8 != NULL);
EXPECT_EQ(String16("com.android.basic"), String16(res_name.package, res_name.packageLen));
EXPECT_EQ(String16("array"), String16(res_name.type, res_name.typeLen));
- EXPECT_EQ(String16("integerArray1"), String16(res_name.name, res_name.nameLen));
+ EXPECT_EQ(String8("integerArray1"), String8(res_name.name8, res_name.nameLen));
}
constexpr const uint32_t kNonOverlaidResourceId = 0x7fff0000u;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index f0053a4..17d2db71 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -176,7 +176,7 @@
"pipeline/skia/SkiaRecordingCanvas.cpp",
"pipeline/skia/SkiaVulkanPipeline.cpp",
"pipeline/skia/VectorDrawableAtlas.cpp",
- "pipeline/skia/VkFunctorDrawable.cpp",
+ "pipeline/skia/VkInteropFunctorDrawable.cpp",
"renderstate/RenderState.cpp",
"renderthread/CacheManager.cpp",
"renderthread/CanvasContext.cpp",
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 236a6b6..b04c774 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -66,6 +66,7 @@
FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
setDensity(1);
+ consumeProperties();
}
FrameInfoVisualizer::~FrameInfoVisualizer() {
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 2ca40b9..c58bcb3 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -139,7 +139,7 @@
uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
uint32_t flags = paint->getFlags();
- SkPaint::Hinting hinting = paint->getHinting();
+ unsigned hinting = static_cast<unsigned>(paint->getHinting());
// select only flags that might affect text layout
flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
SkPaint::kSubpixelText_Flag | SkPaint::kEmbeddedBitmapText_Flag |
@@ -150,7 +150,7 @@
void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
paint->setFlags(paintFlags & SkPaint::kAllFlags);
- paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
+ paint->setHinting(static_cast<SkFontHinting>(paintFlags >> 16));
}
void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font,
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 596b8af..45022e7 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -24,7 +24,7 @@
#include "RenderNode.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/GLFunctorDrawable.h"
-#include "pipeline/skia/VkFunctorDrawable.h"
+#include "pipeline/skia/VkInteropFunctorDrawable.h"
namespace android {
namespace uirenderer {
@@ -124,8 +124,8 @@
uirenderer::GlFunctorLifecycleListener* listener) {
FunctorDrawable* functorDrawable;
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- functorDrawable = mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, listener,
- asSkCanvas());
+ functorDrawable = mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(functor,
+ listener, asSkCanvas());
} else {
functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, listener,
asSkCanvas());
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 2ca110f..7fc41ac 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -22,7 +22,7 @@
#include "SkiaProfileRenderer.h"
#include "renderstate/RenderState.h"
#include "renderthread/Frame.h"
-#include "VkFunctorDrawable.h"
+#include "VkInteropFunctorDrawable.h"
#include <SkSurface.h>
#include <SkTypes.h>
@@ -144,7 +144,7 @@
}
void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
- VkFunctorDrawable::vkInvokeFunctor(functor);
+ VkInteropFunctorDrawable::vkInvokeFunctor(functor);
}
sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
similarity index 92%
rename from libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
rename to libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index 6486ddb..a594206 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "VkFunctorDrawable.h"
+#include "VkInteropFunctorDrawable.h"
#include <private/hwui/DrawGlInfo.h>
#include "renderthread/EglManager.h"
@@ -64,7 +64,7 @@
}
};
-void VkFunctorDrawable::vkInvokeFunctor(Functor* functor) {
+void VkInteropFunctorDrawable::vkInvokeFunctor(Functor* functor) {
ScopedDrawRequest _drawRequest{};
sGLDrawThread->queue().runSync([&]() {
EGLDisplay display = sEglManager.eglDisplay();
@@ -78,11 +78,11 @@
#define FENCE_TIMEOUT 2000000000
-void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
+void VkInteropFunctorDrawable::onDraw(SkCanvas* canvas) {
ATRACE_CALL();
if (canvas->getGrContext() == nullptr) {
- SkDEBUGF(("Attempting to draw VkFunctor into an unsupported surface"));
+ SkDEBUGF(("Attempting to draw VkInteropFunctor into an unsupported surface"));
return;
}
@@ -99,10 +99,11 @@
ColorTypeToPixelFormat(surfaceInfo.colorType()),
GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
GraphicBuffer::USAGE_SW_READ_NEVER | GraphicBuffer::USAGE_HW_RENDER,
- std::string("VkFunctorDrawable::onDraw pid [") + std::to_string(getpid()) + "]");
+ std::string("VkInteropFunctorDrawable::onDraw pid [") + std::to_string(getpid()) +
+ "]");
status_t error = mFrameBuffer->initCheck();
if (error < 0) {
- ALOGW("VkFunctorDrawable::onDraw() failed in GraphicBuffer.create()");
+ ALOGW("VkInteropFunctorDrawable::onDraw() failed in GraphicBuffer.create()");
return;
}
@@ -202,7 +203,7 @@
canvas->restore();
}
-VkFunctorDrawable::~VkFunctorDrawable() {
+VkInteropFunctorDrawable::~VkInteropFunctorDrawable() {
if (mListener.get() != nullptr) {
ScopedDrawRequest _drawRequest{};
sGLDrawThread->queue().runSync([&]() {
@@ -211,7 +212,7 @@
}
}
-void VkFunctorDrawable::syncFunctor() const {
+void VkInteropFunctorDrawable::syncFunctor() const {
ScopedDrawRequest _drawRequest{};
sGLDrawThread->queue().runSync([&]() {
(*mFunctor)(DrawGlInfo::kModeSync, nullptr);
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.h b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
similarity index 86%
rename from libs/hwui/pipeline/skia/VkFunctorDrawable.h
rename to libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
index e37f6fb..3269cfb 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
@@ -30,11 +30,12 @@
* This drawable wraps a Vulkan functor enabling it to be recorded into a list
* of Skia drawing commands.
*/
-class VkFunctorDrawable : public FunctorDrawable {
+class VkInteropFunctorDrawable : public FunctorDrawable {
public:
- VkFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener, SkCanvas* canvas)
+ VkInteropFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener,
+ SkCanvas* canvas)
: FunctorDrawable(functor, listener, canvas) {}
- virtual ~VkFunctorDrawable();
+ virtual ~VkInteropFunctorDrawable();
void syncFunctor() const override;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 92a749f..f1a522e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -180,14 +180,20 @@
}
}
-void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- mLightGeometry.radius = lightRadius;
+void CanvasContext::allocateBuffers() {
+ if (mNativeSurface) {
+ mNativeSurface->allocateBuffers();
+ }
+}
+
+void CanvasContext::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
mLightInfo.spotShadowAlpha = spotShadowAlpha;
}
-void CanvasContext::setLightCenter(const Vector3& lightCenter) {
+void CanvasContext::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
mLightGeometry.center = lightCenter;
+ mLightGeometry.radius = lightRadius;
}
void CanvasContext::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2307ee4..70be4a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -113,9 +113,10 @@
bool pauseSurface();
void setStopped(bool stopped);
bool hasSurface() { return mNativeSurface.get(); }
+ void allocateBuffers();
- void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
- void setLightCenter(const Vector3& lightCenter);
+ void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ void setLightGeometry(const Vector3& lightCenter, float lightRadius);
void setOpaque(bool opaque);
void setWideGamut(bool wideGamut);
bool makeCurrent();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 54219b5..085812a0 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -80,22 +80,16 @@
mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}
-void RenderProxy::initialize(const sp<Surface>& surface) {
+void RenderProxy::setSurface(const sp<Surface>& surface) {
mRenderThread.queue().post(
[ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
}
-void RenderProxy::allocateBuffers(const sp<Surface>& surface) {
- mRenderThread.queue().post(
- [ surf = surface ]() mutable { surf->allocateBuffers(); });
+void RenderProxy::allocateBuffers() {
+ mRenderThread.queue().post([=]() { mContext->allocateBuffers(); });
}
-void RenderProxy::updateSurface(const sp<Surface>& surface) {
- mRenderThread.queue().post(
- [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
-}
-
-bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
+bool RenderProxy::pause() {
return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
}
@@ -103,13 +97,13 @@
mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
}
-void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void RenderProxy::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
mRenderThread.queue().post(
- [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
+ [=]() { mContext->setLightAlpha(ambientShadowAlpha, spotShadowAlpha); });
}
-void RenderProxy::setLightCenter(const Vector3& lightCenter) {
- mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
+void RenderProxy::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
+ mRenderThread.queue().post([=]() { mContext->setLightGeometry(lightCenter, lightRadius); });
}
void RenderProxy::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d29fcc4..6668c584 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,13 +69,12 @@
ANDROID_API bool loadSystemProperties();
ANDROID_API void setName(const char* name);
- ANDROID_API void initialize(const sp<Surface>& surface);
- ANDROID_API void allocateBuffers(const sp<Surface>& surface);
- ANDROID_API void updateSurface(const sp<Surface>& surface);
- ANDROID_API bool pauseSurface(const sp<Surface>& surface);
+ ANDROID_API void setSurface(const sp<Surface>& surface);
+ ANDROID_API void allocateBuffers();
+ ANDROID_API bool pause();
ANDROID_API void setStopped(bool stopped);
- ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
- ANDROID_API void setLightCenter(const Vector3& lightCenter);
+ ANDROID_API void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ ANDROID_API void setLightGeometry(const Vector3& lightCenter, float lightRadius);
ANDROID_API void setOpaque(bool opaque);
ANDROID_API void setWideGamut(bool wideGamut);
ANDROID_API int64_t* frameInfo();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 62f704b..2384f95 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -74,7 +74,7 @@
PREVENT_COPY_AND_ASSIGN(RenderThread);
public:
- // Sets a callback that fires before any RenderThread setup has occured.
+ // Sets a callback that fires before any RenderThread setup has occurred.
ANDROID_API static void setOnStartHook(void (*onStartHook)());
WorkQueue& queue() { return ThreadBase::queue(); }
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5f5a92e..5fa008b 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -132,10 +132,10 @@
ContextFactory factory;
std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
proxy->loadSystemProperties();
- proxy->initialize(surface);
+ proxy->setSurface(surface);
float lightX = width / 2.0;
- proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15);
- proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
+ proxy->setLightAlpha(255 * 0.075, 255 * 0.15);
+ proxy->setLightGeometry((Vector3){lightX, dp(-200.0f), dp(800.0f)}, dp(800.0f));
// Do a few cold runs then reset the stats so that the caches are all hot
int warmupFrameCount = 5;
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 1276881..b5d835a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -120,4 +120,18 @@
// used by gts tests to verify throttling whitelist
String[] getBackgroundThrottlingWhitelist();
+
+ /**
+ * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
+ * provider} to start the UI to modify the location permission for a package.
+ *
+ * <p>Can only be called by the location provider.
+ *
+ * @param packageName The package the permission belongs to
+ * @param permission The (individual) permission to switch
+ *
+ * @return A pending intent that starts the permission management UI or {@code null} if the
+ * intent cannot be created
+ */
+ PendingIntent createManageLocationPermissionIntent(in String packageName, in String permission);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b1968ba..02680ab 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,6 +22,7 @@
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -43,7 +44,9 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
+
import com.android.internal.location.ProviderProperties;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -2393,4 +2396,29 @@
return null;
}
}
+
+ /**
+ * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
+ * provider} to start the UI to modify the location permission for a package.
+ *
+ * <p>Can only be called by the location provider.
+ *
+ * @param packageName The package the permission belongs to
+ * @param permission The (individual) location permission to switch
+ *
+ * @return A one-shot pending intent that starts the permission management UI or {@code null} if
+ * the intent cannot be created
+ *
+ * @hide
+ */
+ @SystemApi
+ public @Nullable PendingIntent createManageLocationPermissionIntent(@NonNull String packageName,
+ @NonNull String permission) {
+ try {
+ return mService.createManageLocationPermissionIntent(packageName, permission);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
}
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index b51caa5..0b3c973 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -23,9 +23,7 @@
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.SurfaceTexture;
-import android.net.Uri;
import android.os.Handler;
-import android.os.Parcel;
import android.os.PersistableBundle;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -34,7 +32,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -241,47 +238,6 @@
return new MediaPlayer2Impl(context);
}
- private static final String[] decodeMediaPlayer2Uri(String location) {
- Uri uri = Uri.parse(location);
- if (!"mediaplayer2".equals(uri.getScheme())) {
- return new String[] {location};
- }
-
- List<String> uris = uri.getQueryParameters("uri");
- if (uris.isEmpty()) {
- return new String[] {location};
- }
-
- List<String> keys = uri.getQueryParameters("key");
- List<String> values = uri.getQueryParameters("value");
- if (keys.size() != values.size()) {
- return new String[] {uris.get(0)};
- }
-
- List<String> ls = new ArrayList();
- ls.add(uris.get(0));
- for (int i = 0; i < keys.size() ; i++) {
- ls.add(keys.get(i));
- ls.add(values.get(i));
- }
-
- return ls.toArray(new String[ls.size()]);
- }
-
- private static final String encodeMediaPlayer2Uri(String uri, String[] keys, String[] values) {
- Uri.Builder builder = new Uri.Builder();
- builder.scheme("mediaplayer2").path("/").appendQueryParameter("uri", uri);
- if (keys == null || values == null || keys.length != values.length) {
- return builder.build().toString();
- }
- for (int i = 0; i < keys.length ; i++) {
- builder
- .appendQueryParameter("key", keys[i])
- .appendQueryParameter("value", values[i]);
- }
- return builder.build().toString();
- }
-
/**
* @hide
*/
@@ -291,12 +247,6 @@
}
/**
- * Returns a {@link MediaPlayerBase} implementation which runs based on
- * this MediaPlayer2 instance.
- */
- public abstract MediaPlayerBase getMediaPlayerBase();
-
- /**
* Releases the resources held by this {@code MediaPlayer2} object.
*
* It is considered good practice to call this method when you're
@@ -342,8 +292,7 @@
* Starts or resumes playback. If playback had previously been paused,
* playback will continue from where it was paused. If playback had
* reached end of stream and been paused, or never started before,
- * playback will start at the beginning. If the source had not been
- * prepared, the player will prepare the source and play.
+ * playback will start at the beginning.
*
* @return a token which can be used to cancel the operation later with {@link #cancel}.
*/
@@ -376,18 +325,6 @@
public abstract Object skipToNext();
/**
- * Moves the media to specified time position.
- * Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
- *
- * @param msec the offset in milliseconds from the start to seek to
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
- */
- // This is an asynchronous call.
- public Object seekTo(long msec) {
- return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
- }
-
- /**
* Gets the current playback position.
*
* @return the current position in milliseconds
@@ -404,9 +341,8 @@
/**
* Gets the current buffered media source position received through progressive downloading.
- * The received buffering percentage indicates how much of the content has been buffered
- * or played. For example a buffering update of 80 percent when half the content
- * has already been played indicates that the next 30 percent of the
+ * For example a buffering update of 8000 milliseconds when 5000 milliseconds of the content
+ * has already been played indicates that the next 3000 milliseconds of the
* content to play has been buffered.
*
* @return the current buffered media source position in milliseconds
@@ -416,7 +352,6 @@
/**
* MediaPlayer2 has not been prepared or just has been reset.
* In this state, MediaPlayer2 doesn't fetch data.
- * @hide
*/
public static final int PLAYER_STATE_IDLE = 1001;
@@ -424,26 +359,23 @@
* MediaPlayer2 has been just prepared.
* In this state, MediaPlayer2 just fetches data from media source,
* but doesn't actively render data.
- * @hide
*/
public static final int PLAYER_STATE_PREPARED = 1002;
/**
* MediaPlayer2 is paused.
- * In this state, MediaPlayer2 doesn't actively render data.
- * @hide
+ * In this state, MediaPlayer2 has allocated resources to construct playback
+ * pipeline, but it doesn't actively render data.
*/
public static final int PLAYER_STATE_PAUSED = 1003;
/**
* MediaPlayer2 is actively playing back data.
- * @hide
*/
public static final int PLAYER_STATE_PLAYING = 1004;
/**
* MediaPlayer2 has hit some fatal error and cannot continue playback.
- * @hide
*/
public static final int PLAYER_STATE_ERROR = 1005;
@@ -469,7 +401,7 @@
/**
* Sets the audio attributes for this MediaPlayer2.
* See {@link AudioAttributes} for how to build and configure an instance of this class.
- * You must call this method before {@link #prepare()} in order
+ * You must call this method before {@link #play()} and {@link #pause()} in order
* for the audio attributes to become effective thereafter.
* @param attributes a non-null set of audio attributes
* @return a token which can be used to cancel the operation later with {@link #cancel}.
@@ -547,7 +479,7 @@
public abstract Object setPlayerVolume(float volume);
/**
- * Returns the current volume of this player to this player.
+ * Returns the current volume of this player.
* Note that it does not take into account the associated stream volume.
* @return the player volume.
*/
@@ -561,24 +493,9 @@
}
/**
- * Create a request parcel which can be routed to the native media
- * player using {@link #invoke(Parcel, Parcel)}. The Parcel
- * returned has the proper InterfaceToken set. The caller should
- * not overwrite that token, i.e it can only append data to the
- * Parcel.
- *
- * @return A parcel suitable to hold a request for the native
- * player.
- * {@hide}
- */
- public Parcel newRequest() {
- return null;
- }
-
- /**
* Insert a task in the command queue to help the client to identify whether a batch
* of commands has been finished. When this command is processed, a notification
- * {@code EventCallback.onCommandLabelReached} will be fired with the
+ * {@link EventCallback#onCommandLabelReached onCommandLabelReached} will be fired with the
* given {@code label}.
*
* @see EventCallback#onCommandLabelReached
@@ -595,16 +512,13 @@
* portion of the media.
*
* Either a surface holder or surface must be set if a display or video sink
- * is needed. Not calling this method or {@link #setSurface(Surface)}
+ * is needed. Not calling this method or {@link #setSurface(Surface)}
* when playing back a video will result in only the audio track being played.
* A null surface holder or surface will result in only the audio track being
* played.
*
* @param sh the SurfaceHolder to use for video display
- * @throws IllegalStateException if the internal player engine has not been
- * initialized or has been released.
* @return a token which can be used to cancel the operation later with {@link #cancel}.
- * @hide
*/
public abstract Object setDisplay(SurfaceHolder sh);
@@ -624,56 +538,44 @@
*
* @param surface The {@link Surface} to be used for the video portion of
* the media.
- * @throws IllegalStateException if the internal player engine has not been
- * initialized or has been released.
* @return a token which can be used to cancel the operation later with {@link #cancel}.
*/
// This is an asynchronous call.
public abstract Object setSurface(Surface surface);
- /* Do not change these video scaling mode values below without updating
- * their counterparts in system/window.h! Please do not forget to update
- * {@link #isVideoScalingModeSupported} when new video scaling modes
- * are added.
- */
/**
- * Specifies a video scaling mode. The content is stretched to the
- * surface rendering area. When the surface has the same aspect ratio
- * as the content, the aspect ratio of the content is maintained;
- * otherwise, the aspect ratio of the content is not maintained when video
- * is being rendered.
- * There is no content cropping with this video scaling mode.
- */
- public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1;
-
- /**
- * Specifies a video scaling mode. The content is scaled, maintaining
- * its aspect ratio. The whole surface area is always used. When the
- * aspect ratio of the content is the same as the surface, no content
- * is cropped; otherwise, content is cropped to fit the surface.
- * @hide
- */
- public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2;
-
- /**
- * Sets video scaling mode. To make the target video scaling mode
- * effective during playback, this method must be called after
- * data source is set. If not called, the default video
- * scaling mode is {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}.
+ * Set the low-level power management behavior for this MediaPlayer2. This
+ * can be used when the MediaPlayer2 is not playing through a SurfaceHolder
+ * set with {@link #setDisplay(SurfaceHolder)} and thus can use the
+ * high-level {@link #setScreenOnWhilePlaying(boolean)} feature.
*
- * <p> The supported video scaling modes are:
- * <ul>
- * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}
- * </ul>
+ * <p>This function has the MediaPlayer2 access the low-level power manager
+ * service to control the device's power usage while playing is occurring.
+ * The parameter is a combination of {@link android.os.PowerManager} wake flags.
+ * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
+ * permission.
+ * By default, no attempt is made to keep the device awake during playback.
*
- * @param mode target video scaling mode. Must be one of the supported
- * video scaling modes; otherwise, IllegalArgumentException will be thrown.
+ * @param context the Context to use
+ * @param mode the power/wake mode to set
* @return a token which can be used to cancel the operation later with {@link #cancel}.
- *
- * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT
- * @hide
+ * @see android.os.PowerManager
*/
- public abstract Object setVideoScalingMode(int mode);
+ // This is an asynchronous call.
+ public abstract Object setWakeMode(Context context, int mode);
+
+ /**
+ * Control whether we should use the attached SurfaceHolder to keep the
+ * screen on while video playback is occurring. This is the preferred
+ * method over {@link #setWakeMode} where possible, since it doesn't
+ * require that the application have permission for low-level wake lock
+ * access.
+ *
+ * @param screenOn Supply true to keep the screen on, false to allow it to turn off.
+ * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ */
+ // This is an asynchronous call.
+ public abstract Object setScreenOnWhilePlaying(boolean screenOn);
/**
* Cancels a pending command.
@@ -702,7 +604,7 @@
* @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
* does not correspond to a valid audio device.
*/
- // This is an asynchronous call.
+ // This is a synchronous call.
@Override
public abstract boolean setPreferredDevice(AudioDeviceInfo deviceInfo);
@@ -747,58 +649,16 @@
AudioRouting.OnRoutingChangedListener listener);
/**
- * Set the low-level power management behavior for this MediaPlayer2.
+ * Returns the size of the video.
*
- * <p>This function has the MediaPlayer2 access the low-level power manager
- * service to control the device's power usage while playing is occurring.
- * The parameter is a combination of {@link android.os.PowerManager} wake flags.
- * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
- * permission.
- * By default, no attempt is made to keep the device awake during playback.
- *
- * @param context the Context to use
- * @param mode the power/wake mode to set
- * @see android.os.PowerManager
- * @hide
- */
- public abstract void setWakeMode(Context context, int mode);
-
- /**
- * Control whether we should use the attached SurfaceHolder to keep the
- * screen on while video playback is occurring. This is the preferred
- * method over {@link #setWakeMode} where possible, since it doesn't
- * require that the application have permission for low-level wake lock
- * access.
- *
- * @param screenOn Supply true to keep the screen on, false to allow it
- * to turn off.
- * @hide
- */
- public abstract void setScreenOnWhilePlaying(boolean screenOn);
-
- /**
- * Returns the width of the video.
- *
- * @return the width of the video, or 0 if there is no video,
- * no display surface was set, or the width has not been determined
- * yet. The {@code EventCallback} can be registered via
+ * @return the size of the video. The width and height of size could be 0 if there is no video,
+ * no display surface was set, or the size has not been determined yet.
+ * The {@code EventCallback} can be registered via
* {@link #setEventCallback(Executor, EventCallback)} to provide a
- * notification {@code EventCallback.onVideoSizeChanged} when the width
+ * notification {@code EventCallback.onVideoSizeChanged} when the size
* is available.
*/
- public abstract int getVideoWidth();
-
- /**
- * Returns the height of the video.
- *
- * @return the height of the video, or 0 if there is no video,
- * no display surface was set, or the height has not been determined
- * yet. The {@code EventCallback} can be registered via
- * {@link #setEventCallback(Executor, EventCallback)} to provide a
- * notification {@code EventCallback.onVideoSizeChanged} when the height is
- * available.
- */
- public abstract int getVideoHeight();
+ public abstract VideoSize getVideoSize();
/**
* Return Metrics data about the current player.
@@ -958,6 +818,18 @@
public abstract SyncParams getSyncParams();
/**
+ * Moves the media to specified time position.
+ * Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
+ *
+ * @param msec the offset in milliseconds from the start to seek to
+ * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ */
+ // This is an asynchronous call.
+ public Object seekTo(long msec) {
+ return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
+ }
+
+ /**
* Seek modes used in method seekTo(long, int) to move media position
* to a specified location.
*
@@ -1287,11 +1159,10 @@
*
* @param mp the MediaPlayer2 associated with this callback
* @param dsd the DataSourceDesc of this data source
- * @param width the width of the video
- * @param height the height of the video
+ * @param size the size of the video
*/
public void onVideoSizeChanged(
- MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) { }
+ MediaPlayer2 mp, DataSourceDesc dsd, VideoSize size) { }
/**
* Called to indicate an avaliable timed text
@@ -1719,18 +1590,21 @@
*/
public static final int CALL_COMPLETED_SET_BUFFERING_PARAMS = 31;
- /** The player just completed a call {@link #setVideoScalingMode}.
- * @see EventCallback#onCallCompleted
- * @hide
- */
- public static final int CALL_COMPLETED_SET_VIDEO_SCALING_MODE = 32;
-
/** The player just completed a call {@link #setDisplay}.
* @see EventCallback#onCallCompleted
- * @hide
*/
public static final int CALL_COMPLETED_SET_DISPLAY = 33;
+ /** The player just completed a call {@link #setWakeMode}.
+ * @see EventCallback#onCallCompleted
+ */
+ public static final int CALL_COMPLETED_SET_WAKE_MODE = 34;
+
+ /** The player just completed a call {@link #setScreenOnWhilePlaying}.
+ * @see EventCallback#onCallCompleted
+ */
+ public static final int CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING = 35;
+
/**
* The start of the methods which have separate call complete callback.
* @hide
@@ -1776,8 +1650,9 @@
CALL_COMPLETED_SKIP_TO_NEXT,
CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES,
CALL_COMPLETED_SET_BUFFERING_PARAMS,
- CALL_COMPLETED_SET_VIDEO_SCALING_MODE,
CALL_COMPLETED_SET_DISPLAY,
+ CALL_COMPLETED_SET_WAKE_MODE,
+ CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING,
CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED,
CALL_COMPLETED_PREPARE_DRM,
})
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index ef8db1d..47ab7fac 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -19,11 +19,11 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ContentProvider;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.graphics.SurfaceTexture;
import android.graphics.Rect;
import android.media.MediaPlayer2Proto.PlayerMessage;
import android.media.MediaPlayer2Proto.Value;
@@ -34,9 +34,6 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.view.Surface;
@@ -78,18 +75,22 @@
native_init();
}
+ private static final int NEXT_SOURCE_STATE_ERROR = -1;
+ private static final int NEXT_SOURCE_STATE_INIT = 0;
+ private static final int NEXT_SOURCE_STATE_PREPARING = 1;
+ private static final int NEXT_SOURCE_STATE_PREPARED = 2;
+
private final static String TAG = "MediaPlayer2Impl";
private Context mContext;
- private long mNativeContext; // accessed by native methods
+ private long mNativeContext; // accessed by native methods
private long mNativeSurfaceTexture; // accessed by native methods
- private int mListenerContext; // accessed by native methods
+ private int mListenerContext; // accessed by native methods
private SurfaceHolder mSurfaceHolder;
private PowerManager.WakeLock mWakeLock = null;
private boolean mScreenOnWhilePlaying;
private boolean mStayAwake;
- private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
private final Object mSrcLock = new Object();
//--- guarded by |mSrcLock| start
@@ -105,6 +106,7 @@
private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
private volatile float mVolume = 1.0f;
+ private VideoSize mVideoSize = new VideoSize(0, 0);
// Modular DRM
private final Object mDrmLock = new Object();
@@ -134,7 +136,7 @@
/**
* Default constructor.
- * <p>When done with the MediaPlayer2Impl, you should call {@link #close()},
+ * <p>When done with the MediaPlayer2Impl, you should call {@link #close()},
* to free the resources. If not released, too many MediaPlayer2Impl instances may
* result in an exception.</p>
*/
@@ -152,45 +154,11 @@
}
@Override
- public MediaPlayerBase getMediaPlayerBase() {
- return null;
- }
-
- /**
- * Releases the resources held by this {@code MediaPlayer2} object.
- *
- * It is considered good practice to call this method when you're
- * done using the MediaPlayer2. In particular, whenever an Activity
- * of an application is paused (its onPause() method is called),
- * or stopped (its onStop() method is called), this method should be
- * invoked to release the MediaPlayer2 object, unless the application
- * has a special need to keep the object around. In addition to
- * unnecessary resources (such as memory and instances of codecs)
- * being held, failure to call this method immediately if a
- * MediaPlayer2 object is no longer needed may also lead to
- * continuous battery consumption for mobile devices, and playback
- * failure for other applications if no multiple instances of the
- * same codec are supported on a device. Even if multiple instances
- * of the same codec are supported, some performance degradation
- * may be expected when unnecessary multiple instances are used
- * at the same time.
- *
- * {@code close()} may be safely called after a prior {@code close()}.
- * This class implements the Java {@code AutoCloseable} interface and
- * may be used with try-with-resources.
- */
- @Override
public void close() {
super.close();
release();
}
- /**
- * Starts or resumes playback. If playback had previously been paused,
- * playback will continue from where it was paused. If playback had
- * been stopped, or never started before, playback will start at the
- * beginning.
- */
@Override
public Object play() {
return addTask(new Task(CALL_COMPLETED_PLAY, false) {
@@ -204,14 +172,6 @@
private native void _start() throws IllegalStateException;
- /**
- * Prepares the player for playback, asynchronously.
- *
- * After setting the datasource and the display surface, you need to either
- * call prepare(). For streams, you should call prepare(),
- * which returns immediately, rather than blocking until enough data has been
- * buffered.
- */
@Override
public Object prepare() {
return addTask(new Task(CALL_COMPLETED_PREPARE, true) {
@@ -224,9 +184,6 @@
public native void _prepare();
- /**
- * Pauses playback. Call play() to resume.
- */
@Override
public Object pause() {
return addTask(new Task(CALL_COMPLETED_PAUSE, false) {
@@ -241,11 +198,6 @@
private native void _pause() throws IllegalStateException;
- /**
- * Tries to play next data source if applicable.
- *
- * @throws IllegalStateException if it is called in an invalid state
- */
@Override
public Object skipToNext() {
return addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
@@ -259,32 +211,12 @@
});
}
- /**
- * Gets the current playback position.
- *
- * @return the current position in milliseconds
- */
@Override
public native long getCurrentPosition();
- /**
- * Gets the duration of the file.
- *
- * @return the duration in milliseconds, if no duration is available
- * (for example, if streaming live content), -1 is returned.
- */
@Override
public native long getDuration();
- /**
- * Gets the current buffered media source position received through progressive downloading.
- * The received buffering percentage indicates how much of the content has been buffered
- * or played. For example a buffering update of 80 percent when half the content
- * has already been played indicates that the next 30 percent of the
- * content to play has been buffered.
- *
- * @return the current buffered media source position in milliseconds
- */
@Override
public long getBufferedPosition() {
// Use cached buffered percent for now.
@@ -298,14 +230,6 @@
private native int native_getState();
- /**
- * Sets the audio attributes for this MediaPlayer2.
- * See {@link AudioAttributes} for how to build and configure an instance of this class.
- * You must call this method before {@link #prepare()} in order
- * for the audio attributes to become effective thereafter.
- * @param attributes a non-null set of audio attributes
- * @throws IllegalArgumentException if the attributes are null or invalid.
- */
@Override
public Object setAudioAttributes(@NonNull AudioAttributes attributes) {
return addTask(new Task(CALL_COMPLETED_SET_AUDIO_ATTRIBUTES, false) {
@@ -326,11 +250,6 @@
return attributes;
}
- /**
- * Sets the data source as described by a DataSourceDesc.
- *
- * @param dsd the descriptor of data source you want to play
- */
@Override
public Object setDataSource(@NonNull DataSourceDesc dsd) {
return addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
@@ -351,12 +270,6 @@
});
}
- /**
- * Sets a single data source as described by a DataSourceDesc which will be played
- * after current data source is finished.
- *
- * @param dsd the descriptor of data source you want to play after current one
- */
@Override
public Object setNextDataSource(@NonNull DataSourceDesc dsd) {
return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
@@ -374,11 +287,6 @@
});
}
- /**
- * Sets a list of data sources to be played sequentially after current data source is done.
- *
- * @param dsds the list of data sources you want to play after current one
- */
@Override
public Object setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCES, false) {
@@ -428,16 +336,11 @@
}
}
- /**
- * Configures the player to loop on the current data source.
- * @param loop true if the current data source is meant to loop.
- */
@Override
public Object loopCurrent(boolean loop) {
return addTask(new Task(CALL_COMPLETED_LOOP_CURRENT, false) {
@Override
void process() {
- // TODO: set the looping mode, send notification
setLooping(loop);
}
});
@@ -445,57 +348,29 @@
private native void setLooping(boolean looping);
- /**
- * Sets the volume of the audio of the media to play, expressed as a linear multiplier
- * on the audio samples.
- * Note that this volume is specific to the player, and is separate from stream volume
- * used across the platform.<br>
- * A value of 0.0f indicates muting, a value of 1.0f is the nominal unattenuated and unamplified
- * gain. See {@link #getMaxPlayerVolume()} for the volume range supported by this player.
- * @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}.
- */
@Override
public Object setPlayerVolume(float volume) {
return addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
@Override
void process() {
mVolume = volume;
- _setVolume(volume);
+ native_setVolume(volume);
}
});
}
- private native void _setVolume(float volume);
+ private native void native_setVolume(float volume);
- /**
- * Returns the current volume of this player to this player.
- * Note that it does not take into account the associated stream volume.
- * @return the player volume.
- */
@Override
public float getPlayerVolume() {
return mVolume;
}
- /**
- * @return the maximum volume that can be used in {@link #setPlayerVolume(float)}.
- */
@Override
public float getMaxPlayerVolume() {
return 1.0f;
}
- private static final int NEXT_SOURCE_STATE_ERROR = -1;
- private static final int NEXT_SOURCE_STATE_INIT = 0;
- private static final int NEXT_SOURCE_STATE_PREPARING = 1;
- private static final int NEXT_SOURCE_STATE_PREPARED = 2;
-
- /*
- * Update the MediaPlayer2Impl SurfaceTexture.
- * Call after setting a new display surface.
- */
- private native void _setVideoSurface(Surface surface);
-
/* Do not change these values (starting with INVOKE_ID) without updating
* their counterparts in include/media/mediaplayer2.h!
*/
@@ -504,7 +379,6 @@
private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3;
private static final int INVOKE_ID_SELECT_TRACK = 4;
private static final int INVOKE_ID_DESELECT_TRACK = 5;
- private static final int INVOKE_ID_SET_VIDEO_SCALE_MODE = 6;
private static final int INVOKE_ID_GET_SELECTED_TRACK = 7;
/**
@@ -518,7 +392,7 @@
* native player.
*/
private PlayerMessage invoke(PlayerMessage msg) {
- byte[] ret = _invoke(msg.toByteArray());
+ byte[] ret = native_invoke(msg.toByteArray());
if (ret == null) {
return null;
}
@@ -529,7 +403,7 @@
}
}
- private native byte[] _invoke(byte[] request);
+ private native byte[] native_invoke(byte[] request);
@Override
public Object notifyWhenCommandLabelReached(Object label) {
@@ -559,7 +433,7 @@
} else {
surface = null;
}
- _setVideoSurface(surface);
+ native_setVideoSurface(surface);
updateSurfaceScreenOn();
}
});
@@ -574,49 +448,13 @@
Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
}
mSurfaceHolder = null;
- _setVideoSurface(surface);
+ native_setVideoSurface(surface);
updateSurfaceScreenOn();
}
});
}
- /**
- * Sets video scaling mode. To make the target video scaling mode
- * effective during playback, this method must be called after
- * data source is set. If not called, the default video
- * scaling mode is {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}.
- *
- * <p> The supported video scaling modes are:
- * <ul>
- * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}
- * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
- * </ul>
- *
- * @param mode target video scaling mode. Must be one of the supported
- * video scaling modes; otherwise, IllegalArgumentException will be thrown.
- *
- * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT
- * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
- * @hide
- */
- @Override
- public Object setVideoScalingMode(int mode) {
- return addTask(new Task(CALL_COMPLETED_SET_VIDEO_SCALING_MODE, false) {
- @Override
- void process() {
- if (!isVideoScalingModeSupported(mode)) {
- final String msg = "Scaling mode " + mode + " is not supported";
- throw new IllegalArgumentException(msg);
- }
- PlayerMessage request = PlayerMessage.newBuilder()
- .addValues(Value.newBuilder()
- .setInt32Value(INVOKE_ID_SET_VIDEO_SCALE_MODE))
- .addValues(Value.newBuilder().setInt32Value(mode))
- .build();
- invoke(request);
- }
- });
- }
+ private native void native_setVideoSurface(Surface surface);
@Override
public boolean cancelCommand(Object token) {
@@ -632,26 +470,6 @@
}
}
- private Object addTask(Task task) {
- synchronized (mTaskLock) {
- mPendingTasks.add(task);
- processPendingTask_l();
- }
- return task;
- }
-
- @GuardedBy("mTaskLock")
- private void processPendingTask_l() {
- if (mCurrentTask != null) {
- return;
- }
- if (!mPendingTasks.isEmpty()) {
- Task task = mPendingTasks.remove(0);
- mCurrentTask = task;
- mTaskHandler.post(task);
- }
- }
-
private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId)
throws IOException {
checkArgument(dsd != null, "the DataSourceDesc cannot be null");
@@ -875,9 +693,7 @@
boolean isCurrent, long srcId, Media2DataSource dataSource,
long startPos, long endPos);
- /**
- * @return true if there is a next data source, false otherwise.
- */
+ // return true if there is a next data source, false otherwise.
// This function should be always called on |mHandlerThread|.
private boolean prepareNextDataSource() {
if (Looper.myLooper() != mHandlerThread.getLooper()) {
@@ -975,30 +791,11 @@
private native void nativePlayNextDataSource(long srcId);
-
- private int getAudioStreamType() {
- if (mStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
- mStreamType = _getAudioStreamType();
- }
- return mStreamType;
- }
-
- private native int _getAudioStreamType() throws IllegalStateException;
-
-
//--------------------------------------------------------------------------
// Explicit Routing
//--------------------
private AudioDeviceInfo mPreferredDevice = null;
- /**
- * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route
- * the output from this MediaPlayer2.
- * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink or source.
- * If deviceInfo is null, default routing is restored.
- * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
- * does not correspond to a valid audio device.
- */
@Override
public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
if (deviceInfo != null && !deviceInfo.isSink()) {
@@ -1014,10 +811,6 @@
return status;
}
- /**
- * Returns the selected output specified by {@link #setPreferredDevice}. Note that this
- * is not guaranteed to correspond to the actual device being used for playback.
- */
@Override
public AudioDeviceInfo getPreferredDevice() {
synchronized (this) {
@@ -1025,12 +818,6 @@
}
}
- /**
- * Returns an {@link AudioDeviceInfo} identifying the current routing of this MediaPlayer2
- * Note: The query is only valid if the MediaPlayer2 is currently playing.
- * If the player is not playing, the returned device can be null or correspond to previously
- * selected device when the player was last active.
- */
@Override
public AudioDeviceInfo getRoutedDevice() {
int deviceId = native_getRoutedDeviceId();
@@ -1047,130 +834,83 @@
return null;
}
- /*
- * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
- */
- @GuardedBy("mRoutingChangeListeners")
- private void enableNativeRoutingCallbacksLocked(boolean enabled) {
- if (mRoutingChangeListeners.size() == 0) {
- native_enableDeviceCallback(enabled);
- }
- }
-
- /**
- * The list of AudioRouting.OnRoutingChangedListener interfaces added (with
- * {@link #addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, Handler)}
- * by an app to receive (re)routing notifications.
- */
- @GuardedBy("mRoutingChangeListeners")
- private ArrayMap<AudioRouting.OnRoutingChangedListener,
- NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
-
- /**
- * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
- * changes on this MediaPlayer2.
- * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive
- * notifications of rerouting events.
- * @param handler Specifies the {@link Handler} object for the thread on which to execute
- * the callback. If <code>null</code>, the handler on the main looper will be used.
- */
@Override
public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
Handler handler) {
- synchronized (mRoutingChangeListeners) {
- if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
- enableNativeRoutingCallbacksLocked(true);
- mRoutingChangeListeners.put(
- listener, new NativeRoutingEventHandlerDelegate(this, listener,
- handler != null ? handler : mTaskHandler));
- }
+ if (listener == null) {
+ throw new IllegalArgumentException("addOnRoutingChangedListener: listener is NULL");
}
+ RoutingDelegate routingDelegate = new RoutingDelegate(this, listener, handler);
+ native_addDeviceCallback(routingDelegate);
}
- /**
- * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added
- * to receive rerouting notifications.
- * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
- * to remove.
- */
@Override
public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
- synchronized (mRoutingChangeListeners) {
- if (mRoutingChangeListeners.containsKey(listener)) {
- mRoutingChangeListeners.remove(listener);
- enableNativeRoutingCallbacksLocked(false);
- }
+ if (listener == null) {
+ throw new IllegalArgumentException("removeOnRoutingChangedListener: listener is NULL");
}
+ native_removeDeviceCallback(listener);
}
private native final boolean native_setOutputDevice(int deviceId);
private native final int native_getRoutedDeviceId();
- private native final void native_enableDeviceCallback(boolean enabled);
+ private native void native_addDeviceCallback(RoutingDelegate rd);
+ private native void native_removeDeviceCallback(
+ AudioRouting.OnRoutingChangedListener listener);
- /**
- * Set the low-level power management behavior for this MediaPlayer2. This
- * can be used when the MediaPlayer2 is not playing through a SurfaceHolder
- * set with {@link #setDisplay(SurfaceHolder)} and thus can use the
- * high-level {@link #setScreenOnWhilePlaying(boolean)} feature.
- *
- * <p>This function has the MediaPlayer2 access the low-level power manager
- * service to control the device's power usage while playing is occurring.
- * The parameter is a combination of {@link android.os.PowerManager} wake flags.
- * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
- * permission.
- * By default, no attempt is made to keep the device awake during playback.
- *
- * @param context the Context to use
- * @param mode the power/wake mode to set
- * @see android.os.PowerManager
- * @hide
- */
@Override
- public void setWakeMode(Context context, int mode) {
- boolean washeld = false;
+ public Object setWakeMode(Context context, int mode) {
+ return addTask(new Task(CALL_COMPLETED_SET_WAKE_MODE, false) {
+ @Override
+ void process() {
+ boolean washeld = false;
- /* Disable persistant wakelocks in media player based on property */
- if (SystemProperties.getBoolean("audio.offload.ignore_setawake", false) == true) {
- Log.w(TAG, "IGNORING setWakeMode " + mode);
- return;
- }
+ if (mWakeLock != null) {
+ if (mWakeLock.isHeld()) {
+ washeld = true;
+ mWakeLock.release();
+ }
+ mWakeLock = null;
+ }
- if (mWakeLock != null) {
- if (mWakeLock.isHeld()) {
- washeld = true;
- mWakeLock.release();
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ ActivityManager am =
+ (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ List<RunningAppProcessInfo> runningAppsProcInfo = am.getRunningAppProcesses();
+ int pid = android.os.Process.myPid();
+ String name = "pid " + String.valueOf(pid);
+ if (runningAppsProcInfo != null) {
+ for (RunningAppProcessInfo procInfo : runningAppsProcInfo) {
+ if (procInfo.pid == pid) {
+ name = procInfo.processName;
+ break;
+ }
+ }
+ }
+ mWakeLock = pm.newWakeLock(mode | PowerManager.ON_AFTER_RELEASE, name);
+ mWakeLock.setReferenceCounted(false);
+ if (washeld) {
+ mWakeLock.acquire();
+ }
}
- mWakeLock = null;
- }
-
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(mode|PowerManager.ON_AFTER_RELEASE, MediaPlayer2Impl.class.getName());
- mWakeLock.setReferenceCounted(false);
- if (washeld) {
- mWakeLock.acquire();
- }
+ });
}
- /**
- * Control whether we should use the attached SurfaceHolder to keep the
- * screen on while video playback is occurring. This is the preferred
- * method over {@link #setWakeMode} where possible, since it doesn't
- * require that the application have permission for low-level wake lock
- * access.
- *
- * @param screenOn Supply true to keep the screen on, false to allow it
- * to turn off.
- * @hide
- */
@Override
- public void setScreenOnWhilePlaying(boolean screenOn) {
- if (mScreenOnWhilePlaying != screenOn) {
- if (screenOn && mSurfaceHolder == null) {
- Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
+ public Object setScreenOnWhilePlaying(boolean screenOn) {
+ return addTask(new Task(CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING, false) {
+ @Override
+ void process() {
+ if (mScreenOnWhilePlaying != screenOn) {
+ if (screenOn && mSurfaceHolder == null) {
+ Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective"
+ + " without a SurfaceHolder");
+ }
+ mScreenOnWhilePlaying = screenOn;
+ updateSurfaceScreenOn();
+ }
}
- mScreenOnWhilePlaying = screenOn;
- updateSurfaceScreenOn();
- }
+ });
}
private void stayAwake(boolean awake) {
@@ -1191,42 +931,11 @@
}
}
- /**
- * Returns the width of the video.
- *
- * @return the width of the video, or 0 if there is no video,
- * no display surface was set, or the width has not been determined
- * yet. The {@code EventCallback} can be registered via
- * {@link #setEventCallback(Executor, EventCallback)} to provide a
- * notification {@code EventCallback.onVideoSizeChanged} when the width
- * is available.
- */
@Override
- public native int getVideoWidth();
+ public VideoSize getVideoSize() {
+ return mVideoSize;
+ }
- /**
- * Returns the height of the video.
- *
- * @return the height of the video, or 0 if there is no video,
- * no display surface was set, or the height has not been determined
- * yet. The {@code EventCallback} can be registered via
- * {@link #setEventCallback(Executor, EventCallback)} to provide a
- * notification {@code EventCallback.onVideoSizeChanged} when the height
- * is available.
- */
- @Override
- public native int getVideoHeight();
-
- /**
- * Return Metrics data about the current player.
- *
- * @return a {@link PersistableBundle} containing the set of attributes and values
- * available for the media being handled by this instance of MediaPlayer2
- * The attributes are descibed in {@link MetricsConstants}.
- *
- * Additional vendor-specific fields may also be present in
- * the return value.
- */
@Override
public PersistableBundle getMetrics() {
PersistableBundle bundle = native_getMetrics();
@@ -1235,27 +944,9 @@
private native PersistableBundle native_getMetrics();
- /**
- * Checks whether the MediaPlayer2 is playing.
- *
- * @return true if currently playing, false otherwise
- * @throws IllegalStateException if the internal player engine has not been
- * initialized or has been released.
- * @hide
- */
@Override
public native boolean isPlaying();
- /**
- * Gets the current buffering management params used by the source component.
- * Calling it only after {@code setDataSource} has been called.
- * Each type of data source might have different set of default params.
- *
- * @return the current buffering management params used by the source component.
- * @throws IllegalStateException if the internal player engine has not been
- * initialized, or {@code setDataSource} has not been called.
- * @hide
- */
@Override
@NonNull
public native BufferingParams getBufferingParams();
@@ -1905,7 +1596,6 @@
private static final int MEDIA_SUBTITLE_DATA = 201;
private static final int MEDIA_META_DATA = 202;
private static final int MEDIA_DRM_INFO = 210;
- private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
private class TaskHandler extends Handler {
private MediaPlayer2Impl mMediaPlayer;
@@ -1944,80 +1634,175 @@
}
switch(msg.what) {
- case MEDIA_PREPARED:
- {
- if (dsd != null) {
+ case MEDIA_PREPARED:
+ {
+ if (dsd != null) {
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onInfo(
+ mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
+ }
+ });
+ }
+
+ synchronized (mSrcLock) {
+ Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
+ + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
+
+ if (isCurrentSrcId) {
+ prepareNextDataSource();
+ } else if (isNextSrcId) {
+ mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
+ if (mNextSourcePlayPending) {
+ playNextDataSource();
+ }
+ }
+ }
+
+ synchronized (mTaskLock) {
+ if (mCurrentTask != null
+ && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
+ && mCurrentTask.mDSD == dsd
+ && mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+ mCurrentTask = null;
+ processPendingTask_l();
+ }
+ }
+ return;
+ }
+
+ case MEDIA_DRM_INFO:
+ {
+ if (msg.obj == null) {
+ Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
+ } else if (msg.obj instanceof byte[]) {
+ // The PlayerMessage was parsed already in postEventFromNative
+ final DrmInfoImpl drmInfo;
+
+ synchronized (mDrmLock) {
+ if (mDrmInfoImpl != null) {
+ drmInfo = mDrmInfoImpl.makeCopy();
+ } else {
+ drmInfo = null;
+ }
+ }
+
+ // notifying the client outside the lock
+ if (drmInfo != null) {
+ sendDrmEvent(new DrmEventNotifier() {
+ @Override
+ public void notify(DrmEventCallback callback) {
+ callback.onDrmInfo(
+ mMediaPlayer, dsd, drmInfo);
+ }
+ });
+ }
+ } else {
+ Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
+ }
+ return;
+ }
+
+ case MEDIA_PLAYBACK_COMPLETE:
+ {
+ if (isCurrentSrcId) {
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onInfo(
+ mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
+ }
+ });
+ stayAwake(false);
+
+ synchronized (mSrcLock) {
+ mNextSourcePlayPending = true;
+
+ Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
+ + ", currentSrcId=" + mCurrentSrcId
+ + ", nextSrcId=" + mNextSrcId);
+ }
+
+ playNextDataSource();
+ }
+
+ return;
+ }
+
+ case MEDIA_STOPPED:
+ case MEDIA_STARTED:
+ case MEDIA_PAUSED:
+ case MEDIA_SKIPPED:
+ case MEDIA_NOTIFY_TIME:
+ {
+ // Do nothing. The client should have enough information with
+ // {@link EventCallback#onMediaTimeDiscontinuity}.
+ break;
+ }
+
+ case MEDIA_BUFFERING_UPDATE:
+ {
+ final int percent = msg.arg1;
sendEvent(new EventNotifier() {
@Override
public void notify(EventCallback callback) {
callback.onInfo(
- mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
+ mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
}
});
- }
- synchronized (mSrcLock) {
- Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
- + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-
- if (isCurrentSrcId) {
- prepareNextDataSource();
- } else if (isNextSrcId) {
- mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
- if (mNextSourcePlayPending) {
- playNextDataSource();
+ synchronized (mSrcLock) {
+ if (isCurrentSrcId) {
+ mBufferedPercentageCurrent.set(percent);
+ } else if (isNextSrcId) {
+ mBufferedPercentageNext.set(percent);
}
}
+ return;
}
- synchronized (mTaskLock) {
- if (mCurrentTask != null
- && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
- && mCurrentTask.mDSD == dsd
- && mCurrentTask.mNeedToWaitForEventToComplete) {
- mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
- mCurrentTask = null;
- processPendingTask_l();
- }
- }
- return;
- }
-
- case MEDIA_DRM_INFO:
- {
- if (msg.obj == null) {
- Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
- } else if (msg.obj instanceof byte[]) {
- // The PlayerMessage was parsed already in postEventFromNative
- final DrmInfoImpl drmInfo;
-
- synchronized (mDrmLock) {
- if (mDrmInfoImpl != null) {
- drmInfo = mDrmInfoImpl.makeCopy();
- } else {
- drmInfo = null;
+ case MEDIA_SEEK_COMPLETE:
+ {
+ synchronized (mTaskLock) {
+ if (mCurrentTask != null
+ && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
+ && mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+ mCurrentTask = null;
+ processPendingTask_l();
}
}
-
- // notifying the client outside the lock
- if (drmInfo != null) {
- sendDrmEvent(new DrmEventNotifier() {
- @Override
- public void notify(DrmEventCallback callback) {
- callback.onDrmInfo(
- mMediaPlayer, dsd, drmInfo);
- }
- });
- }
- } else {
- Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
+ return;
}
- return;
- }
- case MEDIA_PLAYBACK_COMPLETE:
- {
- if (isCurrentSrcId) {
+ case MEDIA_SET_VIDEO_SIZE:
+ {
+ final int width = msg.arg1;
+ final int height = msg.arg2;
+
+ mVideoSize = new VideoSize(width, height);
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onVideoSizeChanged(
+ mMediaPlayer, dsd, mVideoSize);
+ }
+ });
+ return;
+ }
+
+ case MEDIA_ERROR:
+ {
+ Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onError(
+ mMediaPlayer, dsd, what, extra);
+ }
+ });
sendEvent(new EventNotifier() {
@Override
public void notify(EventCallback callback) {
@@ -2026,231 +1811,127 @@
}
});
stayAwake(false);
-
- synchronized (mSrcLock) {
- mNextSourcePlayPending = true;
-
- Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
- + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
- }
-
- playNextDataSource();
+ return;
}
- return;
- }
-
- case MEDIA_STOPPED:
- case MEDIA_STARTED:
- case MEDIA_PAUSED:
- case MEDIA_SKIPPED:
- case MEDIA_NOTIFY_TIME:
- {
- // Do nothing. The client should have enough information with
- // {@link EventCallback#onMediaTimeDiscontinuity}.
- break;
- }
-
- case MEDIA_BUFFERING_UPDATE:
- {
- final int percent = msg.arg1;
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onInfo(
- mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
+ case MEDIA_INFO:
+ {
+ switch (msg.arg1) {
+ case MEDIA_INFO_VIDEO_TRACK_LAGGING:
+ Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
+ break;
}
- });
- synchronized (mSrcLock) {
- if (isCurrentSrcId) {
- mBufferedPercentageCurrent.set(percent);
- } else if (isNextSrcId) {
- mBufferedPercentageNext.set(percent);
- }
- }
- return;
- }
-
- case MEDIA_SEEK_COMPLETE:
- {
- synchronized (mTaskLock) {
- if (mCurrentTask != null
- && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
- && mCurrentTask.mNeedToWaitForEventToComplete) {
- mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
- mCurrentTask = null;
- processPendingTask_l();
- }
- }
- return;
- }
-
- case MEDIA_SET_VIDEO_SIZE:
- {
- final int width = msg.arg1;
- final int height = msg.arg2;
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onVideoSizeChanged(
- mMediaPlayer, dsd, width, height);
- }
- });
- return;
- }
-
- case MEDIA_ERROR:
- {
- Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onError(
- mMediaPlayer, dsd, what, extra);
- }
- });
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onInfo(
- mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
- }
- });
- stayAwake(false);
- return;
- }
-
- case MEDIA_INFO:
- {
- switch (msg.arg1) {
- case MEDIA_INFO_VIDEO_TRACK_LAGGING:
- Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
- break;
- }
-
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onInfo(
- mMediaPlayer, dsd, what, extra);
- }
- });
-
- if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
- if (isCurrentSrcId) {
- prepareNextDataSource();
- }
- }
-
- // No real default action so far.
- return;
- }
-
- case MEDIA_TIMED_TEXT:
- {
- final TimedText text;
- if (msg.obj instanceof byte[]) {
- PlayerMessage playerMsg;
- try {
- playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
- } catch (InvalidProtocolBufferException e) {
- Log.w(TAG, "Failed to parse timed text.", e);
- return;
- }
- text = TimedTextUtil.parsePlayerMessage(playerMsg);
- } else {
- text = null;
- }
-
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onTimedText(
- mMediaPlayer, dsd, text);
- }
- });
- return;
- }
-
- case MEDIA_SUBTITLE_DATA:
- {
- if (msg.obj instanceof byte[]) {
- PlayerMessage playerMsg;
- try {
- playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
- } catch (InvalidProtocolBufferException e) {
- Log.w(TAG, "Failed to parse subtitle data.", e);
- return;
- }
- Iterator<Value> in = playerMsg.getValuesList().iterator();
- SubtitleData data = new SubtitleData(
- in.next().getInt32Value(), // trackIndex
- in.next().getInt64Value(), // startTimeUs
- in.next().getInt64Value(), // durationUs
- in.next().getBytesValue().toByteArray()); // data
sendEvent(new EventNotifier() {
@Override
public void notify(EventCallback callback) {
- callback.onSubtitleData(
+ callback.onInfo(
+ mMediaPlayer, dsd, what, extra);
+ }
+ });
+
+ if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
+ if (isCurrentSrcId) {
+ prepareNextDataSource();
+ }
+ }
+
+ // No real default action so far.
+ return;
+ }
+
+ case MEDIA_TIMED_TEXT:
+ {
+ final TimedText text;
+ if (msg.obj instanceof byte[]) {
+ PlayerMessage playerMsg;
+ try {
+ playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+ } catch (InvalidProtocolBufferException e) {
+ Log.w(TAG, "Failed to parse timed text.", e);
+ return;
+ }
+ text = TimedTextUtil.parsePlayerMessage(playerMsg);
+ } else {
+ text = null;
+ }
+
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onTimedText(
+ mMediaPlayer, dsd, text);
+ }
+ });
+ return;
+ }
+
+ case MEDIA_SUBTITLE_DATA:
+ {
+ if (msg.obj instanceof byte[]) {
+ PlayerMessage playerMsg;
+ try {
+ playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+ } catch (InvalidProtocolBufferException e) {
+ Log.w(TAG, "Failed to parse subtitle data.", e);
+ return;
+ }
+ Iterator<Value> in = playerMsg.getValuesList().iterator();
+ SubtitleData data = new SubtitleData(
+ in.next().getInt32Value(), // trackIndex
+ in.next().getInt64Value(), // startTimeUs
+ in.next().getInt64Value(), // durationUs
+ in.next().getBytesValue().toByteArray()); // data
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onSubtitleData(
+ mMediaPlayer, dsd, data);
+ }
+ });
+ }
+ return;
+ }
+
+ case MEDIA_META_DATA:
+ {
+ final TimedMetaData data;
+ if (msg.obj instanceof byte[]) {
+ PlayerMessage playerMsg;
+ try {
+ playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+ } catch (InvalidProtocolBufferException e) {
+ Log.w(TAG, "Failed to parse timed meta data.", e);
+ return;
+ }
+ Iterator<Value> in = playerMsg.getValuesList().iterator();
+ data = new TimedMetaData(
+ in.next().getInt64Value(), // timestampUs
+ in.next().getBytesValue().toByteArray()); // metaData
+ } else {
+ data = null;
+ }
+
+ sendEvent(new EventNotifier() {
+ @Override
+ public void notify(EventCallback callback) {
+ callback.onTimedMetaDataAvailable(
mMediaPlayer, dsd, data);
}
});
- }
- return;
- }
-
- case MEDIA_META_DATA:
- {
- final TimedMetaData data;
- if (msg.obj instanceof byte[]) {
- PlayerMessage playerMsg;
- try {
- playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
- } catch (InvalidProtocolBufferException e) {
- Log.w(TAG, "Failed to parse timed meta data.", e);
- return;
- }
- Iterator<Value> in = playerMsg.getValuesList().iterator();
- data = new TimedMetaData(
- in.next().getInt64Value(), // timestampUs
- in.next().getBytesValue().toByteArray()); // metaData
- } else {
- data = null;
+ return;
}
- sendEvent(new EventNotifier() {
- @Override
- public void notify(EventCallback callback) {
- callback.onTimedMetaDataAvailable(
- mMediaPlayer, dsd, data);
- }
- });
- return;
- }
-
- case MEDIA_NOP: // interface test message - ignore
- {
- break;
- }
-
- case MEDIA_AUDIO_ROUTING_CHANGED:
- {
- AudioManager.resetAudioPortGeneration();
- synchronized (mRoutingChangeListeners) {
- for (NativeRoutingEventHandlerDelegate delegate
- : mRoutingChangeListeners.values()) {
- delegate.notifyClient();
- }
+ case MEDIA_NOP: // interface test message - ignore
+ {
+ break;
}
- return;
- }
- default:
- {
- Log.e(TAG, "Unknown message type " + msg.what);
- return;
- }
+ default:
+ {
+ Log.e(TAG, "Unknown message type " + msg.what);
+ return;
+ }
}
}
}
@@ -3388,13 +3069,6 @@
// Modular DRM end
- /*
- * Test whether a given video scaling mode is supported.
- */
- private boolean isVideoScalingModeSupported(int mode) {
- return (mode == VIDEO_SCALING_MODE_SCALE_TO_FIT ||
- mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
- }
private static class TimedTextUtil {
// These keys must be in sync with the keys in TextDescription2.h
@@ -3450,6 +3124,26 @@
}
}
+ private Object addTask(Task task) {
+ synchronized (mTaskLock) {
+ mPendingTasks.add(task);
+ processPendingTask_l();
+ }
+ return task;
+ }
+
+ @GuardedBy("mTaskLock")
+ private void processPendingTask_l() {
+ if (mCurrentTask != null) {
+ return;
+ }
+ if (!mPendingTasks.isEmpty()) {
+ Task task = mPendingTasks.remove(0);
+ mCurrentTask = task;
+ mTaskHandler.post(task);
+ }
+ }
+
private abstract class Task implements Runnable {
private final int mMediaCallType;
private final boolean mNeedToWaitForEventToComplete;
diff --git a/media/java/android/media/RoutingDelegate.java b/media/java/android/media/RoutingDelegate.java
new file mode 100644
index 0000000..2359813
--- /dev/null
+++ b/media/java/android/media/RoutingDelegate.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.media;
+
+import android.os.Handler;
+
+class RoutingDelegate implements AudioRouting.OnRoutingChangedListener {
+ private AudioRouting mAudioRouting;
+ private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
+ private Handler mHandler;
+
+ RoutingDelegate(final AudioRouting audioRouting,
+ final AudioRouting.OnRoutingChangedListener listener,
+ Handler handler) {
+ mAudioRouting = audioRouting;
+ mOnRoutingChangedListener = listener;
+ mHandler = handler;
+ }
+
+ public AudioRouting.OnRoutingChangedListener getListener() {
+ return mOnRoutingChangedListener;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ @Override
+ public void onRoutingChanged(AudioRouting router) {
+ if (mOnRoutingChangedListener != null) {
+ mOnRoutingChangedListener.onRoutingChanged(mAudioRouting);
+ }
+ }
+}
diff --git a/media/java/android/media/VideoSize.java b/media/java/android/media/VideoSize.java
new file mode 100644
index 0000000..7e5cb1f
--- /dev/null
+++ b/media/java/android/media/VideoSize.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 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.media;
+
+/**
+ * Immutable class for describing width and height dimensions.
+ *
+ * @hide
+ */
+public final class VideoSize {
+ /**
+ * Create a new immutable VideoSize instance.
+ *
+ * @param width The width of the video size
+ * @param height The height of the video size
+ */
+ public VideoSize(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ /**
+ * Get the width of the video size
+ * @return width
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Get the height of the video size
+ * @return height
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Check if this video size is equal to another video size.
+ * <p>
+ * Two video sizes are equal if and only if both their widths and heights are
+ * equal.
+ * </p>
+ * <p>
+ * A video size object is never equal to any other type of object.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof VideoSize) {
+ VideoSize other = (VideoSize) obj;
+ return mWidth == other.mWidth && mHeight == other.mHeight;
+ }
+ return false;
+ }
+
+ /**
+ * Return the video size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the video size
+ */
+ @Override
+ public String toString() {
+ return mWidth + "x" + mHeight;
+ }
+
+ private final int mWidth;
+ private final int mHeight;
+}
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 7cf8828..8637ada 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -543,7 +543,7 @@
import jav.util.Iterator;
HashMap<k, v> hm;
- Set<Entry<k, v> > s = hm.entrySet();
+ Set<Entry<k, v>> s = hm.entrySet();
Iterator i = s.iterator();
Entry e = s.next();
*/
@@ -613,10 +613,10 @@
}
static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
- List<Vector<uint8_t> > list) {
+ List<Vector<uint8_t>> list) {
jclass clazz = gFields.arraylistClassId;
jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
- List<Vector<uint8_t> >::iterator iter = list.begin();
+ List<Vector<uint8_t>>::iterator iter = list.begin();
while (iter != list.end()) {
jbyteArray byteArray = VectorToJByteArray(env, *iter);
env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
@@ -1216,7 +1216,7 @@
return NULL;
}
- List<Vector<uint8_t> > secureStops;
+ List<Vector<uint8_t>> secureStops;
status_t err = drm->getSecureStops(secureStops);
@@ -1237,7 +1237,7 @@
return NULL;
}
- List<Vector<uint8_t> > secureStopIds;
+ List<Vector<uint8_t>> secureStopIds;
status_t err = drm->getSecureStopIds(secureStopIds);
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 61c28ed..67005be 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -790,40 +790,6 @@
return (jint)mp->getState();
}
-static jint
-android_media_MediaPlayer2_getVideoWidth(JNIEnv *env, jobject thiz)
-{
- sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return 0;
- }
- int w;
- if (0 != mp->getVideoWidth(&w)) {
- ALOGE("getVideoWidth failed");
- w = 0;
- }
- ALOGV("getVideoWidth: %d", w);
- return (jint) w;
-}
-
-static jint
-android_media_MediaPlayer2_getVideoHeight(JNIEnv *env, jobject thiz)
-{
- sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return 0;
- }
- int h;
- if (0 != mp->getVideoHeight(&h)) {
- ALOGE("getVideoHeight failed");
- h = 0;
- }
- ALOGV("getVideoHeight: %d", h);
- return (jint) h;
-}
-
static jobject
android_media_MediaPlayer2_native_getMetrics(JNIEnv *env, jobject thiz)
{
@@ -893,20 +859,6 @@
process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
}
-static jint
-android_media_MediaPlayer2_getAudioStreamType(JNIEnv *env, jobject thiz)
-{
- sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return 0;
- }
- audio_stream_type_t streamtype;
- process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL );
- ALOGV("getAudioStreamType: %d (streamtype)", streamtype);
- return (jint) streamtype;
-}
-
static jboolean
android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
{
@@ -1372,15 +1324,30 @@
return mp->getRoutedDeviceId();
}
-static void android_media_MediaPlayer2_enableDeviceCallback(
- JNIEnv* env, jobject thiz, jboolean enabled)
+static void android_media_MediaPlayer2_addDeviceCallback(
+ JNIEnv* env, jobject thiz, jobject routingDelegate)
{
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
if (mp == NULL) {
return;
}
- status_t status = mp->enableAudioDeviceCallback(enabled);
+ status_t status = mp->addAudioDeviceCallback(routingDelegate);
+ if (status != NO_ERROR) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ ALOGE("enable device callback failed: %d", status);
+ }
+}
+
+static void android_media_MediaPlayer2_removeDeviceCallback(
+ JNIEnv* env, jobject thiz, jobject listener)
+{
+ sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL) {
+ return;
+ }
+
+ status_t status = mp->removeAudioDeviceCallback(listener);
if (status != NO_ERROR) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
ALOGE("enable device callback failed: %d", status);
@@ -1467,14 +1434,12 @@
(void *)android_media_MediaPlayer2_handleDataSourceCallback
},
{"nativePlayNextDataSource", "(J)V", (void *)android_media_MediaPlayer2_playNextDataSource},
- {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer2_setVideoSurface},
+ {"native_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer2_setVideoSurface},
{"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams},
{"_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
{"_prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
{"_start", "()V", (void *)android_media_MediaPlayer2_start},
{"native_getState", "()I", (void *)android_media_MediaPlayer2_getState},
- {"getVideoWidth", "()I", (void *)android_media_MediaPlayer2_getVideoWidth},
- {"getVideoHeight", "()I", (void *)android_media_MediaPlayer2_getVideoHeight},
{"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
{"_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
{"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},
@@ -1487,13 +1452,12 @@
{"getDuration", "()J", (void *)android_media_MediaPlayer2_getDuration},
{"_release", "()V", (void *)android_media_MediaPlayer2_release},
{"_reset", "()V", (void *)android_media_MediaPlayer2_reset},
- {"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer2_getAudioStreamType},
{"setParameter", "(ILjava/lang/Object;)Z", (void *)android_media_MediaPlayer2_setParameter},
{"getParameter", "(I)Ljava/lang/Object;", (void *)android_media_MediaPlayer2_getParameter},
{"setLooping", "(Z)V", (void *)android_media_MediaPlayer2_setLooping},
{"isLooping", "()Z", (void *)android_media_MediaPlayer2_isLooping},
- {"_setVolume", "(F)V", (void *)android_media_MediaPlayer2_setVolume},
- {"_invoke", "([B)[B", (void *)android_media_MediaPlayer2_invoke},
+ {"native_setVolume", "(F)V", (void *)android_media_MediaPlayer2_setVolume},
+ {"native_invoke", "([B)[B", (void *)android_media_MediaPlayer2_invoke},
{"native_init", "()V", (void *)android_media_MediaPlayer2_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer2_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer2_native_finalize},
@@ -1508,7 +1472,9 @@
// AudioRouting
{"native_setOutputDevice", "(I)Z", (void *)android_media_MediaPlayer2_setOutputDevice},
{"native_getRoutedDeviceId", "()I", (void *)android_media_MediaPlayer2_getRoutedDeviceId},
- {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaPlayer2_enableDeviceCallback},
+ {"native_addDeviceCallback", "(Landroid/media/RoutingDelegate;)V", (void *)android_media_MediaPlayer2_addDeviceCallback},
+ {"native_removeDeviceCallback", "(Landroid/media/AudioRouting$OnRoutingChangedListener;)V",
+ (void *)android_media_MediaPlayer2_removeDeviceCallback},
// StreamEventCallback for JAudioTrack
{"native_stream_event_onTearDown", "(JJ)V", (void *)android_media_MediaPlayer2_native_on_tear_down},
diff --git a/media/native/midi/midi.cpp b/media/native/midi/midi.cpp
index 78ca0ab..a5bdba8 100644
--- a/media/native/midi/midi.cpp
+++ b/media/native/midi/midi.cpp
@@ -338,7 +338,8 @@
numMessageBytes = std::min(maxBytes, numMessageBytes);
memcpy(buffer, readBuffer + 1, numMessageBytes);
if (timestampPtr != nullptr) {
- *timestampPtr = *(uint64_t*)(readBuffer + readCount - sizeof(uint64_t));
+ memcpy(timestampPtr, readBuffer + readCount - sizeof(uint64_t),
+ sizeof(*timestampPtr));
}
}
*numBytesReceivedPtr = numMessageBytes;
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 1b1bf8d..8f13497 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -30,7 +30,7 @@
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
- "android.car.user",
+ "android.car.userlib",
"androidx.car_car",
"androidx.legacy_legacy-support-v4",
"androidx.recyclerview_recyclerview",
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index ddc00e3..1136684 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -236,13 +236,13 @@
@NonNull ArrayList<CharSequence> smartReplies) {
Bundle signals = new Bundle();
+ if (!smartActions.isEmpty()) {
+ signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
+ }
+ if (!smartReplies.isEmpty()) {
+ signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
+ }
if (AUTO_DEMOTE_NOTIFICATIONS) {
- if (!smartActions.isEmpty()) {
- signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
- }
- if (!smartReplies.isEmpty()) {
- signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
- }
if (mNotificationCategorizer.shouldSilence(entry)) {
final int importance = entry.getImportance() < IMPORTANCE_LOW
? entry.getImportance() : IMPORTANCE_LOW;
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
index 8fee822..6f437bd5 100644
--- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
@@ -15,6 +15,7 @@
*/
package android.ext.services.notification;
+import static android.app.Notification.CATEGORY_MESSAGE;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -148,6 +149,18 @@
return Objects.equals(getNotification().category, category);
}
+ /**
+ * Similar to {@link #isCategory(String)}, but checking the public version of the notification,
+ * if available.
+ */
+ public boolean isPublicVersionCategory(String category) {
+ Notification publicVersion = getNotification().publicVersion;
+ if (publicVersion == null) {
+ return false;
+ }
+ return Objects.equals(publicVersion.category, category);
+ }
+
public boolean isAudioAttributesUsage(int usage) {
return mAttributes != null && mAttributes.getUsage() == usage;
}
@@ -175,9 +188,9 @@
}
protected boolean isMessaging() {
- return isCategory(Notification.CATEGORY_MESSAGE)
- || hasStyle(Notification.MessagingStyle.class)
- || hasInlineReply();
+ return isCategory(CATEGORY_MESSAGE)
+ || isPublicVersionCategory(CATEGORY_MESSAGE)
+ || hasStyle(Notification.MessagingStyle.class);
}
public boolean hasInlineReply() {
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 37a98fd..b2fc417 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -19,23 +19,22 @@
import android.annotation.Nullable;
import android.app.Notification;
import android.app.RemoteAction;
-import android.app.RemoteInput;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.Process;
-import android.os.SystemProperties;
-import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.view.textclassifier.ConversationActions;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
public class SmartActionsHelper {
private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>();
@@ -50,12 +49,18 @@
private static final int MAX_ACTION_EXTRACTION_TEXT_LENGTH = 400;
private static final int MAX_ACTIONS_PER_LINK = 1;
private static final int MAX_SMART_ACTIONS = Notification.MAX_ACTION_BUTTONS;
- // Allow us to test out smart reply with dumb suggestions, it is disabled by default.
- // TODO: Removed this once we have the model.
- private static final String SYS_PROP_SMART_REPLIES_EXPERIMENT =
- "persist.sys.smart_replies_experiment";
+ private static final int MAX_SUGGESTED_REPLIES = 3;
- SmartActionsHelper() {}
+ private static final ConversationActions.TypeConfig TYPE_CONFIG =
+ new ConversationActions.TypeConfig.Builder().setIncludedTypes(
+ Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+ .includeTypesFromTextClassifier(false)
+ .build();
+ private static final List<String> HINTS =
+ Collections.singletonList(ConversationActions.HINT_FOR_NOTIFICATION);
+
+ SmartActionsHelper() {
+ }
/**
* Adds action adjustments based on the notification contents.
@@ -92,8 +97,31 @@
if (context == null) {
return EMPTY_REPLY_LIST;
}
- // TODO: replaced this with our model when it is ready.
- return new ArrayList<>(Arrays.asList("Yes, please", "No, thanks"));
+ TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
+ if (tcm == null) {
+ return EMPTY_REPLY_LIST;
+ }
+ CharSequence text = getMostSalientActionText(entry.getNotification());
+ ConversationActions.Message message =
+ new ConversationActions.Message.Builder()
+ .setText(text)
+ .build();
+
+ ConversationActions.Request request =
+ new ConversationActions.Request.Builder(Collections.singletonList(message))
+ .setMaxSuggestions(MAX_SUGGESTED_REPLIES)
+ .setHints(HINTS)
+ .setTypeConfig(TYPE_CONFIG)
+ .build();
+
+ TextClassifier textClassifier = tcm.getTextClassifier();
+ List<ConversationActions.ConversationAction> conversationActions =
+ textClassifier.suggestConversationActions(request).getConversationActions();
+
+ return conversationActions.stream()
+ .map(conversationAction -> conversationAction.getTextReply())
+ .filter(textReply -> !TextUtils.isEmpty(textReply))
+ .collect(Collectors.toCollection(ArrayList::new));
}
/**
@@ -124,20 +152,30 @@
}
private boolean isEligibleForReplyAdjustment(@NonNull NotificationEntry entry) {
- if (!SystemProperties.getBoolean(SYS_PROP_SMART_REPLIES_EXPERIMENT, false)) {
+ if (!Process.myUserHandle().equals(entry.getSbn().getUser())) {
return false;
}
- Notification notification = entry.getNotification();
- if (notification.actions == null) {
+ String pkg = entry.getSbn().getPackageName();
+ if (TextUtils.isEmpty(pkg) || pkg.equals("android")) {
return false;
}
- return entry.hasInlineReply();
+ // For now, we are only interested in messages.
+ if (!entry.isMessaging()) {
+ return false;
+ }
+ // Does not make sense to provide suggested replies if it is not something that can be
+ // replied.
+ if (!entry.hasInlineReply()) {
+ return false;
+ }
+ return true;
}
/** Returns the text most salient for action extraction in a notification. */
@Nullable
private CharSequence getMostSalientActionText(@NonNull Notification notification) {
/* If it's messaging style, use the most recent message. */
+ // TODO: Use the last few X messages instead and take the Person object into consideration.
Parcelable[] messages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES);
if (messages != null && messages.length != 0) {
Bundle lastMessage = (Bundle) messages[messages.length - 1];
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
index 1eb423e..74c7b58 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.provider.Settings;
import android.util.Log;
/**
@@ -29,11 +30,11 @@
private static final String TAG = PackageInstalledReceiver.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final boolean APP_INSTALLED_NOTIFICATION_ENABLED = false;
@Override
public void onReceive(Context context, Intent intent) {
- if (!APP_INSTALLED_NOTIFICATION_ENABLED) {
+ if (Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, 0) == 0) {
return;
}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 508adbd..e2a34f4 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -21,35 +21,47 @@
<!-- Toast message when Wi-Fi cannot scan for networks -->
<string name="wifi_fail_to_scan">Can\'t scan for networks</string>
<!-- Do not translate. Concise terminology for wifi with WEP security -->
- <string name="wifi_security_short_wep">WEP</string>
+ <string name="wifi_security_short_wep" translatable="false">WEP</string>
<!-- Do not translate. Concise terminology for wifi with WPA security -->
- <string name="wifi_security_short_wpa">WPA</string>
+ <string name="wifi_security_short_wpa" translatable="false">WPA</string>
<!-- Do not translate. Concise terminology for wifi with WPA2 security -->
- <string name="wifi_security_short_wpa2">WPA2</string>
+ <string name="wifi_security_short_wpa2" translatable="false">WPA2</string>
<!-- Do not translate. Concise terminology for wifi with both WPA/WPA2 security -->
- <string name="wifi_security_short_wpa_wpa2">WPA/WPA2</string>
+ <string name="wifi_security_short_wpa_wpa2" translatable="false">WPA/WPA2</string>
<!-- Do not translate. Concise terminology for wifi with unknown PSK type -->
- <string name="wifi_security_short_psk_generic">@string/wifi_security_short_wpa_wpa2</string>
+ <string name="wifi_security_short_psk_generic" translatable="false">@string/wifi_security_short_wpa_wpa2</string>
<!-- Do not translate. Concise terminology for wifi with 802.1x EAP security -->
- <string name="wifi_security_short_eap">802.1x</string>
+ <string name="wifi_security_short_eap" translatable="false">802.1x</string>
+ <!-- Do not translate. Concise terminology for wifi with WPA3 security -->
+ <string name="wifi_security_short_sae" translatable="false">WPA3</string>
+ <!-- Do not translate. Concise terminology for wifi with OWE security -->
+ <string name="wifi_security_short_owe" translatable="false">OWE</string>
+ <!-- Do not translate. Concise terminology for wifi with 802.1x EAP Suite-B security -->
+ <string name="wifi_security_short_eap_suiteb" translatable="false">Suite-B</string>
<!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. -->
- <string name="wifi_security_none">None</string>
+ <string name="wifi_security_none" translatable="false">None</string>
<!-- Do not translate. Terminology for wifi with WEP security -->
- <string name="wifi_security_wep">WEP</string>
+ <string name="wifi_security_wep" translatable="false">WEP</string>
<!-- Do not translate. Terminology for wifi with WPA security -->
- <string name="wifi_security_wpa">WPA PSK</string>
+ <string name="wifi_security_wpa" translatable="false">WPA-Personal</string>
<!-- Do not translate. Terminology for wifi with WPA2 security -->
- <string name="wifi_security_wpa2">WPA2 PSK</string>
+ <string name="wifi_security_wpa2" translatable="false">WPA2-Personal</string>
<!-- Do not translate. Terminology for wifi with both WPA/WPA2 security, or unknown -->
- <string name="wifi_security_wpa_wpa2">WPA/WPA2 PSK</string>
+ <string name="wifi_security_wpa_wpa2" translatable="false">WPA/WPA2-Personal</string>
<!-- Do not translate. Terminology for wifi with unknown PSK type -->
- <string name="wifi_security_psk_generic">@string/wifi_security_wpa_wpa2</string>
+ <string name="wifi_security_psk_generic" translatable="false">@string/wifi_security_wpa_wpa2</string>
<!-- Do not translate. Concise terminology for wifi with 802.1x EAP security -->
- <string name="wifi_security_eap">802.1x EAP</string>
+ <string name="wifi_security_eap" translatable="false">WPA/WPA2-Enterprise</string>
<!-- Do not translate. Concise terminology for Passpoint network -->
- <string name="wifi_security_passpoint">Passpoint</string>
+ <string name="wifi_security_passpoint" translatable="false">Passpoint</string>
+ <!-- Do not translate. Terminology for wifi with WPA3 security -->
+ <string name="wifi_security_sae" translatable="false">WPA3-Personal</string>
+ <!-- Do not translate. Terminology for wifi with OWE security -->
+ <string name="wifi_security_owe" translatable="false">Enhanced Open</string>
+ <!-- Do not translate. Concise terminology for wifi with 802.1x EAP Suite-B security -->
+ <string name="wifi_security_eap_suiteb" translatable="false">WPA3-Enterprise</string>
<!-- Summary for the remembered network. -->
<string name="wifi_remembered">Saved</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index e1f9111..69c267e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -65,6 +65,15 @@
}
}
+ /**
+ * Logs a generic Settings event.
+ */
+ public void action(int attribution, int action, int pageId, String key, int value) {
+ for (LogWriter writer : mLoggerWriters) {
+ writer.action(attribution, action, pageId, key, value);
+ }
+ }
+
public void action(Context context, int category, int value) {
for (LogWriter writer : mLoggerWriters) {
writer.action(context, category, value);
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
index a28e45c..71f3789 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -116,8 +116,6 @@
mPreferenceKeySet.add(prefKey);
return;
}
- // TODO: Remove count logging to save some resource.
- mMetricsFeature.count(mContext, buildCountName(prefKey, value), 1);
final Pair<Integer, Object> valueData;
if (value instanceof Long) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index dd8bfda..92fd868 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -51,6 +51,8 @@
public static final String CATEGORY_GESTURES = "com.android.settings.category.ia.gestures";
public static final String CATEGORY_NIGHT_DISPLAY =
"com.android.settings.category.ia.night_display";
+ public static final String CATEGORY_PRIVACY =
+ "com.android.settings.category.ia.privacy";
public static final Map<String, String> KEY_COMPAT_MAP;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index e950e8e..523361d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -158,9 +158,12 @@
* These values are matched in string arrays -- changes must be kept in sync
*/
public static final int SECURITY_NONE = 0;
- public static final int SECURITY_WEP = 1;
- public static final int SECURITY_PSK = 2;
- public static final int SECURITY_EAP = 3;
+ public static final int SECURITY_OWE = 1;
+ public static final int SECURITY_WEP = 2;
+ public static final int SECURITY_PSK = 3;
+ public static final int SECURITY_SAE = 4;
+ public static final int SECURITY_EAP = 5;
+ public static final int SECURITY_EAP_SUITE_B = 6;
private static final int PSK_UNKNOWN = 0;
private static final int PSK_WPA = 1;
@@ -433,7 +436,7 @@
if (isConnectable()) {
builder.append(',').append("connectable");
}
- if (security != SECURITY_NONE) {
+ if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
builder.append(',').append(securityToString(security, pskType));
}
builder.append(",level=").append(getLevel());
@@ -720,6 +723,9 @@
case SECURITY_EAP:
return concise ? context.getString(R.string.wifi_security_short_eap) :
context.getString(R.string.wifi_security_eap);
+ case SECURITY_EAP_SUITE_B:
+ return concise ? context.getString(R.string.wifi_security_short_eap_suiteb) :
+ context.getString(R.string.wifi_security_eap_suiteb);
case SECURITY_PSK:
switch (pskType) {
case PSK_WPA:
@@ -739,6 +745,12 @@
case SECURITY_WEP:
return concise ? context.getString(R.string.wifi_security_short_wep) :
context.getString(R.string.wifi_security_wep);
+ case SECURITY_SAE:
+ return concise ? context.getString(R.string.wifi_security_short_sae) :
+ context.getString(R.string.wifi_security_sae);
+ case SECURITY_OWE:
+ return concise ? context.getString(R.string.wifi_security_short_owe) :
+ context.getString(R.string.wifi_security_owe);
case SECURITY_NONE:
default:
return concise ? "" : context.getString(R.string.wifi_security_none);
@@ -980,13 +992,20 @@
* Can only be called for unsecured networks.
*/
public void generateOpenNetworkConfig() {
- if (security != SECURITY_NONE)
+ if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
throw new IllegalStateException();
+ }
if (mConfig != null)
return;
mConfig = new WifiConfiguration();
mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
- mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+
+ if (security == SECURITY_NONE) {
+ mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+ } else {
+ mConfig.allowedKeyManagement.set(KeyMgmt.OWE);
+ mConfig.requirePMF = true;
+ }
}
public void saveWifiState(Bundle savedState) {
@@ -1288,22 +1307,38 @@
private static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
+ } else if (result.capabilities.contains("SAE")) {
+ return SECURITY_SAE;
} else if (result.capabilities.contains("PSK")) {
return SECURITY_PSK;
+ } else if (result.capabilities.contains("EAP_SUITE_B_192")) {
+ return SECURITY_EAP_SUITE_B;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
+ } else if (result.capabilities.contains("OWE")) {
+ return SECURITY_OWE;
}
+
return SECURITY_NONE;
}
static int getSecurity(WifiConfiguration config) {
+ if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
+ return SECURITY_SAE;
+ }
if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
+ if (config.allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+ return SECURITY_EAP_SUITE_B;
+ }
if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
+ if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
+ return SECURITY_OWE;
+ }
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
@@ -1321,6 +1356,12 @@
return "PSK";
} else if (security == SECURITY_EAP) {
return "EAP";
+ } else if (security == SECURITY_SAE) {
+ return "SAE";
+ } else if (security == SECURITY_EAP_SUITE_B) {
+ return "SUITE_B";
+ } else if (security == SECURITY_OWE) {
+ return "OWE";
}
return "NONE";
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index f3c43cc..db364a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -200,7 +200,8 @@
if (frictionImageView == null || mFrictionSld == null) {
return;
}
- if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
+ if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE)
+ && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) {
mFrictionSld.setState(STATE_SECURED);
} else if (mAccessPoint.isMetered()) {
mFrictionSld.setState(STATE_METERED);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 2d43762..f1295e03 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -481,6 +481,9 @@
dumpSetting(s, p,
Settings.Global.EMULATE_DISPLAY_CUTOUT,
GlobalSettingsProto.Development.EMULATE_DISPLAY_CUTOUT);
+ dumpSetting(s, p,
+ Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
+ GlobalSettingsProto.Development.FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS);
p.end(developmentToken);
final long deviceToken = p.start(GlobalSettingsProto.DEVICE);
@@ -1120,6 +1123,9 @@
dumpSetting(s, p,
Settings.Global.SHOW_FIRST_CRASH_DIALOG,
GlobalSettingsProto.SHOW_FIRST_CRASH_DIALOG);
+ dumpSetting(s, p,
+ Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED,
+ GlobalSettingsProto.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED);
// Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated.
dumpSetting(s, p,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
@@ -1127,6 +1133,9 @@
dumpSetting(s, p,
Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
GlobalSettingsProto.SHOW_MUTE_IN_CRASH_DIALOG);
+ dumpSetting(s, p,
+ Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED,
+ GlobalSettingsProto.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED);
final long smartSelectToken = p.start(GlobalSettingsProto.SMART_SELECTION);
dumpSetting(s, p,
@@ -1637,11 +1646,11 @@
Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
SecureSettingsProto.Accessibility.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED,
- SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_ENABLED);
+ Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
+ SecureSettingsProto.Accessibility.NON_INTERACTIVE_UI_TIMEOUT_MS);
dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS,
- SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_MS);
+ Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
+ SecureSettingsProto.Accessibility.INTERACTIVE_UI_TIMEOUT_MS);
p.end(accessibilityToken);
dumpSetting(s, p,
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index b770d5c..a00baad 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -66,7 +66,7 @@
libs: [
"telephony-common",
"android.car",
- "android.car.user",
+ "android.car.userlib",
],
aaptflags: [
@@ -120,7 +120,7 @@
"android.test.runner",
"telephony-common",
"android.car",
- "android.car.user",
+ "android.car.userlib",
"android.test.base",
],
aaptflags: [
@@ -146,7 +146,7 @@
libs: [
"telephony-common",
"android.car",
- "android.car.user",
+ "android.car.userlib",
],
dxflags: ["--multi-dex"],
@@ -183,7 +183,7 @@
libs: [
"telephony-common",
"android.car",
- "android.car.user",
+ "android.car.userlib",
],
srcs: [
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
index 0d758df..dfa38ba 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
@@ -497,7 +497,7 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mSystemInsets.set(insets.getSystemWindowInsets());
+ mSystemInsets.set(insets.getSystemWindowInsetsAsRect());
mTaskStackView.setSystemInsets(mSystemInsets);
requestLayout();
return insets;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index b4fc820..887ea59 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -13,11 +13,11 @@
*/
package com.android.systemui.plugins;
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
import android.graphics.Paint.Style;
import android.view.View;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
/**
* This plugin is used to replace main clock in keyguard.
*/
@@ -44,4 +44,9 @@
* @param color A color value.
*/
void setTextColor(int color);
+
+ /**
+ * Notifies that time tick alarm from doze service fired.
+ */
+ default void dozeTimeTick() { }
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
new file mode 100644
index 0000000..dce02e1
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Used to capture Falsing data (related to unlocking the screen).
+ *
+ * The intent is that the data can later be analyzed to validate the quality of the
+ * {@link com.android.systemui.classifier.FalsingManager}.
+ */
+@ProvidesInterface(action = FalsingPlugin.ACTION, version = FalsingPlugin.VERSION)
+public interface FalsingPlugin extends Plugin {
+ String ACTION = "com.android.systemui.action.FALSING_PLUGIN";
+ int VERSION = 1;
+
+ /**
+ * Called when there is data to be recorded.
+ *
+ * @param success Indicates whether the action is considered a success.
+ * @param data The raw data to be recorded for analysis.
+ */
+ void dataCollected(boolean success, byte[] data);
+}
diff --git a/packages/SystemUI/res/drawable/biometric_dialog_bg.xml b/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
index d4dfdee..d041556 100644
--- a/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
+++ b/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
@@ -21,6 +21,6 @@
<corners android:radius="1dp"
android:topLeftRadius="@dimen/biometric_dialog_corner_size"
android:topRightRadius="@dimen/biometric_dialog_corner_size"
- android:bottomLeftRadius="0dp"
- android:bottomRightRadius="0dp"/>
+ android:bottomLeftRadius="@dimen/biometric_dialog_corner_size"
+ android:bottomRightRadius="@dimen/biometric_dialog_corner_size"/>
</shape>
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index ec25e31..67c0adf 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -31,7 +31,8 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
<!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
on horizontal/portrait orientation -->
@@ -43,11 +44,13 @@
<LinearLayout
android:id="@+id/dialog"
- android:layout_width="0dp"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:elevation="2dp"
- android:background="@drawable/biometric_dialog_bg">
+ android:background="@drawable/biometric_dialog_bg"
+ android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
+ android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
+ android:layout_marginRight="@dimen/biometric_dialog_border_padding">
<TextView
android:id="@+id/title"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index f138685..c86ebe7 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -152,6 +152,13 @@
android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button" />
<TextView
+ android:id="@+id/toggle_silent"
+ android:text="@string/inline_silent_button_silent"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+ style="@style/TextAppearance.NotificationInfo.Button" />
+ <TextView
android:id="@+id/keep"
android:minWidth="48dp"
android:text="@string/inline_keep_button"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c61b1d2..d8648fa 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -147,7 +147,7 @@
<!-- The number of milliseconds before the ambient notification auto-dismisses. This will
override the default pulse length. -->
- <integer name="ambient_notification_decay">6000</integer>
+ <integer name="ambient_notification_decay">10000</integer>
<!-- Minimum display time for a heads up notification, in milliseconds. -->
<integer name="ambient_notification_minimum_time">2000</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 525421a..3050e79 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -889,6 +889,7 @@
<dimen name="biometric_dialog_biometric_icon_size">64dp</dimen>
<dimen name="biometric_dialog_corner_size">4dp</dimen>
<dimen name="biometric_dialog_animation_translation_offset">350dp</dimen>
+ <dimen name="biometric_dialog_border_padding">4dp</dimen>
<!-- Wireless Charging Animation values -->
<dimen name="wireless_charging_dots_radius_start">0dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7d09c00..50454fc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1540,6 +1540,12 @@
<!-- Notification inline controls: Shown when a channel's notifications are minimized -->
<string name="notification_channel_minimized">These notifications will be minimized</string>
+ <!-- Notification inline controls: Shown when a channel's notifications are silenced [CHAR_LIMIT=100] -->
+ <string name="notification_channel_silenced">These notifications will be shown silently</string>
+
+ <!-- Notification inline controls: Shown when a channel's notifications are set to alert [CHAR_LIMIT=100] -->
+ <string name="notification_channel_unsilenced">These notifications will alert you</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
<string name="inline_blocking_helper">You usually dismiss these notifications.
\nKeep showing them?</string>
@@ -1556,6 +1562,12 @@
<!-- Notification inline controls: minimize notifications button -->
<string name="inline_minimize_button">Minimize</string>
+ <!-- Notification inline controls: show notifications silently button [CHAR_LIMIT=25] -->
+ <string name="inline_silent_button_silent">Show silently</string>
+
+ <!-- Notification inline controls: show and alert button [CHAR_LIMIT=25] -->
+ <string name="inline_silent_button_alert">Show and alert</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, app level -->
<string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
@@ -2131,7 +2143,7 @@
<string name="app_info">App info</string>
<!-- Action label for switching to a browser for an instant app [CHAR LIMIT=20] -->
- <string name="go_to_web">Go to web</string>
+ <string name="go_to_web">Go to browser</string>
<!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
<string name="mobile_data">Mobile data</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 013745a..8881f8a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -143,6 +143,15 @@
}
/**
+ * Notifies that time tick alarm from doze service fired.
+ */
+ public void dozeTimeTick() {
+ if (mClockPlugin != null) {
+ mClockPlugin.dozeTimeTick();
+ }
+ }
+
+ /**
* When plugin changes, set all kept parameters into newer plugin.
*/
private void initPluginParams() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 2bc0e45c..e051317 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -15,54 +15,164 @@
*/
package com.android.keyguard;
-import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Display.DEFAULT_DISPLAY;
+import android.annotation.Nullable;
import android.app.Presentation;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
import android.graphics.Point;
+import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.os.Bundle;
-import android.util.Slog;
+import android.util.Log;
+import android.util.SparseArray;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
+import java.util.function.BooleanSupplier;
+
// TODO(multi-display): Support multiple external displays
public class KeyguardDisplayManager {
protected static final String TAG = "KeyguardDisplayManager";
private static boolean DEBUG = KeyguardConstants.DEBUG;
private final ViewMediatorCallback mCallback;
+
private final MediaRouter mMediaRouter;
+ private final DisplayManager mDisplayService;
private final Context mContext;
- Presentation mPresentation;
private boolean mShowing;
+ private final SparseArray<Presentation> mPresentations = new SparseArray<>();
+
+ private final DisplayManager.DisplayListener mDisplayListener =
+ new DisplayManager.DisplayListener() {
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ final Display display = mDisplayService.getDisplay(displayId);
+ if (mShowing) {
+ notifyIfChanged(() -> showPresentation(display));
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == DEFAULT_DISPLAY) return;
+ final Display display = mDisplayService.getDisplay(displayId);
+ if (display != null && mShowing) {
+ final Presentation presentation = mPresentations.get(displayId);
+ if (presentation != null && !presentation.getDisplay().equals(display)) {
+ hidePresentation(displayId);
+ showPresentation(display);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ notifyIfChanged(() -> hidePresentation(displayId));
+ }
+ };
+
public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) {
mContext = context;
mCallback = callback;
- mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ mMediaRouter = mContext.getSystemService(MediaRouter.class);
+ mDisplayService = mContext.getSystemService(DisplayManager.class);
+ mDisplayService.registerDisplayListener(mDisplayListener, null /* handler */);
+ }
+
+ /**
+ * @param display The display to show the presentation on.
+ * @return {@code true} if a presentation was added.
+ * {@code false} if the presentation cannot be added on that display or the presentation
+ * was already there.
+ */
+ private boolean showPresentation(Display display) {
+ if (display == null || display.getDisplayId() == DEFAULT_DISPLAY) return false;
+ if (DEBUG) Log.i(TAG, "Keyguard enabled on display: " + display);
+ final int displayId = display.getDisplayId();
+ Presentation presentation = mPresentations.get(displayId);
+ if (presentation == null) {
+ presentation = new KeyguardPresentation(mContext, display);
+ presentation.setOnDismissListener(dialog -> {
+ if (null != mPresentations.get(displayId)) {
+ mPresentations.remove(displayId);
+ }
+ });
+ try {
+ presentation.show();
+ } catch (WindowManager.InvalidDisplayException ex) {
+ Log.w(TAG, "Invalid display:", ex);
+ presentation = null;
+ }
+ if (presentation != null) {
+ mPresentations.append(displayId, presentation);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param displayId The id of the display to hide the presentation off.
+ * @return {@code true} if the a presentation was removed.
+ * {@code false} if the presentation was not added before.
+ */
+ private boolean hidePresentation(int displayId) {
+ final Presentation presentation = mPresentations.get(displayId);
+ if (presentation != null) {
+ presentation.dismiss();
+ mPresentations.remove(displayId);
+ return true;
+ }
+ return false;
+ }
+
+ private void notifyIfChanged(BooleanSupplier updateMethod) {
+ if (updateMethod.getAsBoolean()) {
+ final int[] displayList = getPresentationDisplayIds();
+ mCallback.onSecondaryDisplayShowingChanged(displayList);
+ }
+ }
+
+ /**
+ * @return An array of displayId's on which a {@link KeyguardPresentation} is showing on.
+ */
+ @Nullable
+ private int[] getPresentationDisplayIds() {
+ final int size = mPresentations.size();
+ if (size == 0) return null;
+
+ final int[] displayIds = new int[size];
+ for (int i = mPresentations.size() - 1; i >= 0; i--) {
+ final Presentation presentation = mPresentations.valueAt(i);
+ if (presentation != null) {
+ displayIds[i] = presentation.getDisplay().getDisplayId();
+ }
+ }
+ return displayIds;
}
public void show() {
if (!mShowing) {
- if (DEBUG) Slog.v(TAG, "show");
+ if (DEBUG) Log.v(TAG, "show");
mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
- updateDisplays(true);
+ notifyIfChanged(() -> updateDisplays(true /* showing */));
}
mShowing = true;
}
public void hide() {
if (mShowing) {
- if (DEBUG) Slog.v(TAG, "hide");
+ if (DEBUG) Log.v(TAG, "hide");
mMediaRouter.removeCallback(mMediaRouterCallback);
- updateDisplays(false);
+ notifyIfChanged(() -> updateDisplays(false /* showing */));
}
mShowing = false;
}
@@ -71,71 +181,38 @@
new MediaRouter.SimpleCallback() {
@Override
public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
- if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
- updateDisplays(mShowing);
+ if (DEBUG) Log.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
+ notifyIfChanged(() -> updateDisplays(mShowing));
}
@Override
public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
- if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
- updateDisplays(mShowing);
+ if (DEBUG) Log.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
+ notifyIfChanged(() -> updateDisplays(mShowing));
}
@Override
public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
- if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
- updateDisplays(mShowing);
+ if (DEBUG) Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
+ notifyIfChanged(() -> updateDisplays(mShowing));
}
};
- private OnDismissListener mOnDismissListener = new OnDismissListener() {
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- mPresentation = null;
- }
- };
-
- protected void updateDisplays(boolean showing) {
- Presentation originalPresentation = mPresentation;
+ protected boolean updateDisplays(boolean showing) {
+ boolean changed = false;
if (showing) {
- MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
- MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
- boolean useDisplay = route != null
- && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
- Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null;
-
- if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
- if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay());
- mPresentation.dismiss();
- mPresentation = null;
- }
-
- if (mPresentation == null && presentationDisplay != null) {
- if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay);
- mPresentation = new KeyguardPresentation(mContext, presentationDisplay,
- R.style.keyguard_presentation_theme);
- mPresentation.setOnDismissListener(mOnDismissListener);
- try {
- mPresentation.show();
- } catch (WindowManager.InvalidDisplayException ex) {
- Slog.w(TAG, "Invalid display:", ex);
- mPresentation = null;
- }
+ final Display[] displays = mDisplayService.getDisplays();
+ for (Display display : displays) {
+ changed |= showPresentation(display);
}
} else {
- if (mPresentation != null) {
- mPresentation.dismiss();
- mPresentation = null;
+ changed = mPresentations.size() > 0;
+ for (int i = mPresentations.size() - 1; i >= 0; i--) {
+ mPresentations.valueAt(i).dismiss();
}
+ mPresentations.clear();
}
-
- // mPresentation is only updated when the display changes
- if (mPresentation != originalPresentation) {
- final int displayId = mPresentation != null
- ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY;
- mCallback.onSecondaryDisplayShowingChanged(displayId);
- }
+ return changed;
}
private final static class KeyguardPresentation extends Presentation {
@@ -157,9 +234,10 @@
}
};
- public KeyguardPresentation(Context context, Display display, int theme) {
- super(context, display, theme);
+ KeyguardPresentation(Context context, Display display) {
+ super(context, display, R.style.keyguard_presentation_theme);
getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ setCancelable(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 50b98a1..79966f7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -17,6 +17,8 @@
package com.android.keyguard;
import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
@@ -80,6 +82,7 @@
private float mDarkAmount = 0;
private LiveData<Slice> mLiveData;
+ private int mDisplayId = INVALID_DISPLAY;
private int mIconSize;
/**
* Runnable called whenever the view contents change.
@@ -129,6 +132,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ mDisplayId = getDisplay().getDisplayId();
// Make sure we always have the most current slice
mLiveData.observeForever(this);
Dependency.get(ConfigurationController.class).addCallback(this);
@@ -138,7 +142,10 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mLiveData.removeObserver(this);
+ // TODO(b/117344873) Remove below work around after this issue be fixed.
+ if (mDisplayId == DEFAULT_DISPLAY) {
+ mLiveData.removeObserver(this);
+ }
Dependency.get(ConfigurationController.class).removeCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index a403b75..f701e22 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -47,7 +47,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
import com.google.android.collect.Sets;
@@ -276,6 +275,7 @@
public void dozeTimeTick() {
refreshTime();
mKeyguardSlice.refresh();
+ mClockView.dozeTimeTick();
}
private void refreshTime() {
diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
index 41b86a7..a07c5cb 100644
--- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
@@ -96,9 +96,9 @@
int getBouncerPromptReason();
/**
- * Invoked when the secondary display showing a keyguard window changes.
+ * Invoked when the secondary displays showing a keyguard window changes.
*/
- void onSecondaryDisplayShowingChanged(int displayId);
+ void onSecondaryDisplayShowingChanged(int[] displayId);
/**
* Consumes a message that was enqueued to be displayed on the next time the bouncer shows up.
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 3fe9944..e3584cf 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -33,10 +33,11 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
+
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
public class SwipeHelper implements Gefingerpoken {
static final String TAG = "com.android.systemui.SwipeHelper";
@@ -604,13 +605,15 @@
}
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
- if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
+ if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(mCurrView,
+ delta > 0)) {
float size = getSize(mCurrView);
float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
if (absDelta >= size) {
delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
} else {
- delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
+ delta = maxScrollDistance * (float) Math.sin(
+ (delta / size) * (Math.PI / 2));
}
}
@@ -674,9 +677,11 @@
}
public boolean isDismissGesture(MotionEvent ev) {
+ float translation = getTranslation(mCurrView);
return ev.getActionMasked() == MotionEvent.ACTION_UP
+ && !mFalsingManager.isUnlockingDisabled()
&& !isFalseGesture(ev) && (swipedFastEnough() || swipedFarEnough())
- && mCallback.canChildBeDismissed(mCurrView);
+ && mCallback.canChildBeDismissedInDirection(mCurrView, translation > 0);
}
public boolean isFalseGesture(MotionEvent ev) {
@@ -707,6 +712,16 @@
boolean canChildBeDismissed(View v);
+ /**
+ * Returns true if the provided child can be dismissed by a swipe in the given direction.
+ *
+ * @param isRightOrDown {@code true} if the swipe direction is right or down,
+ * {@code false} if it is left or up.
+ */
+ default boolean canChildBeDismissedInDirection(View v, boolean isRightOrDown) {
+ return canChildBeDismissed(v);
+ }
+
boolean isAntiFalsingNeeded();
void onBeginDrag(View v);
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
index 69e347c9..46e004c 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
@@ -16,6 +16,9 @@
package com.android.systemui.analytics;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
+
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.Sensor;
@@ -32,13 +35,15 @@
import android.view.MotionEvent;
import android.widget.Toast;
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.FalsingPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginManager;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-
/**
* Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
* the data containing these events is saved to a file. This data is collected
@@ -53,6 +58,8 @@
private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches";
private static final String ALLOW_REJECTED_TOUCH_REPORTS =
"data_collector_allow_rejected_touch_reports";
+ private static final String DISABLE_UNLOCKING_FOR_FALSING_COLLECTION =
+ "data_collector_disable_unlocking";
private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
public static final boolean DEBUG = false;
@@ -65,14 +72,16 @@
private SensorLoggerSession mCurrentSession = null;
private boolean mEnableCollector = false;
- private boolean mTimeoutActive = false;
private boolean mCollectBadTouches = false;
private boolean mCornerSwiping = false;
private boolean mTrackingStarted = false;
private boolean mAllowReportRejectedTouch = false;
+ private boolean mDisableUnlocking = false;
private static DataCollector sInstance = null;
+ private FalsingPlugin mFalsingPlugin = null;
+
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
@@ -80,6 +89,16 @@
}
};
+ private final PluginListener mPluginListener = new PluginListener<FalsingPlugin>() {
+ public void onPluginConnected(FalsingPlugin plugin, Context context) {
+ mFalsingPlugin = plugin;
+ }
+
+ public void onPluginDisconnected(FalsingPlugin plugin) {
+ mFalsingPlugin = null;
+ }
+ };
+
private DataCollector(Context context) {
mContext = context;
@@ -98,7 +117,14 @@
mSettingsObserver,
UserHandle.USER_ALL);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(DISABLE_UNLOCKING_FOR_FALSING_COLLECTION), false,
+ mSettingsObserver,
+ UserHandle.USER_ALL);
+
updateConfiguration();
+
+ Dependency.get(PluginManager.class).addPluginListener(mPluginListener, FalsingPlugin.class);
}
public static DataCollector getInstance(Context context) {
@@ -118,6 +144,9 @@
mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
mContext.getContentResolver(),
ALLOW_REJECTED_TOUCH_REPORTS, 0);
+ mDisableUnlocking = mEnableCollector && Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ DISABLE_UNLOCKING_FOR_FALSING_COLLECTION, 0);
}
private boolean sessionEntrypoint() {
@@ -144,7 +173,7 @@
SensorLoggerSession session = mCurrentSession;
mCurrentSession = null;
- if (mEnableCollector) {
+ if (mEnableCollector || mDisableUnlocking) {
session.end(System.currentTimeMillis(), result);
queueSession(session);
}
@@ -181,24 +210,28 @@
@Override
public void run() {
byte[] b = Session.toByteArray(currentSession.toProto());
- String dir = mContext.getFilesDir().getAbsolutePath();
- if (currentSession.getResult() != Session.SUCCESS) {
- if (!mCollectBadTouches) {
- return;
- }
- dir += "/bad_touches";
+
+ if (mFalsingPlugin != null) {
+ mFalsingPlugin.dataCollected(currentSession.getResult() == Session.SUCCESS, b);
} else {
- dir += "/good_touches";
- }
+ String dir = mContext.getFilesDir().getAbsolutePath();
+ if (currentSession.getResult() != Session.SUCCESS) {
+ if (!mDisableUnlocking && !mCollectBadTouches) {
+ return;
+ }
+ dir += "/bad_touches";
+ } else if (!mDisableUnlocking) {
+ dir += "/good_touches";
+ }
- File file = new File(dir);
- file.mkdir();
- File touch = new File(file, "trace_" + System.currentTimeMillis());
-
- try {
- new FileOutputStream(touch).write(b);
- } catch (IOException e) {
- throw new RuntimeException(e);
+ File file = new File(dir);
+ file.mkdir();
+ File touch = new File(file, "trace_" + System.currentTimeMillis());
+ try {
+ new FileOutputStream(touch).write(b);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
});
@@ -208,19 +241,6 @@
public synchronized void onSensorChanged(SensorEvent event) {
if (isEnabled() && mCurrentSession != null) {
mCurrentSession.addSensorEvent(event, System.nanoTime());
- enforceTimeout();
- }
- }
-
- private void enforceTimeout() {
- if (mTimeoutActive) {
- if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
- > TIMEOUT_MILLIS) {
- onSessionEnd(Session.UNKNOWN);
- if (DEBUG) {
- Log.i(TAG, "Analytics timed out.");
- }
- }
}
}
@@ -233,9 +253,12 @@
* rejected touch report.
*/
public boolean isEnabled() {
- return mEnableCollector || mAllowReportRejectedTouch;
+ return mEnableCollector || mAllowReportRejectedTouch || mDisableUnlocking;
}
+ public boolean isUnlockingDisabled() {
+ return mDisableUnlocking;
+ }
/**
* @return true if the full data set for data gathering should be collected - including
* extensive sensor data, which is is not normally included with rejected touch reports.
@@ -450,7 +473,6 @@
}
mCurrentSession.addMotionEvent(event);
mCurrentSession.setTouchArea(width, height);
- enforceTimeout();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
index d6472b7..d294012 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -16,17 +16,17 @@
package com.android.systemui.analytics;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
+
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import java.util.ArrayList;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
-
/**
* Collects touch, sensor and phone events and converts the data to
* TouchAnalyticsProto.Session.
@@ -104,6 +104,7 @@
proto.startTimestampMillis = mStartTimestampMillis;
proto.durationMillis = mEndTimestampMillis - mStartTimestampMillis;
proto.build = Build.FINGERPRINT;
+ proto.deviceId = Build.DEVICE;
proto.result = mResult;
proto.type = mType;
proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 7935115..1faae9d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -42,6 +42,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
/**
* Abstract base class. Shows a dialog for BiometricPrompt.
@@ -199,7 +200,10 @@
final Button negative = mLayout.findViewById(R.id.button2);
final Button positive = mLayout.findViewById(R.id.button1);
- mDialog.getLayoutParams().width = (int) mDialogWidth;
+ if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
+ mDialog.getLayoutParams().width = (int) mDialogWidth;
+ }
+
mLastState = STATE_NONE;
updateState(STATE_AUTHENTICATING);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 3d578c3..2c61da3 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -201,6 +201,9 @@
return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled();
}
+ public boolean isUnlockingDisabled() {
+ return mDataCollector.isUnlockingDisabled();
+ }
/**
* @return true if the classifier determined that this is not a human interacting with the phone
*/
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4988f07..fe1b356 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.telephony.IccCardConstants.State.ABSENT;
import static com.android.internal.telephony.IccCardConstants.State.PIN_REQUIRED;
@@ -95,6 +94,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* Mediates requests related to the keyguard. This includes queries about the
@@ -246,8 +246,8 @@
// AOD is enabled and status bar is in AOD state.
private boolean mAodShowing;
- // display id of the secondary display on which we have put a keyguard window
- private int mSecondaryDisplayShowing = INVALID_DISPLAY;
+ // display ids of the external display on which we have put a keyguard window
+ private int[] mSecondaryDisplaysShowing;
/** Cached value of #isInputRestricted */
private boolean mInputRestricted;
@@ -700,9 +700,9 @@
}
@Override
- public void onSecondaryDisplayShowingChanged(int displayId) {
+ public void onSecondaryDisplayShowingChanged(int[] displayIds) {
synchronized (KeyguardViewMediator.this) {
- setShowingLocked(mShowing, mAodShowing, displayId, false);
+ setShowingLocked(mShowing, mAodShowing, displayIds, false);
}
}
};
@@ -749,10 +749,10 @@
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()),
- mAodShowing, mSecondaryDisplayShowing, true /* forceCallbacks */);
+ mAodShowing, mSecondaryDisplaysShowing, true /* forceCallbacks */);
} else {
// The system's keyguard is disabled or missing.
- setShowingLocked(false, mAodShowing, mSecondaryDisplayShowing, true);
+ setShowingLocked(false, mAodShowing, mSecondaryDisplaysShowing, true);
}
mStatusBarKeyguardViewManager =
@@ -1776,11 +1776,11 @@
}
private void updateActivityLockScreenState(boolean showing, boolean aodShowing,
- int secondaryDisplayShowing) {
+ int[] secondaryDisplaysShowing) {
mUiOffloadThread.submit(() -> {
try {
ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing,
- secondaryDisplayShowing);
+ secondaryDisplaysShowing);
} catch (RemoteException e) {
}
});
@@ -1895,7 +1895,8 @@
if (!mHiding) {
// Tell ActivityManager that we canceled the keyguardExitAnimation.
- setShowingLocked(mShowing, mAodShowing, mSecondaryDisplayShowing, true /* force */);
+ setShowingLocked(mShowing, mAodShowing, mSecondaryDisplaysShowing,
+ true /* force */);
return;
}
mHiding = false;
@@ -2164,22 +2165,23 @@
}
private void setShowingLocked(boolean showing, boolean aodShowing) {
- setShowingLocked(showing, aodShowing, mSecondaryDisplayShowing,
+ setShowingLocked(showing, aodShowing, mSecondaryDisplaysShowing,
false /* forceCallbacks */);
}
- private void setShowingLocked(boolean showing, boolean aodShowing, int secondaryDisplayShowing,
- boolean forceCallbacks) {
+ private void setShowingLocked(boolean showing, boolean aodShowing,
+ int[] secondaryDisplaysShowing, boolean forceCallbacks) {
final boolean notifyDefaultDisplayCallbacks = showing != mShowing
|| aodShowing != mAodShowing || forceCallbacks;
- if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) {
+ if (notifyDefaultDisplayCallbacks
+ || !Arrays.equals(secondaryDisplaysShowing, mSecondaryDisplaysShowing)) {
mShowing = showing;
mAodShowing = aodShowing;
- mSecondaryDisplayShowing = secondaryDisplayShowing;
+ mSecondaryDisplaysShowing = secondaryDisplaysShowing;
if (notifyDefaultDisplayCallbacks) {
notifyDefaultDisplayCallbacks(showing);
}
- updateActivityLockScreenState(showing, aodShowing, secondaryDisplayShowing);
+ updateActivityLockScreenState(showing, aodShowing, secondaryDisplaysShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 568a039..35ae899 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -399,8 +399,8 @@
if (b != null) {
mThermalService = IThermalService.Stub.asInterface(b);
try {
- mThermalService.registerThermalEventListener(
- new ThermalEventListener());
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventListener(), Temperature.TYPE_SKIN);
} catch (RemoteException e) {
// Should never happen.
}
@@ -552,7 +552,7 @@
// Thermal event received from vendor thermal management subsystem
private final class ThermalEventListener extends IThermalEventListener.Stub {
- @Override public void notifyThrottling(boolean isThrottling, Temperature temp) {
+ @Override public void notifyThrottling(Temperature temp) {
// Trigger an update of the temperature warning. Only one
// callback can be enabled at a time, so remove any existing
// callback; updateTemperatureWarning will schedule another one.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 8526afd..8a86826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -128,7 +128,8 @@
}
return true;
case MotionEvent.ACTION_UP:
- if (!isFalseTouch() && mDragDownCallback.onDraggedDown(mStartingChild,
+ if (!mFalsingManager.isUnlockingDisabled() && !isFalseTouch()
+ && mDragDownCallback.onDraggedDown(mStartingChild,
(int) (y - mInitialTouchY))) {
if (mStartingChild == null) {
cancelExpansion();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index a00eac4..960d221 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -51,6 +51,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -66,7 +67,7 @@
/**
* Controls the indications and error messages shown on the Keyguard
*/
-public class KeyguardIndicationController {
+public class KeyguardIndicationController implements StateListener {
private static final String TAG = "KeyguardIndication";
private static final boolean DEBUG_CHARGING_SPEED = false;
@@ -154,6 +155,19 @@
mContext.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
new IntentFilter(Intent.ACTION_TIME_TICK), null,
Dependency.get(Dependency.TIME_TICK_HANDLER));
+
+ Dependency.get(StatusBarStateController.class).addListener(this);
+ }
+
+ /**
+ * Used by {@link com.android.systemui.statusbar.phone.StatusBar} to give the indication
+ * controller a chance to unregister itself as a receiver.
+ *
+ * //TODO: This can probably be converted to a fragment and not have to be manually recreated
+ */
+ public void destroy() {
+ mContext.unregisterReceiver(mTickReceiver);
+ Dependency.get(StatusBarStateController.class).removeListener(this);
}
/**
@@ -518,6 +532,16 @@
updateAlphas();
}
+ @Override
+ public void onStateChanged(int newState) {
+ // don't care
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ setDozing(isDozing);
+ }
+
protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
public static final int HIDE_DELAY_MS = 5000;
private int mLastSuccessiveErrorMessage = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 8994568..bc662e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -15,7 +15,6 @@
package com.android.systemui.statusbar;
import android.content.pm.UserInfo;
-import android.os.SystemProperties;
import android.service.notification.StatusBarNotification;
import android.util.SparseArray;
@@ -26,8 +25,6 @@
String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
= "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
- boolean AUTO_DEMOTE_NOTIFICATIONS = SystemProperties.getBoolean("debug.demote_notifs", false);
-
boolean shouldAllowLockscreenRemoteInput();
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 0108469..e3bc5b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -293,7 +294,7 @@
return false;
}
boolean exceedsPriorityThreshold;
- if (AUTO_DEMOTE_NOTIFICATIONS) {
+ if (NotificationUtils.useNewInterruptionModel(mContext)) {
exceedsPriorityThreshold =
getEntryManager().getNotificationData().getImportance(sbn.getKey())
>= IMPORTANCE_DEFAULT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 92765bb..7581d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -24,7 +24,6 @@
import android.view.ViewGroup;
import com.android.systemui.Dependency;
-import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -380,6 +379,7 @@
}
row.showAppOpsIcons(entry.mActiveAppOps);
+ row.setAudiblyAlerted(entry.audiblyAlerted);
}
Trace.beginSection("NotificationPresenter#onUpdateRowStates");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index c35e1da..bc3638e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -21,6 +21,7 @@
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.Log;
+import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -35,7 +36,6 @@
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.StatusBarState;
@@ -268,6 +268,14 @@
buildNavBarWindows();
buildNavBarContent();
attachNavBarWindows();
+
+ // Add external navigation bars if more than one displays exist.
+ final Display[] displays = mDisplayManager.getDisplays();
+
+ for (Display display : displays) {
+ // TODO(115978725): Add phone navigationBar for now
+ addExternalNavigationBar(display);
+ }
}
private void buildNavBarContent() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index 3539fff..f7c07f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -51,13 +51,14 @@
import android.view.View;
import android.widget.ImageView;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.InitController;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -75,8 +76,6 @@
import java.util.List;
import java.util.Objects;
-import androidx.annotation.Nullable;
-
/**
* The list of currently displaying notifications.
*/
@@ -102,6 +101,9 @@
public String key;
public StatusBarNotification notification;
public NotificationChannel channel;
+ public boolean audiblyAlerted;
+ public boolean noisy;
+ public int importance;
public StatusBarIconView icon;
public StatusBarIconView expandedIcon;
public ExpandableNotificationRow row; // the outer expanded view
@@ -154,6 +156,9 @@
public void populateFromRanking(@NonNull Ranking ranking) {
channel = ranking.getChannel();
+ audiblyAlerted = ranking.audiblyAlerted();
+ noisy = ranking.isNoisy();
+ importance = ranking.getImportance();
snoozeCriteria = ranking.getSnoozeCriteria();
userSentiment = ranking.getUserSentiment();
smartActions = ranking.getSmartActions() == null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 66ba9e9..1f48c15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -16,8 +16,11 @@
package com.android.systemui.statusbar.notification;
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+
import android.content.Context;
import android.graphics.Color;
+import android.provider.Settings;
import android.view.View;
import android.widget.ImageView;
@@ -68,4 +71,10 @@
context.getResources().getDisplayMetrics().density);
return (int) (dimensionPixelSize * factor);
}
+
+ /** Returns the value of the new interruption model setting. */
+ public static boolean useNewInterruptionModel(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) != 0;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
index 28c07a3..43b5503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
@@ -30,6 +30,9 @@
/** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
"blocking_helper_stop_notifications";
+ /** Counter tag for when the user hits 'show silently' in the blocking helper. */
+ public static final String BLOCKING_HELPER_TOGGLE_SILENT =
+ "blocking_helper_toggle_silent";
/** Counter tag for when the user hits 'keep showing' in the blocking helper. */
public static final String BLOCKING_HELPER_KEEP_SHOWING =
"blocking_helper_keep_showing";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index b5fbde1..5dfd5d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -29,9 +29,11 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import java.util.ArrayList;
@@ -42,7 +44,7 @@
* Handles notification logging, in particular, logging which notifications are visible and which
* are not.
*/
-public class NotificationLogger {
+public class NotificationLogger implements StateListener {
private static final String TAG = "NotificationLogger";
/** The minimum delay in ms between reports of notification visibility. */
@@ -63,7 +65,7 @@
protected IStatusBarService mBarService;
private long mLastVisibilityReportUptimeMs;
private NotificationListContainer mListContainer;
- private Object mDozingLock = new Object();
+ private final Object mDozingLock = new Object();
private boolean mDozing;
protected final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
@@ -146,6 +148,8 @@
public NotificationLogger() {
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ // Not expected to be destroyed, don't need to unsubscribe
+ Dependency.get(StatusBarStateController.class).addListener(this);
}
public void setUpWithContainer(NotificationListContainer listContainer) {
@@ -175,7 +179,7 @@
mNotificationLocationsChangedListener.onChildLocationsChanged();
}
- public void setDozing(boolean dozing) {
+ private void setDozing(boolean dozing) {
synchronized (mDozingLock) {
mDozing = dozing;
}
@@ -258,6 +262,16 @@
return mVisibilityReporter;
}
+ @Override
+ public void onStateChanged(int newState) {
+ // don't care about state change
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ setDozing(isDozing);
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 965fb13..5166e06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -16,14 +16,22 @@
package com.android.systemui.statusbar.notification.row;
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_PUBLIC;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+ .ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.row.NotificationContentView
+ .VISIBLE_TYPE_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentView
+ .VISIBLE_TYPE_CONTRACTED;
+import static com.android.systemui.statusbar.notification.row.NotificationContentView
+ .VISIBLE_TYPE_HEADSUP;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+ .FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+ .FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+ .FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+ .InflationCallback;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -1658,6 +1666,17 @@
mPublicLayout.showAppOpsIcons(activeOps);
}
+ /** Sets whether the notification being displayed audibly alerted the user. */
+ public void setAudiblyAlerted(boolean audiblyAlerted) {
+ if (NotificationUtils.useNewInterruptionModel(mContext)) {
+ if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() != null) {
+ mChildrenContainer.getHeaderView().setAudiblyAlerted(audiblyAlerted);
+ }
+ mPrivateLayout.setAudiblyAlerted(audiblyAlerted);
+ mPublicLayout.setAudiblyAlerted(audiblyAlerted);
+ }
+ }
+
public View.OnClickListener getAppOpsOnClickListener() {
return mOnAppOpsClickListener;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 11cf8e0..fa3fa5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1551,6 +1551,19 @@
}
}
+ /** Sets whether the notification being displayed audibly alerted the user. */
+ public void setAudiblyAlerted(boolean audiblyAlerted) {
+ if (mContractedChild != null && mContractedWrapper.getNotificationHeader() != null) {
+ mContractedWrapper.getNotificationHeader().setAudiblyAlerted(audiblyAlerted);
+ }
+ if (mExpandedChild != null && mExpandedWrapper.getNotificationHeader() != null) {
+ mExpandedWrapper.getNotificationHeader().setAudiblyAlerted(audiblyAlerted);
+ }
+ if (mHeadsUpChild != null && mHeadsUpWrapper.getNotificationHeader() != null) {
+ mHeadsUpWrapper.getNotificationHeader().setAudiblyAlerted(audiblyAlerted);
+ }
+ }
+
public NotificationHeaderView getContractedNotificationHeader() {
if (mContractedChild != null) {
return mContractedWrapper.getNotificationHeader();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 0a197da..fbe9c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -23,7 +23,6 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -31,6 +30,8 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
@@ -98,6 +99,11 @@
* Return whether something changed and needs to be saved, possibly requiring a bouncer.
*/
boolean shouldBeSaved();
+
+ /**
+ * Called when the guts view has finished its close animation.
+ */
+ default void onFinishedClosing() {}
}
public interface OnGutsClosedListener {
@@ -304,7 +310,7 @@
x, y, r, 0);
a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
- a.addListener(new AnimateCloseListener(this /* view */));
+ a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
a.start();
} else {
// Fade in the blocking helper.
@@ -312,11 +318,12 @@
.alpha(0f)
.setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
.setInterpolator(Interpolators.ALPHA_OUT)
- .setListener(new AnimateCloseListener(this /* view */))
+ .setListener(new AnimateCloseListener(this, /* view */mGutsContent))
.start();
}
} else {
Log.w(TAG, "Failed to animate guts close");
+ mGutsContent.onFinishedClosing();
}
}
@@ -414,15 +421,18 @@
/** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
private static class AnimateCloseListener extends AnimatorListenerAdapter {
final View mView;
+ private final GutsContent mGutsContent;
- private AnimateCloseListener(View view) {
+ private AnimateCloseListener(View view, GutsContent gutsContent) {
mView = view;
+ mGutsContent = gutsContent;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mView.setVisibility(View.GONE);
+ mGutsContent.onFinishedClosing();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2499952..b838c9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -28,7 +28,6 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -46,15 +45,13 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -298,7 +295,9 @@
mDeviceProvisionedController.isDeviceProvisioned(),
row.getIsNonblockable(),
isForBlockingHelper,
- row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+ row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
+ row.getEntry().noisy,
+ row.getEntry().importance);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 903c272..522da4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -16,13 +16,18 @@
package com.android.systemui.statusbar.notification.row;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.Notification;
@@ -54,6 +59,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import java.util.List;
@@ -65,6 +71,17 @@
public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
private static final String TAG = "InfoGuts";
+ @IntDef(prefix = { "SWAP_CONTENT_" }, value = {
+ SWAP_CONTENT_UNDO,
+ SWAP_CONTENT_TOGGLE_SILENT,
+ SWAP_CONTENT_BLOCK,
+ })
+ @interface SwapContentAction {}
+
+ private static final int SWAP_CONTENT_UNDO = 0;
+ private static final int SWAP_CONTENT_TOGGLE_SILENT = 1;
+ private static final int SWAP_CONTENT_BLOCK = 2;
+
private INotificationManager mINotificationManager;
private PackageManager mPm;
private MetricsLogger mMetricsLogger;
@@ -74,7 +91,8 @@
private int mAppUid;
private int mNumUniqueChannelsInRow;
private NotificationChannel mSingleNotificationChannel;
- private int mStartingUserImportance;
+ private int mStartingChannelImportance;
+ private int mStartingChannelOrNotificationImportance;
private int mChosenImportance;
private boolean mIsSingleDefaultChannel;
private boolean mIsNonblockable;
@@ -82,6 +100,7 @@
private AnimatorSet mExpandAnimation;
private boolean mIsForeground;
private boolean mIsDeviceProvisioned;
+ private boolean mIsNoisy;
private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
@@ -102,10 +121,22 @@
closeControls(v);
};
+ private OnClickListener mOnToggleSilent = v -> {
+ Runnable saveImportance = () -> {
+ mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
+ swapContent(SWAP_CONTENT_TOGGLE_SILENT);
+ };
+ if (mCheckSaveListener != null) {
+ mCheckSaveListener.checkSave(saveImportance, mSbn);
+ } else {
+ saveImportance.run();
+ }
+ };
+
private OnClickListener mOnStopOrMinimizeNotifications = v -> {
Runnable saveImportance = () -> {
mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
- swapContent(false);
+ swapContent(SWAP_CONTENT_BLOCK);
};
if (mCheckSaveListener != null) {
mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -118,7 +149,7 @@
// Reset exit counter that we'll log and record an undo event separately (not an exit event)
mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
- swapContent(true);
+ swapContent(SWAP_CONTENT_UNDO);
};
public NotificationInfo(Context context, AttributeSet attrs) {
@@ -152,12 +183,15 @@
final OnSettingsClickListener onSettingsClick,
final OnAppSettingsClickListener onAppSettingsClick,
boolean isDeviceProvisioned,
- boolean isNonblockable)
+ boolean isNonblockable,
+ boolean isNoisy,
+ int importance)
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel,
numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
- false /* isBlockingHelper */, false /* isUserSentimentNegative */);
+ false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
+ importance);
}
public void bindNotification(
@@ -173,7 +207,9 @@
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean isForBlockingHelper,
- boolean isUserSentimentNegative)
+ boolean isUserSentimentNegative,
+ boolean isNoisy,
+ int importance)
throws RemoteException {
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -186,7 +222,10 @@
mCheckSaveListener = checkSaveListener;
mOnSettingsClickListener = onSettingsClick;
mSingleNotificationChannel = notificationChannel;
- mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
+ int channelImportance = mSingleNotificationChannel.getImportance();
+ mStartingChannelImportance = mChosenImportance = channelImportance;
+ mStartingChannelOrNotificationImportance =
+ channelImportance == IMPORTANCE_UNSPECIFIED ? importance : channelImportance;
mNegativeUserSentiment = isUserSentimentNegative;
mIsNonblockable = isNonblockable;
mIsForeground =
@@ -194,6 +233,7 @@
mIsForBlockingHelper = isForBlockingHelper;
mAppUid = mSbn.getUid();
mIsDeviceProvisioned = isDeviceProvisioned;
+ mIsNoisy = isNoisy;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -306,7 +346,8 @@
}
private boolean hasImportanceChanged() {
- return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
+ return mSingleNotificationChannel != null
+ && mStartingChannelImportance != mChosenImportance;
}
private void saveImportance() {
@@ -320,34 +361,46 @@
*/
private void updateImportance() {
MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
- mChosenImportance - mStartingUserImportance);
+ mChosenImportance - mStartingChannelImportance);
Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
- mStartingUserImportance, mChosenImportance));
+ mStartingChannelImportance, mChosenImportance));
}
private void bindButtons() {
// Set up stay-in-notification actions
View block = findViewById(R.id.block);
TextView keep = findViewById(R.id.keep);
+ TextView silent = findViewById(R.id.toggle_silent);
View minimize = findViewById(R.id.minimize);
findViewById(R.id.undo).setOnClickListener(mOnUndo);
block.setOnClickListener(mOnStopOrMinimizeNotifications);
keep.setOnClickListener(mOnKeepShowing);
+ silent.setOnClickListener(mOnToggleSilent);
minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
if (mIsNonblockable) {
keep.setText(android.R.string.ok);
block.setVisibility(GONE);
+ silent.setVisibility(GONE);
minimize.setVisibility(GONE);
} else if (mIsForeground) {
block.setVisibility(GONE);
+ silent.setVisibility(GONE);
minimize.setVisibility(VISIBLE);
- } else if (!mIsForeground) {
+ } else {
block.setVisibility(VISIBLE);
+ boolean showToggleSilent = mIsNoisy
+ && NotificationUtils.useNewInterruptionModel(mContext);
+ silent.setVisibility(showToggleSilent ? VISIBLE : GONE);
+ boolean isCurrentlyAlerting =
+ mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT;
+ silent.setText(isCurrentlyAlerting
+ ? R.string.inline_silent_button_silent
+ : R.string.inline_silent_button_alert);
minimize.setVisibility(GONE);
}
@@ -368,7 +421,7 @@
}
}
- private void swapContent(boolean showPrompt) {
+ private void swapContent(@SwapContentAction int action) {
if (mExpandAnimation != null) {
mExpandAnimation.cancel();
}
@@ -378,26 +431,43 @@
TextView confirmationText = findViewById(R.id.confirmation_text);
View header = findViewById(R.id.header);
- if (showPrompt) {
- mChosenImportance = mStartingUserImportance;
- } else if (mIsForeground) {
- mChosenImportance = IMPORTANCE_MIN;
- confirmationText.setText(R.string.notification_channel_minimized);
- } else {
- mChosenImportance = IMPORTANCE_NONE;
- confirmationText.setText(R.string.notification_channel_disabled);
+ switch (action) {
+ case SWAP_CONTENT_UNDO:
+ mChosenImportance = mStartingChannelImportance;
+ break;
+ case SWAP_CONTENT_TOGGLE_SILENT:
+ if (mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT) {
+ mChosenImportance = IMPORTANCE_LOW;
+ confirmationText.setText(R.string.notification_channel_silenced);
+ } else {
+ mChosenImportance = IMPORTANCE_HIGH;
+ confirmationText.setText(R.string.notification_channel_unsilenced);
+ }
+ break;
+ case SWAP_CONTENT_BLOCK:
+ if (mIsForeground) {
+ mChosenImportance = IMPORTANCE_MIN;
+ confirmationText.setText(R.string.notification_channel_minimized);
+ } else {
+ mChosenImportance = IMPORTANCE_NONE;
+ confirmationText.setText(R.string.notification_channel_disabled);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException();
}
+ boolean isUndo = action == SWAP_CONTENT_UNDO;
ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
- prompt.getAlpha(), showPrompt ? 1f : 0f);
- promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ prompt.getAlpha(), isUndo ? 1f : 0f);
+ promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
- confirmation.getAlpha(), showPrompt ? 0f : 1f);
- confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+ confirmation.getAlpha(), isUndo ? 0f : 1f);
+ confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
- prompt.setVisibility(showPrompt ? VISIBLE : GONE);
- confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
- header.setVisibility(showPrompt ? VISIBLE : GONE);
+ prompt.setVisibility(isUndo ? VISIBLE : GONE);
+ confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+ header.setVisibility(isUndo ? VISIBLE : GONE);
mExpandAnimation = new AnimatorSet();
mExpandAnimation.playTogether(promptAnim, confirmAnim);
@@ -413,8 +483,8 @@
@Override
public void onAnimationEnd(Animator animation) {
if (!cancelled) {
- prompt.setVisibility(showPrompt ? VISIBLE : GONE);
- confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+ prompt.setVisibility(isUndo ? VISIBLE : GONE);
+ confirmation.setVisibility(isUndo ? GONE : VISIBLE);
}
}
});
@@ -428,6 +498,25 @@
}
@Override
+ public void onFinishedClosing() {
+ mStartingChannelImportance = mChosenImportance;
+ if (mChosenImportance != IMPORTANCE_UNSPECIFIED) {
+ mStartingChannelOrNotificationImportance = mChosenImportance;
+ }
+ mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+
+ View prompt = findViewById(R.id.prompt);
+ ViewGroup confirmation = findViewById(R.id.confirmation);
+ View header = findViewById(R.id.header);
+ prompt.setVisibility(VISIBLE);
+ prompt.setAlpha(1f);
+ confirmation.setVisibility(GONE);
+ confirmation.setAlpha(1f);
+ header.setVisibility(VISIBLE);
+ header.setAlpha(1f);
+ }
+
+ @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (mGutsContainer != null &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 7e60c4b..674c8ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -16,17 +16,8 @@
package com.android.systemui.statusbar.notification.row;
-import java.util.ArrayList;
-
import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.AlphaOptimizedImageView;
-import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -45,6 +36,15 @@
import android.widget.FrameLayout.LayoutParams;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.AlphaOptimizedImageView;
+import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+
+import java.util.ArrayList;
+import java.util.List;
public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener,
ExpandableNotificationRow.LayoutListener {
@@ -70,7 +70,8 @@
private MenuItem mInfoItem;
private MenuItem mAppOpsItem;
private MenuItem mSnoozeItem;
- private ArrayList<MenuItem> mMenuItems;
+ private ArrayList<MenuItem> mLeftMenuItems;
+ private ArrayList<MenuItem> mRightMenuItems;
private OnMenuEventListener mMenuListener;
private ValueAnimator mFadeAnimator;
@@ -107,12 +108,13 @@
mContext = context;
mShouldShowMenu = context.getResources().getBoolean(R.bool.config_showNotificationGear);
mHandler = new Handler(Looper.getMainLooper());
- mMenuItems = new ArrayList<>();
+ mLeftMenuItems = new ArrayList<>();
+ mRightMenuItems = new ArrayList<>();
}
@Override
public ArrayList<MenuItem> getMenuItems(Context context) {
- return mMenuItems;
+ return mOnLeft ? mLeftMenuItems : mRightMenuItems;
}
@Override
@@ -231,7 +233,8 @@
final Resources res = mContext.getResources();
mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
- mMenuItems.clear();
+ mLeftMenuItems.clear();
+ mRightMenuItems.clear();
// Construct the menu items based on the notification
if (mParent != null && mParent.getStatusBarNotification() != null) {
int flags = mParent.getStatusBarNotification().getNotification().flags;
@@ -239,24 +242,19 @@
if (!isForeground) {
// Only show snooze for non-foreground notifications
mSnoozeItem = createSnoozeItem(mContext);
- mMenuItems.add(mSnoozeItem);
+ mLeftMenuItems.add(mSnoozeItem);
+ mRightMenuItems.add(mSnoozeItem);
}
}
mInfoItem = createInfoItem(mContext);
- mMenuItems.add(mInfoItem);
+ mLeftMenuItems.add(mInfoItem);
+ mRightMenuItems.add(mInfoItem);
mAppOpsItem = createAppOpsItem(mContext);
- mMenuItems.add(mAppOpsItem);
+ mLeftMenuItems.add(mAppOpsItem);
+ mRightMenuItems.add(mAppOpsItem);
- // Construct the menu views
- if (mMenuContainer != null) {
- mMenuContainer.removeAllViews();
- } else {
- mMenuContainer = new FrameLayout(mContext);
- }
- for (int i = 0; i < mMenuItems.size(); i++) {
- addMenuView(mMenuItems.get(i), mMenuContainer);
- }
+ populateMenuViews();
if (resetState) {
resetState(false /* notify */);
} else {
@@ -268,6 +266,18 @@
}
}
+ private void populateMenuViews() {
+ if (mMenuContainer != null) {
+ mMenuContainer.removeAllViews();
+ } else {
+ mMenuContainer = new FrameLayout(mContext);
+ }
+ List<MenuItem> menuItems = mOnLeft ? mLeftMenuItems : mRightMenuItems;
+ for (int i = 0; i < menuItems.size(); i++) {
+ addMenuView(menuItems.get(i), mMenuContainer);
+ }
+ }
+
private void resetState(boolean notify) {
setMenuAlpha(0f);
mIconsPlaced = false;
@@ -386,10 +396,16 @@
if (appName == null) {
return;
}
+ setAppName(appName, mLeftMenuItems);
+ setAppName(appName, mRightMenuItems);
+ }
+
+ private void setAppName(String appName,
+ ArrayList<MenuItem> menuItems) {
Resources res = mContext.getResources();
- final int count = mMenuItems.size();
+ final int count = menuItems.size();
for (int i = 0; i < count; i++) {
- MenuItem item = mMenuItems.get(i);
+ MenuItem item = menuItems.get(i);
String description = String.format(
res.getString(R.string.notification_menu_accessibility),
appName, item.getContentDescription());
@@ -402,7 +418,9 @@
@Override
public void onParentHeightUpdate() {
- if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) {
+ if (mParent == null
+ || (mLeftMenuItems.isEmpty() && mRightMenuItems.isEmpty())
+ || mMenuContainer == null) {
return;
}
int parentHeight = mParent.getActualHeight();
@@ -443,13 +461,14 @@
}
v.getLocationOnScreen(mIconLocation);
mParent.getLocationOnScreen(mParentLocation);
- final int centerX = (int) (mHorizSpaceForIcon / 2);
+ final int centerX = mHorizSpaceForIcon / 2;
final int centerY = v.getHeight() / 2;
final int x = mIconLocation[0] - mParentLocation[0] + centerX;
final int y = mIconLocation[1] - mParentLocation[1] + centerY;
final int index = mMenuContainer.indexOfChild(v);
if (mMenuListener != null) {
- mMenuListener.onMenuClicked(mParent, x, y, mMenuItems.get(index));
+ mMenuListener.onMenuClicked(mParent, x, y,
+ (mOnLeft ? mLeftMenuItems : mRightMenuItems).get(index));
}
}
@@ -469,6 +488,11 @@
// Do nothing
return;
}
+ boolean wasOnLeft = mOnLeft;
+ mOnLeft = showOnLeft;
+ if (wasOnLeft != showOnLeft) {
+ populateMenuViews();
+ }
final int count = mMenuContainer.getChildCount();
for (int i = 0; i < count; i++) {
final View v = mMenuContainer.getChildAt(i);
@@ -476,7 +500,6 @@
final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
v.setX(showOnLeft ? left : right);
}
- mOnLeft = showOnLeft;
mIconsPlaced = true;
}
@@ -603,6 +626,7 @@
private void addMenuView(MenuItem item, ViewGroup parent) {
View menuView = item.getMenuView();
if (menuView != null) {
+ menuView.setAlpha(mAlpha);
parent.addView(menuView);
menuView.setOnClickListener(this);
FrameLayout.LayoutParams lp = (LayoutParams) menuView.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index c47d408..a315bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1124,7 +1124,7 @@
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private float getExpandTranslationStart() {
- return -mTopPadding + getMinExpansionHeight();
+ return -mTopPadding + getMinExpansionHeight() - mShelf.getIntrinsicHeight();
}
/**
@@ -5643,6 +5643,11 @@
public boolean canChildBeDismissed(View v) {
return NotificationStackScrollLayout.this.canChildBeDismissed(v);
}
+
+ @Override
+ public boolean canChildBeDismissedInDirection(View v, boolean isRightOrDown) {
+ return (isLayoutRtl() ? !isRightOrDown : isRightOrDown) && canChildBeDismissed(v);
+ }
};
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index a0597dc..94b2cde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -20,13 +20,17 @@
import android.os.Handler;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
/**
* Controller which handles all the doze animations of the scrims.
*/
-public class DozeScrimController {
+public class DozeScrimController implements StateListener {
private static final String TAG = "DozeScrimController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -83,8 +87,11 @@
public DozeScrimController(DozeParameters dozeParameters) {
mDozeParameters = dozeParameters;
+ //Never expected to be destroyed
+ Dependency.get(StatusBarStateController.class).addListener(this);
}
+ @VisibleForTesting
public void setDozing(boolean dozing) {
if (mDozing == dozing) return;
mDozing = dozing;
@@ -181,4 +188,14 @@
public ScrimController.Callback getScrimCallback() {
return mScrimCallback;
}
+
+ @Override
+ public void onStateChanged(int newState) {
+ // don't care
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ setDozing(isDozing);
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 4a7bc3a..d8280ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -187,6 +187,7 @@
if (mPulsing) {
clockYDark -= mPulsingPadding;
}
+ clockYDark = MathUtils.max(0, clockYDark);
float clockYRegular = getExpandedClockPosition();
float clockYBouncer = -mKeyguardStatusHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
index 462201c..b3d0bf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
@@ -35,7 +35,7 @@
}
/**
- * Executes an action that requres the screen to be unlocked.
+ * Executes an action that requires the screen to be unlocked.
*
* <p>Must be called after {@link #setDismissHandler}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 329a33d..4406b14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -55,7 +55,8 @@
import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;
-import android.view.IRotationWatcher.Stub;
+import android.view.Display;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -74,12 +75,12 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.stackdivider.Divider;
@@ -419,8 +420,12 @@
}
checkNavBarModes();
mStatusBar.touchAutoHide();
- mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
- true /* nbModeChanged */, mNavigationBarMode);
+
+ // TODO(115978725): Support light bar controller on external nav bars.
+ if (mLightBarController != null) {
+ mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
+ true /* nbModeChanged */, mNavigationBarMode);
+ }
}
@Override
@@ -452,8 +457,11 @@
}
}
- mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
- mNavigationBarMode);
+ // TODO(115978725): Support light bar controller on external nav bars.
+ if (mLightBarController != null) {
+ mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
+ mNavigationBarMode);
+ }
}
@Override
@@ -840,9 +848,17 @@
};
public static View create(Context context, FragmentListener listener) {
+ final int displayId = context.getDisplay().getDisplayId();
+ final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ final int height = isDefaultDisplay
+ ? LayoutParams.MATCH_PARENT
+ : context.getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+ LayoutParams.MATCH_PARENT, height,
+ // TODO(b/117478341): Resolve one status bar/ navigation bar assumption
+ isDefaultDisplay
+ ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+ : WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
@@ -851,9 +867,13 @@
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
lp.token = new Binder();
- lp.setTitle("NavigationBar");
+ lp.setTitle("NavigationBar" + displayId);
lp.accessibilityTitle = context.getString(R.string.nav_bar);
lp.windowAnimations = 0;
+ if (!isDefaultDisplay) {
+ lp.flags |= LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+ lp.gravity = Gravity.BOTTOM;
+ }
View navigationBarView = LayoutInflater.from(context).inflate(
R.layout.navigation_bar_window, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index c08366a..6b12dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -16,22 +16,24 @@
package com.android.systemui.statusbar.phone;
-import android.annotation.NonNull;
import android.app.Notification;
import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
-import androidx.annotation.Nullable;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListener;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -48,7 +50,7 @@
* A class to handle notifications and their corresponding groups.
*/
public class NotificationGroupManager implements OnHeadsUpChangedListener,
- OnAmbientChangedListener {
+ OnAmbientChangedListener, StateListener {
private static final String TAG = "NotificationGroupManager";
private static final long ALERT_TRANSFER_TIMEOUT = 300;
@@ -62,10 +64,8 @@
private boolean mIsUpdatingUnchangedGroup;
private HashMap<String, NotificationData.Entry> mPendingNotifications;
- private final StateListener mStateListener = this::setStatusBarState;
-
public NotificationGroupManager() {
- Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+ Dependency.get(StatusBarStateController.class).addListener(this);
}
public void setOnGroupChangeListener(OnGroupChangeListener listener) {
@@ -185,6 +185,7 @@
* specific alert state logic based off when the state changes.
* @param isDozing if the device is dozing.
*/
+ @VisibleForTesting
public void setDozing(boolean isDozing) {
if (mIsDozing != isDozing) {
for (NotificationGroup group : mGroupMap.values()) {
@@ -732,6 +733,16 @@
mPendingNotifications = pendingNotifications;
}
+ @Override
+ public void onStateChanged(int newState) {
+ setStatusBarState(newState);
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ setDozing(isDozing);
+ }
+
public static class NotificationGroup {
public final HashMap<String, NotificationData.Entry> children = new HashMap<>();
public NotificationData.Entry summary;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index f50e9a2..8e90f98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -20,7 +20,6 @@
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationData;
@@ -50,7 +49,7 @@
public void onTuningChanged(String key, String newValue) {
if (key.equals(LOW_PRIORITY)) {
mShowLowPriority = "1".equals(newValue)
- || !NotificationLockscreenUserManager.AUTO_DEMOTE_NOTIFICATIONS;
+ || !NotificationUtils.useNewInterruptionModel(mContext);
if (mNotificationScrollLayout != null) {
updateStatusBarIcons();
}
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 31facb7..f4c2e27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -582,7 +582,7 @@
int stackScrollerPadding;
if (mBarState != StatusBarState.KEYGUARD) {
stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
- + mQsNotificationTopPadding;
+ + mQsNotificationTopPadding;
} else {
int totalHeight = getHeight();
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
@@ -754,7 +754,7 @@
mQsExpandImmediate = true;
mNotificationStackScroller.setShouldShowShelfOnly(true);
}
- if (isFullyCollapsed()){
+ if (isFullyCollapsed()) {
expand(true /* animate */);
} else {
flingSettings(0 /* velocity */, FLING_EXPAND);
@@ -921,7 +921,7 @@
}
private boolean flingExpandsQs(float vel) {
- if (isFalseTouch()) {
+ if (mFalsingManager.isUnlockingDisabled() || isFalseTouch()) {
return false;
}
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -1046,11 +1046,11 @@
final boolean stylusButtonClickDrag = action == MotionEvent.ACTION_DOWN
&& (event.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)
- || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY));
+ || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY));
final boolean mouseButtonClickDrag = action == MotionEvent.ACTION_DOWN
&& (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
- || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
+ || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag;
}
@@ -1321,12 +1321,12 @@
private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener =
new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
- updateHeaderKeyguardAlpha();
- }
- };
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
+ updateHeaderKeyguardAlpha();
+ }
+ };
private void animateKeyguardStatusBarIn(long duration) {
mKeyguardStatusBar.setVisibility(View.VISIBLE);
@@ -1382,7 +1382,7 @@
if (keyguardFadingAway) {
mKeyguardStatusView.animate()
.setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
- .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration()/2)
+ .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2)
.start();
}
} else if (mBarState == StatusBarState.SHADE_LOCKED
@@ -1425,8 +1425,8 @@
updateEmptyShadeView();
mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
&& !mStackScrollerOverscrolling && mQsScrimEnabled
- ? View.VISIBLE
- : View.INVISIBLE);
+ ? View.VISIBLE
+ : View.INVISIBLE);
if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
}
@@ -1459,7 +1459,8 @@
setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
}
- if (mQsFullyExpanded && mFalsingManager.shouldEnforceBouncer()) {
+ if (!mFalsingManager.isUnlockingDisabled() && mQsFullyExpanded
+ && mFalsingManager.shouldEnforceBouncer()) {
mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
}
@@ -2130,8 +2131,7 @@
}
}, null, true /* dismissShade */, false /* afterKeyguardGone */,
true /* deferred */);
- }
- else {
+ } else {
mKeyguardBottomArea.launchLeftAffordance();
}
} else {
@@ -2588,7 +2588,7 @@
x = Math.min(rightMost, Math.max(leftMost, x));
setVerticalPanelTranslation(x -
(mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2));
- }
+ }
private void resetVerticalPanelPosition() {
setVerticalPanelTranslation(0f);
@@ -2716,8 +2716,8 @@
String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
? null : resolveInfo.activityInfo.packageName;
return packageToLaunch != null &&
- (keyguardIsShowing || !isForegroundApp(packageToLaunch)) &&
- !mAffordanceHelper.isSwipingInProgress();
+ (keyguardIsShowing || !isForegroundApp(packageToLaunch))
+ && !mAffordanceHelper.isSwipingInProgress();
}
/**
@@ -2884,13 +2884,14 @@
}
public void setStatusAccessibilityImportance(int mode) {
- mKeyguardStatusView.setImportantForAccessibility(mode);
+ mKeyguardStatusView.setImportantForAccessibility(mode);
}
/**
* TODO: this should be removed.
* It's not correct to pass this view forward because other classes will end up adding
* children to it. Theme will be out of sync.
+ *
* @return bottom area view
*/
public KeyguardBottomAreaView getKeyguardBottomAreaView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f29b7ca..021b430 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -670,6 +670,10 @@
* @return whether a fling should expands the panel; contracts otherwise
*/
protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
+ if (mFalsingManager.isUnlockingDisabled()) {
+ return true;
+ }
+
if (isFalseTouch(x, y)) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2337857..966a346 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -22,6 +22,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
@@ -70,6 +71,8 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -96,6 +99,7 @@
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
@@ -558,8 +562,37 @@
}
};
+ protected DisplayManager mDisplayManager;
+
private NavigationBarFragment mNavigationBar;
private View mNavigationBarView;
+
+ /** A displayId - nav bar mapping */
+ private SparseArray<NavigationBarFragment> mExternalNavigationBarMap = new SparseArray<>();
+
+ // TODO(b/115978725): Move it to DisplayNavigationBarController
+ private final DisplayListener mDisplayListener = new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ final Display display = mDisplayManager.getDisplay(displayId);
+ addExternalNavigationBar(display);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ final NavigationBarFragment navBar = mExternalNavigationBarMap.get(displayId);
+ if (navBar != null) {
+ final View navigationView = navBar.getView().getRootView();
+ WindowManagerGlobal.getInstance().removeView(navigationView, true);
+ mExternalNavigationBarMap.remove(displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ }
+ };
+
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private boolean mVibrateOnOpening;
private VibratorHelper mVibratorHelper;
@@ -586,7 +619,6 @@
mNotificationLogger = Dependency.get(NotificationLogger.class);
mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
mNotificationListener = Dependency.get(NotificationListener.class);
- mGroupManager = Dependency.get(NotificationGroupManager.class);
mNetworkController = Dependency.get(NetworkController.class);
mUserSwitcherController = Dependency.get(UserSwitcherController.class);
mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
@@ -618,6 +650,9 @@
mDisplay = mWindowManager.getDefaultDisplay();
updateDisplaySize();
+ // get display service to detect display status
+ mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+
Resources res = mContext.getResources();
mVibrateOnOpening = mContext.getResources().getBoolean(
R.bool.config_vibrateOnIconAnimation);
@@ -660,6 +695,7 @@
// If the system process isn't there we're doomed anyway.
}
+ mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
createAndAddWindows();
// Make sure we always have the most current wallpaper info.
@@ -864,6 +900,7 @@
}
});
+ // TODO(115978725): Support light bar controller on external nav bars.
mLightBarController = Dependency.get(LightBarController.class);
if (mNavigationBar != null) {
mNavigationBar.setLightBarController(mLightBarController);
@@ -1047,6 +1084,33 @@
}
mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
});
+
+ // Add external navigation bars if more than one displays exist.
+ final Display[] displays = mDisplayManager.getDisplays();
+ for (Display display : displays) {
+ addExternalNavigationBar(display);
+ }
+ }
+
+ /**
+ * Add a phone navigation bar on an external display if the display supports system decorations.
+ *
+ * @param display the display to add navigation bar on
+ */
+ protected void addExternalNavigationBar(Display display) {
+ if (display == null || display.getDisplayId() == DEFAULT_DISPLAY
+ || !display.supportsSystemDecorations()) {
+ return;
+ }
+
+ final int displayId = display.getDisplayId();
+ final Context externalDisplayContext = mContext.createDisplayContext(display);
+ NavigationBarFragment.create(externalDisplayContext,
+ (tag, fragment) -> {
+ final NavigationBarFragment navBar = (NavigationBarFragment) fragment;
+ navBar.setCurrentSysuiVisibility(mSystemUiVisibility);
+ mExternalNavigationBarMap.append(displayId, navBar);
+ });
}
/**
@@ -1096,6 +1160,9 @@
@Override
public void onThemeChanged() {
// Recreate Indication controller because internal references changed
+ if (mKeyguardIndicationController != null) {
+ mKeyguardIndicationController.destroy();
+ }
mKeyguardIndicationController =
SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
@@ -1104,7 +1171,6 @@
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD);
- mKeyguardIndicationController.setDozing(mDozing);
if (mStatusBarKeyguardViewManager != null) {
mStatusBarKeyguardViewManager.onThemeChanged();
}
@@ -2065,6 +2131,7 @@
}
}
+ // TODO(115978725): Support auto hide on external nav bars.
void touchAutoHide() {
// update transient bar autohide
if (mStatusBarMode == MODE_SEMI_TRANSPARENT || (mNavigationBar != null
@@ -2104,6 +2171,7 @@
: MODE_OPAQUE;
}
+ // TODO(115978725): Support animations on external nav bars.
void checkBarModes() {
if (mDemoMode) return;
if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
@@ -2123,6 +2191,7 @@
transitions.transitionTo(mode, anim);
}
+ // TODO(115978725): Support animations on external nav bars.
private void finishBarAnimations() {
if (mStatusBarView != null) {
mStatusBarView.getBarTransitions().finishAnimations();
@@ -2856,6 +2925,16 @@
mWindowManager.removeViewImmediate(mNavigationBarView);
mNavigationBarView = null;
}
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ if (mExternalNavigationBarMap.size() > 0) {
+ for (int i = 0; i < mExternalNavigationBarMap.size(); i++) {
+ final View navigationWindow = mExternalNavigationBarMap.valueAt(i)
+ .getView().getRootView();
+ WindowManagerGlobal.getInstance()
+ .removeView(navigationWindow, true /* immediate */);
+ }
+ mExternalNavigationBarMap.clear();
+ }
mContext.unregisterReceiver(mBroadcastReceiver);
mContext.unregisterReceiver(mDemoReceiver);
mAssistManager.destroy();
@@ -2924,6 +3003,7 @@
"transparent".equals(mode) ? MODE_TRANSPARENT :
"warning".equals(mode) ? MODE_WARNING :
-1;
+ // TODO(115978725): Support external nav bar transitions
if (barMode != -1) {
boolean animate = true;
if (mStatusBarView != null) {
@@ -3157,6 +3237,7 @@
mDraggedDownRow = null;
}
+ // TODO(115978725): Support animations on external nav bars.
// Disable layout transitions in navbar for this transition because the load is just
// too heavy for the CPU and GPU on any device.
if (mNavigationBar != null) {
@@ -3247,12 +3328,8 @@
boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup())
|| (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard);
- mDozeScrimController.setDozing(mDozing);
- mKeyguardIndicationController.setDozing(mDozing);
mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation,
mDozeServiceHost.wasPassivelyInterrupted());
- mNotificationLogger.setDozing(mDozing);
- mGroupManager.setDozing(mDozing);
updateQsExpansionEnabled();
Trace.endSection();
}
@@ -3442,13 +3519,6 @@
updateQsExpansionEnabled();
mKeyguardViewMediator.setAodShowing(mDozing);
- //TODO: make these folks listeners of StatusBarStateController.onDozingChanged
- mStatusBarWindowController.setDozing(mDozing);
- mStatusBarKeyguardViewManager.setDozing(mDozing);
- if (mAmbientIndicationContainer instanceof DozeReceiver) {
- ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
- }
-
mEntryManager.updateNotifications();
updateDozingState();
updateScrimController();
@@ -4425,6 +4495,7 @@
}
// End Extra BaseStatusBarMethods.
+ // TODO(115978725): Handle dimming for external nav bars
private final Runnable mAutoDim = () -> {
if (mNavigationBar != null) {
mNavigationBar.getBarTransitions().setAutoDim(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index df99a9c..484fe11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -59,7 +59,8 @@
* which is in turn, reported to this class by the current
* {@link com.android.keyguard.KeyguardViewBase}.
*/
-public class StatusBarKeyguardViewManager implements RemoteInputController.Callback {
+public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
+ StatusBarStateController.StateListener {
// When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
@@ -150,6 +151,7 @@
mLockPatternUtils = lockPatternUtils;
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
+ Dependency.get(StatusBarStateController.class).addListener(this);
}
public void registerStatusBar(StatusBar statusBar,
@@ -334,7 +336,7 @@
updateStates();
}
- public void setDozing(boolean dozing) {
+ private void setDozing(boolean dozing) {
if (mDozing != dozing) {
mDozing = dozing;
if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) {
@@ -781,6 +783,16 @@
}
}
+ @Override
+ public void onStateChanged(int newState) {
+ // Nothing
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ setDozing(isDozing);
+ }
+
private static class DismissWithActionRequest {
final OnDismissAction dismissAction;
final Runnable cancelAction;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 0d37b55..11de941 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -76,7 +76,6 @@
private final State mCurrentState = new State();
private OtherwisedCollapsedListener mListener;
- private final StateListener mStateListener = this::setStatusBarState;
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
public StatusBarWindowController(Context context) {
@@ -564,6 +563,18 @@
}
}
+ private final StateListener mStateListener = new StateListener() {
+ @Override
+ public void onStateChanged(int newState) {
+ setStatusBarState(newState);
+ }
+
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ setDozing(isDozing);
+ }
+ };
+
/**
* Custom listener to pipe data back to plugins about whether or not the status bar would be
* collapsed if not for the plugin.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
index 50fd52a..cfb633d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
@@ -134,4 +134,6 @@
optional int32 touchAreaHeight = 10;
optional Type type = 11;
repeated PhoneEvent phoneEvents = 12;
+
+ optional string device_id = 13;
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 3744105..9077b6b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -539,9 +539,9 @@
if (value != volumeItem.progress) {
volumeItem.listItem.setProgress(value);
volumeItem.progress = value;
- if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
- show(Events.SHOW_REASON_VOLUME_CHANGED);
- }
+ }
+ if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
+ show(Events.SHOW_REASON_VOLUME_CHANGED);
}
}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index aac37a2..b32bf99 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -39,7 +39,7 @@
telephony-common \
android.test.base \
android.car \
- android.car.user
+ android.car.userlib
LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index 459dc5d..8e6bfe3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -437,22 +437,23 @@
outRanking.getImportance(), outRanking.getImportanceExplanation(),
outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
- null, null);
+ false, false, null, null);
} else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
outRanking.populate(key, outRanking.getRank(),
outRanking.matchesInterruptionFilter(),
outRanking.getVisibilityOverride(), 255,
outRanking.getImportance(), outRanking.getImportanceExplanation(),
outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
- outRanking.canShowBadge(), outRanking.getUserSentiment(), true, null, null);
+ outRanking.canShowBadge(), outRanking.getUserSentiment(), true, false,
+ false, null, null);
} else {
outRanking.populate(key, outRanking.getRank(),
outRanking.matchesInterruptionFilter(),
outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
outRanking.getImportance(), outRanking.getImportanceExplanation(),
outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
- outRanking.canShowBadge(), outRanking.getUserSentiment(), false, null,
- null);
+ outRanking.canShowBadge(), outRanking.getUserSentiment(), false, false,
+ false, null, null);
}
return true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index fb4ecd1..9f8a5cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -19,7 +19,6 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
@@ -168,7 +167,7 @@
0,
NotificationManager.IMPORTANCE_DEFAULT,
null, null,
- null, null, null, true, sentiment, false, null, null);
+ null, null, null, true, sentiment, false, false, false, null, null);
return true;
}).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
}
@@ -186,8 +185,8 @@
NotificationManager.IMPORTANCE_DEFAULT,
null, null,
null, null, null, true,
- NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false,
- smartActions, null);
+ NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false, false,
+ false, smartActions, null);
return true;
}).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index ee35449..626726d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -19,8 +19,10 @@
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.service.notification.NotificationListenerService.Ranking
+ .USER_SENTIMENT_NEGATIVE;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -34,15 +36,14 @@
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
-import android.app.NotificationManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -57,11 +58,12 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+ .OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -71,8 +73,8 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.junit.MockitoRule;
import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
/**
* Tests for {@link NotificationGutsManager}.
@@ -84,7 +86,7 @@
private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
private NotificationChannel mTestNotificationChannel = new NotificationChannel(
- TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+ TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
private TestableLooper mTestableLooper;
private Handler mHandler;
private NotificationTestHelper mHelper;
@@ -297,7 +299,9 @@
eq(false),
eq(false),
eq(true) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */);
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0));
}
@Test
@@ -324,7 +328,69 @@
eq(false),
eq(false),
eq(false) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */);
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0));
+ }
+
+ @Test
+ public void testInitializeNotificationInfoView_noisy() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ row.getEntry().noisy = true;
+ when(row.getIsNonblockable()).thenReturn(false);
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ any(NotificationChannel.class),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ eq(false),
+ eq(false),
+ eq(true) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */,
+ eq(true) /*isNoisy */,
+ eq(0));
+ }
+
+ @Test
+ public void testInitializeNotificationInfoView_importance() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ row.getEntry().importance = IMPORTANCE_DEFAULT;
+ when(row.getIsNonblockable()).thenReturn(false);
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ any(NotificationChannel.class),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ eq(false),
+ eq(false),
+ eq(true) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(IMPORTANCE_DEFAULT));
}
@Test
@@ -352,7 +418,9 @@
eq(true),
eq(false),
eq(false) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */);
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index ca968a8..3744196 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -17,11 +17,14 @@
package com.android.systemui.statusbar.notification.row;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
@@ -56,6 +59,7 @@
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -72,6 +76,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -150,6 +155,15 @@
IMPORTANCE_LOW);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
+
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+ }
+
+ @After
+ public void tearDown() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
}
// TODO: if tests are taking too long replace this with something that makes the animation
@@ -172,7 +186,8 @@
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -184,7 +199,8 @@
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -192,7 +208,8 @@
@Test
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -208,7 +225,8 @@
eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -219,7 +237,8 @@
@Test
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -228,7 +247,7 @@
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false);
+ false, false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -241,7 +260,7 @@
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false);
+ false, false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -249,7 +268,8 @@
@Test
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -257,18 +277,71 @@
@Test
public void testBindNotification_BlockButton() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
+ final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(VISIBLE, block.getVisibility());
+ assertEquals(GONE, toggleSilent.getVisibility());
assertEquals(GONE, minimize.getVisibility());
}
@Test
+ public void testBindNotification_SilenceButton() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+ }
+
+ @Test
+ public void testBindNotification_UnSilenceButton() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_LOW);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+ }
+
+ @Test
+ public void testBindNotification_SilenceButton_ChannelImportanceUnspecified() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+ }
+
+ @Test
+ public void testBindNotification_UnSilenceButton_ChannelImportanceUnspecified()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_LOW);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+ }
+
+ @Test
public void testBindNotification_MinButton() throws Exception {
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(GONE, block.getVisibility());
@@ -283,7 +356,7 @@
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
- }, null, true, false);
+ }, null, true, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
@@ -294,7 +367,8 @@
@Test
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -306,7 +380,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
- }, null, false, false);
+ }, null, false, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -314,11 +388,12 @@
@Test
public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
- }, null, true, false);
+ }, null, true, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -326,7 +401,8 @@
@Test
public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
}
@@ -335,7 +411,7 @@
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
- true, true);
+ true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
}
@@ -348,7 +424,7 @@
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
- }, null, true, true);
+ }, null, true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
@@ -361,7 +437,7 @@
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true);
+ null, true, true, false, IMPORTANCE_DEFAULT);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, channelNameView.getVisibility());
@@ -372,7 +448,7 @@
public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true);
+ null, true, true, false, IMPORTANCE_DEFAULT);
final TextView blockView = mNotificationInfo.findViewById(R.id.block);
assertEquals(GONE, blockView.getVisibility());
}
@@ -381,7 +457,7 @@
public void testbindNotification_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
- true, true);
+ true, true, false, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -390,7 +466,8 @@
@Test
public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -400,7 +477,8 @@
@Test
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -410,7 +488,8 @@
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -423,7 +502,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
mTestableLooper.processAllMessages();
@@ -432,11 +512,40 @@
}
@Test
+ public void testDoesNotUpdateNotificationChannelAfterImportanceChangedSilenced()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mTestableLooper.processAllMessages();
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
+ public void testDoesNotUpdateNotificationChannelAfterImportanceChangedUnSilenced()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mTestableLooper.processAllMessages();
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
int originalImportance = mNotificationChannel.getImportance();
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -450,7 +559,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -468,7 +578,7 @@
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */);
+ true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -489,7 +599,7 @@
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */);
+ true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -510,7 +620,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -538,7 +648,7 @@
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -566,7 +676,8 @@
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true, true /* isUserSentimentNegative */);
+ true, true /* isUserSentimentNegative */, false, /* isNoisy */
+ IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
@@ -585,7 +696,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -607,7 +718,8 @@
false /* isNonblockable */,
true /* isForBlockingHelper */,
true,
- false /* isUserSentimentNegative */);
+ false /* isUserSentimentNegative */,
+ false, /* isNoisy */IMPORTANCE_DEFAULT);
NotificationGuts guts = mock(NotificationGuts.class);
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
@@ -621,7 +733,8 @@
public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -634,7 +747,8 @@
public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -666,7 +780,8 @@
true /*provisioned */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */,
+ false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -687,7 +802,8 @@
public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -701,7 +817,8 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -721,7 +838,8 @@
public void testKeepUpdatesNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -738,7 +856,8 @@
public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -759,7 +878,8 @@
public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -777,10 +897,97 @@
}
@Test
+ public void testSilenceCallsUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testUnSilenceCallsUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_LOW);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+ }
+
+ @Test
public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -795,7 +1002,8 @@
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -812,7 +1020,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
- }, null, null, true, true);
+ }, null, null, true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -830,7 +1038,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
- }, null, null, true, false);
+ }, null, null, true, false, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -866,7 +1074,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false);
+ }, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -894,7 +1102,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false);
+ }, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -913,7 +1121,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
- null, true, false);
+ null, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -933,7 +1141,8 @@
0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -956,7 +1165,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
- true, true);
+ true, true, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -972,7 +1181,8 @@
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -984,7 +1194,8 @@
public void testUndoText_block() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -993,10 +1204,39 @@
}
@Test
+ public void testUndoText_silence() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+ assertEquals(mContext.getString(R.string.notification_channel_silenced),
+ confirmationText.getText());
+ }
+
+ @Test
+ public void testUndoText_unsilence() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+ assertEquals(mContext.getString(R.string.notification_channel_unsilenced),
+ confirmationText.getText());
+ }
+
+ @Test
public void testNoHeaderOnConfirmation() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1007,7 +1247,8 @@
public void testHeaderOnUndo() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
new file mode 100644
index 0000000..f8ad298
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
+
+ private static final int SCREEN_HEIGHT = 2000;
+ private static final int EMPTY_MARGIN = 0;
+ private static final int EMPTY_HEIGHT = 0;
+ private static final boolean SECURE_LOCKED = false;
+ private static final boolean PULSING_NO = false;
+ private static final float ZERO_DRAG = 0.f;
+ private static final float OPAQUE = 1.f;
+ private static final float TRANSPARENT = 0.f;
+
+ private KeyguardClockPositionAlgorithm mClockPositionAlgorithm;
+ private KeyguardClockPositionAlgorithm.Result mClockPosition;
+ private int mNotificationStackHeight;
+ private float mPanelExpansion;
+ private int mKeyguardStatusHeight;
+ private float mDark;
+
+ @Before
+ public void setUp() {
+ mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm();
+ mClockPosition = new KeyguardClockPositionAlgorithm.Result();
+ }
+
+ @Test
+ public void clockPositionMiddleOfScreenOnAOD() {
+ // GIVEN on AOD and both stack scroll and clock have 0 height
+ givenAOD();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+ assertThat(mClockPosition.clockY).isEqualTo(1000);
+ // AND the clock is opaque and positioned on the left.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionAdjustsForKeyguardStatusOnAOD() {
+ // GIVEN on AOD with a clock of height 100
+ givenAOD();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = 100;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position adjusts for the clock height (SCREEN_HEIGHT / 2 - 100).
+ assertThat(mClockPosition.clockY).isEqualTo(900);
+ // AND the clock is opaque and positioned on the left.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionLargeClockOnAOD() {
+ // GIVEN on AOD with a full screen clock
+ givenAOD();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = SCREEN_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position doesn't overflow the screen.
+ assertThat(mClockPosition.clockY).isEqualTo(0);
+ // AND the clock is opaque and positioned on the left.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionMiddleOfScreenOnLockScreen() {
+ // GIVEN on lock screen with stack scroll and clock of 0 height
+ givenLockScreen();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+ assertThat(mClockPosition.clockY).isEqualTo(1000);
+ // AND the clock is opaque and positioned on the left.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionWithStackScrollExpandOnLockScreen() {
+ // GIVEN on lock screen with stack scroll of height 500
+ givenLockScreen();
+ mNotificationStackHeight = 500;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position adjusts for stack scroll height ( (SCREEN_HEIGHT - 500 ) / 2).
+ assertThat(mClockPosition.clockY).isEqualTo(750);
+ // AND the clock is opaque and positioned on the left.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionWithPartialDragOnLockScreen() {
+ // GIVEN dragging up on lock screen
+ givenLockScreen();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ mPanelExpansion = 0.5f;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position adjusts with drag gesture.
+ assertThat(mClockPosition.clockY).isLessThan(1000);
+ // AND the clock is positioned on the left and not fully opaque.
+ assertThat(mClockPosition.clockX).isEqualTo(0);
+ assertThat(mClockPosition.clockAlpha).isLessThan(OPAQUE);
+ }
+
+ @Test
+ public void clockPositionWithFullDragOnLockScreen() {
+ // GIVEN the lock screen is dragged up
+ givenLockScreen();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ mPanelExpansion = 0.f;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock is transparent.
+ assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
+ }
+
+ @Test
+ public void largeClockOnLockScreenIsTransparent() {
+ // GIVEN on lock screen with a full screen clock
+ givenLockScreen();
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = SCREEN_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock is transparent
+ assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
+ }
+
+ private void givenAOD() {
+ mPanelExpansion = 1.f;
+ mDark = 1.f;
+ }
+
+ private void givenLockScreen() {
+ mPanelExpansion = 1.f;
+ mDark = 0.f;
+ }
+
+ private void positionClock() {
+ mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
+ mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mDark, SECURE_LOCKED,
+ PULSING_NO, ZERO_DRAG);
+ mClockPositionAlgorithm.run(mClockPosition);
+ }
+}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index ddd0c2c..a947ea1 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -2832,7 +2832,7 @@
// ACTION: Logs the end to end time taken by all provisioning tasks.
PROVISIONING_TOTAL_TASK_TIME_MS = 627;
- // OPEN: Settings > Privacy
+ // OPEN: Settings > Security
// CATEGORY: SETTINGS
// OS: O
ENTERPRISE_PRIVACY_SETTINGS = 628;
@@ -6579,6 +6579,11 @@
// OS: Q
BIOMETRIC_ENROLL_ACTIVITY = 1586;
+ // OPEN: Settings > Privacy
+ // CATEGORY: SETTINGS
+ // OS: Q
+ TOP_LEVEL_PRIVACY = 1587;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e89b951..5c189ce 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1672,22 +1672,23 @@
client -> client.setState(clientState)));
}
- private void scheduleNotifyClientsOfServicesStateChange(UserState userState) {
+ private void scheduleNotifyClientsOfServicesStateChangeLocked(UserState userState) {
+ updateRecommendedUiTimeoutLocked(userState);
mMainHandler.sendMessage(obtainMessage(
AccessibilityManagerService::sendServicesStateChanged,
- this, userState.mUserClients));
+ this, userState.mUserClients, getRecommendedTimeoutMillisLocked(userState)));
}
private void sendServicesStateChanged(
- RemoteCallbackList<IAccessibilityManagerClient> userClients) {
- notifyClientsOfServicesStateChange(mGlobalClients);
- notifyClientsOfServicesStateChange(userClients);
+ RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout) {
+ notifyClientsOfServicesStateChange(mGlobalClients, uiTimeout);
+ notifyClientsOfServicesStateChange(userClients, uiTimeout);
}
private void notifyClientsOfServicesStateChange(
- RemoteCallbackList<IAccessibilityManagerClient> clients) {
+ RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout) {
clients.broadcast(ignoreRemoteException(
- client -> client.notifyServicesStateChanged()));
+ client -> client.notifyServicesStateChanged(uiTimeout)));
}
private void scheduleUpdateInputFilter(UserState userState) {
@@ -1701,24 +1702,6 @@
this, userState));
}
- private void scheduleSetAllClientsMinimumUiTimeout(UserState userState) {
- mMainHandler.sendMessage(obtainMessage(
- AccessibilityManagerService::sendMinimumUiTimeoutChanged,
- this, userState.mUserClients, userState.mMinimumUiTimeout));
- }
-
- private void sendMinimumUiTimeoutChanged(
- RemoteCallbackList<IAccessibilityManagerClient> userClients, int uiTimeout) {
- notifyClientsOfServicesMinimumUiTimeoutChange(mGlobalClients, uiTimeout);
- notifyClientsOfServicesMinimumUiTimeoutChange(userClients, uiTimeout);
- }
-
- private void notifyClientsOfServicesMinimumUiTimeoutChange(
- RemoteCallbackList<IAccessibilityManagerClient> clients, int uiTimeout) {
- clients.broadcast(ignoreRemoteException(
- client -> client.setMinimumUiTimeout(uiTimeout)));
- }
-
private void updateInputFilter(UserState userState) {
if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return;
@@ -1852,7 +1835,6 @@
scheduleUpdateClientsIfNeededLocked(userState);
updateRelevantEventsLocked(userState);
updateAccessibilityButtonTargetsLocked(userState);
- updateMinimumUiTimeoutLocked(userState);
}
private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
@@ -1971,7 +1953,7 @@
somethingChanged |= readAutoclickEnabledSettingLocked(userState);
somethingChanged |= readAccessibilityShortcutSettingLocked(userState);
somethingChanged |= readAccessibilityButtonSettingsLocked(userState);
- somethingChanged |= readUserMinimumUiTimeoutSettingsLocked(userState);
+ somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
return somethingChanged;
}
@@ -2083,7 +2065,7 @@
}
userState.mServiceToEnableWithShortcut = componentNameToEnable;
- scheduleNotifyClientsOfServicesStateChange(userState);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
return true;
}
@@ -2118,17 +2100,20 @@
return true;
}
- private boolean readUserMinimumUiTimeoutSettingsLocked(UserState userState) {
- final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, 0,
- userState.mUserId) == 1;
- final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, 0,
+ private boolean readUserRecommendedUiTimeoutSettingsLocked(UserState userState) {
+ final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0,
userState.mUserId);
- if (enabled != userState.mUserMinimumUiTimeoutEnabled
- || timeout != userState.mUserMinimumUiTimeout) {
- userState.mUserMinimumUiTimeoutEnabled = enabled;
- userState.mUserMinimumUiTimeout = timeout;
+ final int interactiveUiTimeout = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0,
+ userState.mUserId);
+ if (nonInteractiveUiTimeout != userState.mUserNonInteractiveUiTimeout
+ || interactiveUiTimeout != userState.mUserInteractiveUiTimeout) {
+ userState.mUserNonInteractiveUiTimeout = nonInteractiveUiTimeout;
+ userState.mUserInteractiveUiTimeout = interactiveUiTimeout;
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
return true;
}
return false;
@@ -2300,25 +2285,33 @@
}
}
- private void updateMinimumUiTimeoutLocked(UserState userState) {
- int newUiTimeout = 0;
- if (userState.mUserMinimumUiTimeoutEnabled) {
- newUiTimeout = userState.mUserMinimumUiTimeout;
- } else {
+ private void updateRecommendedUiTimeoutLocked(UserState userState) {
+ int newNonInteractiveUiTimeout = userState.mUserNonInteractiveUiTimeout;
+ int newInteractiveUiTimeout = userState.mUserInteractiveUiTimeout;
+ // read from a11y services if user does not specify value
+ if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) {
+ int serviceNonInteractiveUiTimeout = 0;
+ int serviceInteractiveUiTimeout = 0;
final List<AccessibilityServiceConnection> services = userState.mBoundServices;
- final int numServices = services.size();
- for (int i = 0; i < numServices; i++) {
- final int serviceUiTimeout = services.get(i).getServiceInfo()
- .getMinimumUiTimeoutMillis();
- if (newUiTimeout < serviceUiTimeout) {
- newUiTimeout = serviceUiTimeout;
+ for (int i = 0; i < services.size(); i++) {
+ int timeout = services.get(i).getServiceInfo().getInteractiveUiTimeoutMillis();
+ if (serviceInteractiveUiTimeout < timeout) {
+ serviceInteractiveUiTimeout = timeout;
+ }
+ timeout = services.get(i).getServiceInfo().getNonInteractiveUiTimeoutMillis();
+ if (serviceNonInteractiveUiTimeout < timeout) {
+ serviceNonInteractiveUiTimeout = timeout;
}
}
+ if (newNonInteractiveUiTimeout == 0) {
+ newNonInteractiveUiTimeout = serviceNonInteractiveUiTimeout;
+ }
+ if (newInteractiveUiTimeout == 0) {
+ newInteractiveUiTimeout = serviceInteractiveUiTimeout;
+ }
}
- if (newUiTimeout != userState.mMinimumUiTimeout) {
- userState.mMinimumUiTimeout = newUiTimeout;
- scheduleSetAllClientsMinimumUiTimeout(userState);
- }
+ userState.mNonInteractiveUiTimeout = newNonInteractiveUiTimeout;
+ userState.mInteractiveUiTimeout = newInteractiveUiTimeout;
}
@GuardedBy("mLock")
@@ -2473,19 +2466,24 @@
}
/**
- * Get the minimum timeout for changes to the UI needed by this user. Controls should remain
- * on the screen for at least this long to give users time to react.
+ * Get the recommended timeout of interactive controls and non-interactive controls.
*
- * @return The minimum timeout for the current user in milliseconds.
+ * @return A long for pair of {@code int}s. First integer for interactive one, and second
+ * integer for non-interactive one.
*/
@Override
- public int getMinimumUiTimeout() {
+ public long getRecommendedTimeoutMillis() {
synchronized(mLock) {
final UserState userState = getCurrentUserStateLocked();
- return userState.mMinimumUiTimeout;
+ return getRecommendedTimeoutMillisLocked(userState);
}
}
+ private long getRecommendedTimeoutMillisLocked(UserState userState) {
+ return IntPair.of(userState.mInteractiveUiTimeout,
+ userState.mNonInteractiveUiTimeout);
+ }
+
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
@@ -2503,7 +2501,8 @@
pw.append(", navBarMagnificationEnabled="
+ userState.mIsNavBarMagnificationEnabled);
pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled);
- pw.append(", minimumUiTimeout=" + userState.mMinimumUiTimeout);
+ pw.append(", nonInteractiveUiTimeout=" + userState.mNonInteractiveUiTimeout);
+ pw.append(", interactiveUiTimeout=" + userState.mInteractiveUiTimeout);
if (mUiAutomationManager.isUiAutomationRunningLocked()) {
pw.append(", ");
mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
@@ -2819,7 +2818,7 @@
AccessibilityManagerService.UserState userState = getUserStateLocked(mCurrentUserId);
onUserStateChangedLocked(userState);
if (serviceInfoChanged) {
- scheduleNotifyClientsOfServicesStateChange(userState);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
}
}
@@ -3794,7 +3793,8 @@
public ComponentName mServiceToEnableWithShortcut;
public int mLastSentClientState = -1;
- public int mMinimumUiTimeout = 0;
+ public int mNonInteractiveUiTimeout = 0;
+ public int mInteractiveUiTimeout = 0;
private int mSoftKeyboardShowMode = 0;
@@ -3809,8 +3809,8 @@
public boolean mIsPerformGesturesEnabled;
public boolean mIsFilterKeyEventsEnabled;
public boolean mAccessibilityFocusOnlyInActiveWindow;
- public boolean mUserMinimumUiTimeoutEnabled;
- public int mUserMinimumUiTimeout;
+ public int mUserNonInteractiveUiTimeout;
+ public int mUserInteractiveUiTimeout;
private boolean mBindInstantServiceAllowed;
@@ -3850,8 +3850,9 @@
// Clear event management state.
mLastSentClientState = -1;
- // clear minimum ui timeout
- mMinimumUiTimeout = 0;
+ // clear UI timeout
+ mNonInteractiveUiTimeout = 0;
+ mInteractiveUiTimeout = 0;
// Clear state persisted in settings.
mEnabledServices.clear();
@@ -3862,8 +3863,8 @@
mServiceAssignedToAccessibilityButton = null;
mIsNavBarMagnificationAssignedToAccessibilityButton = false;
mIsAutoclickEnabled = false;
- mUserMinimumUiTimeoutEnabled = false;
- mUserMinimumUiTimeout = 0;
+ mUserNonInteractiveUiTimeout = 0;
+ mUserInteractiveUiTimeout = 0;
}
public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
@@ -3871,7 +3872,7 @@
serviceConnection.onAdded();
mBoundServices.add(serviceConnection);
mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection);
- scheduleNotifyClientsOfServicesStateChange(this);
+ scheduleNotifyClientsOfServicesStateChangeLocked(this);
}
}
@@ -3897,7 +3898,7 @@
AccessibilityServiceConnection boundClient = mBoundServices.get(i);
mComponentNameToServiceMap.put(boundClient.mComponentName, boundClient);
}
- scheduleNotifyClientsOfServicesStateChange(this);
+ scheduleNotifyClientsOfServicesStateChangeLocked(this);
}
/**
@@ -4108,11 +4109,11 @@
private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
- private final Uri mUserMinimumUiTimeoutEnabledUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED);
+ private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
- private final Uri mUserMinimumUiTimeoutUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS);
+ private final Uri mUserInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
public AccessibilityContentObserver(Handler handler) {
super(handler);
@@ -4149,9 +4150,9 @@
contentResolver.registerContentObserver(
mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(
- mUserMinimumUiTimeoutEnabledUri, false, this, UserHandle.USER_ALL);
+ mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(
- mUserMinimumUiTimeoutUri, false, this, UserHandle.USER_ALL);
+ mUserInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
}
@Override
@@ -4202,11 +4203,9 @@
if (readAccessibilityButtonSettingsLocked(userState)) {
onUserStateChangedLocked(userState);
}
- } else if (mUserMinimumUiTimeoutEnabledUri.equals(uri)
- || mUserMinimumUiTimeoutUri.equals(uri)) {
- if (readUserMinimumUiTimeoutSettingsLocked(userState)) {
- updateMinimumUiTimeoutLocked(userState);
- }
+ } else if (mUserNonInteractiveUiTimeoutUri.equals(uri)
+ || mUserInteractiveUiTimeoutUri.equals(uri)) {
+ readUserRecommendedUiTimeoutSettingsLocked(userState);
}
}
}
diff --git a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java b/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java
index a437a39..9cab1ed 100644
--- a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java
@@ -23,12 +23,15 @@
import android.service.intelligence.InteractionContext;
import android.service.intelligence.InteractionSessionId;
import android.util.Slog;
+import android.view.intelligence.ContentCaptureEvent;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import com.android.server.AbstractRemoteService;
import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;
import java.io.PrintWriter;
+import java.util.List;
final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks {
@@ -45,15 +48,15 @@
ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
@NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
@NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
- int taskId, int displayId, int localSessionId, int globalSessionId, int flags,
+ int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
boolean bindInstantServiceAllowed, boolean verbose) {
mLock = lock;
mActivityToken = activityToken;
mService = service;
+ mId = Preconditions.checkNotNull(sessionId);
mRemoteService = new RemoteIntelligenceService(context,
IntelligenceService.SERVICE_INTERFACE, serviceComponentName, userId, this,
bindInstantServiceAllowed, verbose);
- mId = new InteractionSessionId(globalSessionId, localSessionId);
mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
}
@@ -66,6 +69,13 @@
}
/**
+ * Notifies the {@link IntelligenceService} of a batch of events.
+ */
+ public void sendEventsLocked(List<ContentCaptureEvent> events) {
+ mRemoteService.onContentCaptureEventsRequest(mId, events);
+ }
+
+ /**
* Cleans up the session and remove itself from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
@@ -79,7 +89,7 @@
mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
}
} finally {
- mService.removeSessionLocked(mInterationContext.getActivityComponent());
+ mService.removeSessionLocked(mId);
}
}
@@ -95,27 +105,25 @@
}
@Override // from RemoteScreenObservationServiceCallbacks
- public void onSessionLifecycleRequestFailureOrTimeout(boolean timedOut) {
+ public void onFailureOrTimeout(boolean timedOut) {
// TODO(b/111276913): log metrics on whether timed out or not
if (mService.isDebug()) {
- Slog.d(TAG, "onSessionLifecycleRequestFailure(" + mId + "): timed out=" + timedOut);
+ Slog.d(TAG, "onFailureOrTimeout(" + mId + "): timed out=" + timedOut);
}
synchronized (mLock) {
removeSelfLocked(/* notifyRemoteService= */ false);
}
}
- /**
- * Gets global id, unique per {@link IntelligencePerUserService}.
- */
- public int getGlobalSessionId() {
- return mId.getGlobalId();
- }
-
@GuardedBy("mLock")
public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
pw.print(prefix); pw.print("id: "); mId.dump(pw); pw.println();
pw.print(prefix); pw.print("context: "); mInterationContext.dump(pw); pw.println();
pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
}
+
+ @Override
+ public String toString() {
+ return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
+ }
}
diff --git a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java
index 4ea9036..43d4a44 100644
--- a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.os.IBinder;
import android.os.UserManager;
+import android.service.intelligence.InteractionSessionId;
+import android.view.intelligence.ContentCaptureEvent;
import android.view.intelligence.IIntelligenceManager;
import com.android.internal.annotations.GuardedBy;
@@ -35,6 +37,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
/**
* A service used to observe the contents of the screen.
@@ -85,9 +88,11 @@
@Override
public void startSession(int userId, @NonNull IBinder activityToken,
- @NonNull ComponentName componentName, int localSessionId, int flags,
- @NonNull IResultReceiver result) {
+ @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
+ int flags, @NonNull IResultReceiver result) {
Preconditions.checkNotNull(activityToken);
+ Preconditions.checkNotNull(componentName);
+ Preconditions.checkNotNull(sessionId);
// TODO(b/111276913): refactor getTaskIdForActivity() to also return ComponentName,
// so we don't pass it on startSession (same for Autofill)
@@ -99,19 +104,29 @@
synchronized (mLock) {
final IntelligencePerUserService service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, componentName, taskId, displayId,
- localSessionId, flags, result);
+ sessionId, flags, result);
}
}
@Override
- public void finishSession(int userId, @NonNull IBinder activityToken,
- @NonNull ComponentName componentName, int localSessionId, int globalSessionId) {
- Preconditions.checkNotNull(activityToken);
+ public void sendEvents(int userId, @NonNull InteractionSessionId sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ Preconditions.checkNotNull(sessionId);
+ Preconditions.checkNotNull(events);
synchronized (mLock) {
final IntelligencePerUserService service = getServiceForUserLocked(userId);
- service.finishSessionLocked(activityToken, componentName, localSessionId,
- globalSessionId);
+ service.sendEventsLocked(sessionId, events);
+ }
+ }
+
+ @Override
+ public void finishSession(int userId, @NonNull InteractionSessionId sessionId) {
+ Preconditions.checkNotNull(sessionId);
+
+ synchronized (mLock) {
+ final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ service.finishSessionLocked(sessionId);
}
}
diff --git a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java
index b62b239..584b872 100644
--- a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java
@@ -25,14 +25,18 @@
import android.content.pm.ServiceInfo;
import android.os.IBinder;
import android.os.RemoteException;
+import android.service.intelligence.InteractionSessionId;
import android.util.ArrayMap;
import android.util.Slog;
+import android.view.intelligence.ContentCaptureEvent;
+import android.view.intelligence.IntelligenceManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import com.android.server.AbstractPerUserSystemService;
import java.io.PrintWriter;
+import java.util.List;
/**
* Per-user instance of {@link IntelligenceManagerService}.
@@ -42,11 +46,9 @@
private static final String TAG = "IntelligencePerUserService";
- private static int sNextSessionId;
-
- // TODO(b/111276913): should key by componentName + taskId or ActivityToken
@GuardedBy("mLock")
- private final ArrayMap<ComponentName, ContentCaptureSession> mSessions = new ArrayMap<>();
+ private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions =
+ new ArrayMap<>();
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
@@ -83,8 +85,9 @@
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
public void startSessionLocked(@NonNull IBinder activityToken,
- @NonNull ComponentName componentName, int taskId, int displayId, int localSessionId,
- int flags, @NonNull IResultReceiver resultReceiver) {
+ @NonNull ComponentName componentName, int taskId, int displayId,
+ @NonNull InteractionSessionId sessionId, int flags,
+ @NonNull IResultReceiver resultReceiver) {
final ComponentName serviceComponentName = getServiceComponentName();
if (serviceComponentName == null) {
// TODO(b/111276913): this happens when the system service is starting, we should
@@ -94,16 +97,16 @@
return;
}
- ContentCaptureSession session = mSessions.get(componentName);
+ ContentCaptureSession session = mSessions.get(sessionId);
if (session != null) {
if (mMaster.debug) {
- Slog.d(TAG, "startSession(): reusing session " + session.getGlobalSessionId()
- + " for " + componentName);
+ Slog.d(TAG, "startSession(): reusing session " + sessionId + " for "
+ + componentName);
}
// TODO(b/111276913): check if local ids match and decide what to do if they don't
// TODO(b/111276913): should we call session.notifySessionStartedLocked() again??
// if not, move notifySessionStartedLocked() into session constructor
- sendToClient(resultReceiver, session.getGlobalSessionId());
+ sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE);
return;
}
@@ -111,45 +114,53 @@
final boolean bindInstantServiceAllowed = false;
session = new ContentCaptureSession(getContext(), mUserId, mLock, activityToken,
- this, serviceComponentName, componentName, taskId, displayId, localSessionId,
- ++sNextSessionId, flags, bindInstantServiceAllowed, mMaster.verbose);
+ this, serviceComponentName, componentName, taskId, displayId, sessionId, flags,
+ bindInstantServiceAllowed, mMaster.verbose);
if (mMaster.verbose) {
- Slog.v(TAG, "startSession(): new session for " + componentName + "; globalId ="
- + session.getGlobalSessionId());
+ Slog.v(TAG, "startSession(): new session for " + componentName + " and id "
+ + sessionId);
}
- mSessions.put(componentName, session);
+ mSessions.put(sessionId, session);
session.notifySessionStartedLocked();
- sendToClient(resultReceiver, session.getGlobalSessionId());
+ sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE);
}
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
- public void finishSessionLocked(@NonNull IBinder activityToken,
- @NonNull ComponentName componentName, int localSessionId, int globalSessionId) {
- final ContentCaptureSession session = mSessions.get(componentName);
+ public void finishSessionLocked(@NonNull InteractionSessionId sessionId) {
+ final ContentCaptureSession session = mSessions.get(sessionId);
if (session == null) {
- Slog.w(TAG, "finishSession(): no session for " + componentName);
+ Slog.w(TAG, "finishSession(): no session with id" + sessionId);
return;
}
if (mMaster.verbose) {
- Slog.v(TAG, "finishSession(): comp=" + componentName + "; globalId ="
- + session.getGlobalSessionId());
+ Slog.v(TAG, "finishSession(): " + session);
}
- // TODO(b/111276913): check if all arguments match existing session and throw exception if
- // not. Or just use componentName if we change AIDL to pass just ApplicationToken and
- // retrieve componentName from AMInternal
session.removeSelfLocked(true);
}
@GuardedBy("mLock")
- public void removeSessionLocked(@NonNull ComponentName key) {
- mSessions.remove(key);
+ public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ final ContentCaptureSession session = mSessions.get(sessionId);
+ if (session == null) {
+ Slog.w(TAG, "sendEvents(): no session for " + sessionId);
+ return;
+ }
+ if (mMaster.verbose) {
+ Slog.v(TAG, "sendEvents(): id=" + sessionId + "; events =" + events.size());
+ }
+ session.sendEventsLocked(events);
+ }
+
+ @GuardedBy("mLock")
+ public void removeSessionLocked(@NonNull InteractionSessionId sessionId) {
+ mSessions.remove(sessionId);
}
@Override
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
- pw.print(prefix); pw.print("next id: "); pw.println(sNextSessionId);
if (mSessions.isEmpty()) {
pw.print(prefix); pw.println("no sessions");
} else {
diff --git a/services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java
index ee66b4e..9d241fb 100644
--- a/services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java
+++ b/services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java
@@ -27,9 +27,12 @@
import android.service.intelligence.InteractionSessionId;
import android.text.format.DateUtils;
import android.util.Slog;
+import android.view.intelligence.ContentCaptureEvent;
import com.android.server.AbstractRemoteService;
+import java.util.List;
+
final class RemoteIntelligenceService extends AbstractRemoteService {
private static final String TAG = "RemoteIntelligenceService";
@@ -79,44 +82,89 @@
scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
}
- private static final class PendingSessionLifecycleRequest
+ /**
+ * Called by {@link ContentCaptureSession} to send a batch of events to the service.
+ */
+ public void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
+ }
+
+
+ private abstract static class MyPendingRequest
extends PendingRequest<RemoteIntelligenceService> {
+ protected final InteractionSessionId mSessionId;
- private final InteractionContext mContext;
- private final InteractionSessionId mSessionId;
-
- protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
- @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
+ private MyPendingRequest(@NonNull RemoteIntelligenceService service,
+ @NonNull InteractionSessionId sessionId) {
super(service);
- mContext = context;
mSessionId = sessionId;
}
@Override // from PendingRequest
- public void run() {
+ protected final void onTimeout(RemoteIntelligenceService remoteService) {
+ Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
+ + mSessionId);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
+ }
+
+ @Override // from PendingRequest
+ public final void run() {
final RemoteIntelligenceService remoteService = getService();
if (remoteService != null) {
try {
- remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+ myRun(remoteService);
+ // We don't expect the service to call us back, so we finish right away.
+ finish();
} catch (RemoteException e) {
- Slog.w(TAG, "exception handling PendingSessionLifecycleRequest for "
+ Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
+ mSessionId + ": " + e);
- remoteService.mCallbacks
- .onSessionLifecycleRequestFailureOrTimeout(/* timedOut= */ false);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
}
}
}
- @Override // from PendingRequest
- protected void onTimeout(RemoteIntelligenceService remoteService) {
- Slog.w(TAG, "timed out handling PendingSessionLifecycleRequest for "
- + mSessionId);
- remoteService.mCallbacks
- .onSessionLifecycleRequestFailureOrTimeout(/* timedOut= */ true);
+ protected abstract void myRun(@NonNull RemoteIntelligenceService service)
+ throws RemoteException;
+
+ }
+
+ private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
+
+ private final InteractionContext mContext;
+
+ protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
+ @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
+ super(service, sessionId);
+ mContext = context;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
+ remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+ }
+ }
+
+ private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
+
+ private final List<ContentCaptureEvent> mEvents;
+
+ protected PendingOnContentCaptureEventsRequest(@NonNull RemoteIntelligenceService service,
+ @NonNull InteractionSessionId sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ super(service, sessionId);
+ mEvents = events;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
+ remoteService.mService.onContentCaptureEvents(mSessionId, mEvents);
}
}
public interface RemoteIntelligenceServiceCallbacks extends VultureCallback {
- void onSessionLifecycleRequestFailureOrTimeout(boolean timedOut);
+ // To keep it simple, we use the same callback for all failures / timeouts.
+ void onFailureOrTimeout(boolean timedOut);
}
}
diff --git a/services/core/java/com/android/server/AbstractRemoteService.java b/services/core/java/com/android/server/AbstractRemoteService.java
index 1d3a34c..181d7fd 100644
--- a/services/core/java/com/android/server/AbstractRemoteService.java
+++ b/services/core/java/com/android/server/AbstractRemoteService.java
@@ -366,11 +366,12 @@
mCompleted = true;
}
- Slog.w(mTag, "timed out");
final S remoteService = mWeakService.get();
if (remoteService != null) {
- Slog.w(mTag, " timed out after " + service.getRemoteRequestMillis() + " ms");
+ Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
onTimeout(remoteService);
+ } else {
+ Slog.w(mTag, "timed out (no service)");
}
};
mServiceHandler.postAtTime(mTimeoutTrigger,
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index cd98263..5814064 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
@@ -36,8 +37,11 @@
import android.app.AppOpsManager.HistoricalPackageOps;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -645,6 +649,26 @@
}
}
+ final IntentFilter packageSuspendFilter = new IntentFilter();
+ packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+ packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+ final String[] changedPkgs = intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
+ for (int i = 0; i < changedUids.length; i++) {
+ final int changedUid = changedUids[i];
+ final String changedPkg = changedPkgs[i];
+ // We trust packagemanager to insert matching uid and packageNames in the extras
+ mHandler.sendMessage(PooledLambda.obtainMessage(AppOpsService::notifyOpChanged,
+ AppOpsService.this, callbacks, OP_PLAY_AUDIO, changedUid, changedPkg));
+ }
+ }
+ }, packageSuspendFilter);
+
PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
packageManagerInternal.setExternalSourcesPolicy(
@@ -1210,13 +1234,29 @@
@Override
public void setMode(int code, int uid, String packageName, int mode) {
+ setMode(code, uid, packageName, mode, true, false);
+ }
+
+ /**
+ * Sets the mode for a certain op and uid.
+ *
+ * @param code The op code to set
+ * @param uid The UID for which to set
+ * @param packageName The package for which to set
+ * @param mode The new mode to set
+ * @param verifyUid Iff {@code true}, check that the package name belongs to the uid
+ * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid ==
+ * false})
+ */
+ private void setMode(int code, int uid, @NonNull String packageName, int mode,
+ boolean verifyUid, boolean isPrivileged) {
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
verifyIncomingOp(code);
ArraySet<ModeCallback> repCbs = null;
code = AppOpsManager.opToSwitch(code);
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
- Op op = getOpLocked(code, uid, packageName, true);
+ Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged);
if (op != null) {
if (op.mode != mode) {
op.mode = mode;
@@ -1575,7 +1615,7 @@
&& uidState.opModes.indexOfKey(code) >= 0) {
return uidState.opModes.get(code);
}
- Op op = getOpLocked(code, uid, resolvedPackageName, false);
+ Op op = getOpLocked(code, uid, resolvedPackageName, false, true, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -1918,7 +1958,7 @@
}
ClientState client = (ClientState) token;
synchronized (this) {
- Op op = getOpLocked(code, uid, resolvedPackageName, true);
+ Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false);
if (op == null) {
return;
}
@@ -2172,6 +2212,43 @@
return ops;
}
+ /**
+ * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>.
+ *
+ * <p>Usually callers should use {@link #getOpLocked} and not call this directly.
+ *
+ * @param uid The uid the of the package
+ * @param packageName The package name for which to get the state for
+ * @param edit Iff {@code true} create the {@link Ops} object if not yet created
+ * @param isPrivileged Whether the package is privileged or not
+ *
+ * @return The {@link Ops state} of all ops for the package
+ */
+ private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName,
+ boolean edit, boolean isPrivileged) {
+ UidState uidState = getUidStateLocked(uid, edit);
+ if (uidState == null) {
+ return null;
+ }
+
+ if (uidState.pkgOps == null) {
+ if (!edit) {
+ return null;
+ }
+ uidState.pkgOps = new ArrayMap<>();
+ }
+
+ Ops ops = uidState.pkgOps.get(packageName);
+ if (ops == null) {
+ if (!edit) {
+ return null;
+ }
+ ops = new Ops(packageName, uidState, isPrivileged);
+ uidState.pkgOps.put(packageName, ops);
+ }
+ return ops;
+ }
+
private void scheduleWriteLocked() {
if (!mWriteScheduled) {
mWriteScheduled = true;
@@ -2188,9 +2265,29 @@
}
}
- private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
- Ops ops = getOpsRawLocked(uid, packageName, edit,
- false /* uidMismatchExpected */);
+ /**
+ * Get the state of an op for a uid.
+ *
+ * @param code The code of the op
+ * @param uid The uid the of the package
+ * @param packageName The package name for which to get the state for
+ * @param edit Iff {@code true} create the {@link Op} object if not yet created
+ * @param verifyUid Iff {@code true} check that the package belongs to the uid
+ * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid
+ * == false})
+ *
+ * @return The {@link Op state} of the op
+ */
+ private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit,
+ boolean verifyUid, boolean isPrivileged) {
+ Ops ops;
+
+ if (verifyUid) {
+ ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */);
+ } else {
+ ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
+ }
+
if (ops == null) {
return null;
}
@@ -3948,5 +4045,11 @@
mProfileOwners = owners;
}
}
+
+ @Override
+ public void setMode(int code, int uid, @NonNull String packageName, int mode,
+ boolean isPrivileged) {
+ AppOpsService.this.setMode(code, uid, packageName, mode, false, isPrivileged);
+ }
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 93bdcbb..046442a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -83,6 +84,7 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
@@ -111,6 +113,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Set;
/**
@@ -541,7 +544,7 @@
}
}
- private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
+ private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
PackageManager pm = mContext.getPackageManager();
String systemPackageName = mContext.getPackageName();
ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
@@ -646,16 +649,14 @@
that matches the signature of at least one package on this list.
*/
Resources resources = mContext.getResources();
- ArrayList<String> providerPackageNames = new ArrayList<>();
String[] pkgs = resources.getStringArray(
com.android.internal.R.array.config_locationProviderPackageNames);
if (D) {
Log.d(TAG, "certificates for location providers pulled from: " +
Arrays.toString(pkgs));
}
- if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
- ensureFallbackFusedProviderPresentLocked(providerPackageNames);
+ ensureFallbackFusedProviderPresentLocked(pkgs);
// bind to network provider
LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
@@ -664,8 +665,7 @@
NETWORK_LOCATION_SERVICE_ACTION,
com.android.internal.R.bool.config_enableNetworkLocationOverlay,
com.android.internal.R.string.config_networkLocationProviderPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames,
- mLocationHandler);
+ com.android.internal.R.array.config_locationProviderPackageNames);
if (networkProvider != null) {
mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
mProxyProviders.add(networkProvider);
@@ -681,8 +681,7 @@
FUSED_LOCATION_SERVICE_ACTION,
com.android.internal.R.bool.config_enableFusedLocationOverlay,
com.android.internal.R.string.config_fusedLocationProviderPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames,
- mLocationHandler);
+ com.android.internal.R.array.config_locationProviderPackageNames);
if (fusedLocationProvider != null) {
addProviderLocked(fusedLocationProvider);
mProxyProviders.add(fusedLocationProvider);
@@ -697,8 +696,7 @@
mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
com.android.internal.R.bool.config_enableGeocoderOverlay,
com.android.internal.R.string.config_geocoderProviderPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames,
- mLocationHandler);
+ com.android.internal.R.array.config_locationProviderPackageNames);
if (mGeocodeProvider == null) {
Slog.e(TAG, "no geocoder provider found");
}
@@ -708,7 +706,6 @@
mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
com.android.internal.R.string.config_geofenceProviderPackageName,
com.android.internal.R.array.config_locationProviderPackageNames,
- mLocationHandler,
mGpsGeofenceProxy,
null);
if (provider == null) {
@@ -725,7 +722,6 @@
}
ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
mContext,
- mLocationHandler,
activityRecognitionHardwareIsSupported,
activityRecognitionHardware,
com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
@@ -3427,6 +3423,48 @@
}
}
+ @Override
+ public PendingIntent createManageLocationPermissionIntent(String packageName,
+ String permission) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkArgument(permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)
+ || permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)
+ || permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION));
+
+ int callingUid = Binder.getCallingUid();
+ long token = Binder.clearCallingIdentity();
+ try {
+ String locProvider = getNetworkProviderPackage();
+ if (locProvider == null) {
+ return null;
+ }
+
+ PackageInfo locProviderInfo;
+ try {
+ locProviderInfo = mContext.getPackageManager().getPackageInfo(
+ locProvider, PackageManager.MATCH_DIRECT_BOOT_AUTO);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not resolve " + locProvider, e);
+ return null;
+ }
+
+ if (locProviderInfo.applicationInfo.uid != callingUid) {
+ throw new SecurityException("Only " + locProvider + " can call this API");
+ }
+
+ Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+ intent.putExtra(Intent.EXTRA_PERMISSION_NAME, permission);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ return PendingIntent.getActivity(mContext,
+ Objects.hash(packageName, permission), intent,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private void log(String log) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.d(TAG, log);
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index 42c836e..574f54a 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -16,8 +16,10 @@
package com.android.server;
-import android.annotation.NonNull;
+import android.annotation.MainThread;
import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -30,17 +32,21 @@
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -50,268 +56,54 @@
* Handles run-time package changes.
*/
public class ServiceWatcher implements ServiceConnection {
+
+ private static final String TAG = "ServiceWatcher";
private static final boolean D = false;
+
public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
- private final String mTag;
- private final Context mContext;
- private final PackageManager mPm;
- private final List<HashSet<Signature>> mSignatureSets;
- private final String mAction;
-
/**
- * If mServicePackageName is not null, only this package will be searched for the service that
- * implements mAction. When null, all packages in the system that matches one of the signature
- * in mSignatureSets are searched.
+ * The runner that runs on the binder retrieved from {@link ServiceWatcher}.
*/
- private final String mServicePackageName;
- private final Runnable mNewServiceWork;
- private final Handler mHandler;
-
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private int mCurrentUserId = UserHandle.USER_SYSTEM;
-
- @GuardedBy("mLock")
- private IBinder mBoundService;
- @GuardedBy("mLock")
- private ComponentName mBoundComponent;
- @GuardedBy("mLock")
- private String mBoundPackageName;
- @GuardedBy("mLock")
- private int mBoundVersion = Integer.MIN_VALUE;
- @GuardedBy("mLock")
- private int mBoundUserId = UserHandle.USER_NULL;
+ public interface BinderRunner {
+ /**
+ * Runs on the retrieved binder.
+ *
+ * @param binder the binder retrieved from the {@link ServiceWatcher}.
+ */
+ void run(IBinder binder);
+ }
public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
- List<String> initialPackageNames) {
+ String... packageNames) {
PackageManager pm = context.getPackageManager();
- ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
- for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
- String pkg = initialPackageNames.get(i);
+
+ ArrayList<HashSet<Signature>> signatureSets = new ArrayList<>(packageNames.length);
+ for (String packageName : packageNames) {
try {
- HashSet<Signature> set = new HashSet<Signature>();
- Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY
- | PackageManager.GET_SIGNATURES).signatures;
- set.addAll(Arrays.asList(sigs));
- sigSets.add(set);
+ Signature[] signatures = pm.getPackageInfo(packageName,
+ PackageManager.MATCH_SYSTEM_ONLY
+ | PackageManager.GET_SIGNATURES).signatures;
+
+ HashSet<Signature> set = new HashSet<>();
+ Collections.addAll(set, signatures);
+ signatureSets.add(set);
} catch (NameNotFoundException e) {
- Log.w("ServiceWatcher", pkg + " not found");
+ Log.w(TAG, packageName + " not found");
}
}
- return sigSets;
+ return signatureSets;
}
- public ServiceWatcher(Context context, String logTag, String action,
- int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Runnable newServiceWork,
- Handler handler) {
- mContext = context;
- mTag = logTag;
- mAction = action;
- mPm = mContext.getPackageManager();
- mNewServiceWork = newServiceWork;
- mHandler = handler;
- Resources resources = context.getResources();
-
- // Whether to enable service overlay.
- boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
- ArrayList<String> initialPackageNames = new ArrayList<String>();
- if (enableOverlay) {
- // A list of package names used to create the signatures.
- String[] pkgs = resources.getStringArray(initialPackageNamesResId);
- if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs));
- mServicePackageName = null;
- if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
- } else {
- // The default package name that is searched for service implementation when overlay is
- // disabled.
- String servicePackageName = resources.getString(defaultServicePackageNameResId);
- if (servicePackageName != null) initialPackageNames.add(servicePackageName);
- mServicePackageName = servicePackageName;
- if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName);
- }
- mSignatureSets = getSignatureSets(context, initialPackageNames);
- }
-
- /**
- * Start this watcher, including binding to the current best match and
- * re-binding to any better matches down the road.
- * <p>
- * Note that if there are no matching encryption-aware services, we may not
- * bind to a real service until after the current user is unlocked.
- *
- * @returns {@code true} if a potential service implementation was found.
- */
- public boolean start() {
- if (isServiceMissing()) return false;
-
- synchronized (mLock) {
- bindBestPackageLocked(mServicePackageName, false);
- }
-
- // listen for user change
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
- intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_NULL);
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- switchUser(userId);
- } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- unlockUser(userId);
- }
- }
- }, UserHandle.ALL, intentFilter, null, mHandler);
-
- // listen for relevant package changes if service overlay is enabled.
- if (mServicePackageName == null) {
- mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
- }
-
- return true;
- }
-
- /**
- * Check if any instance of this service is present on the device,
- * regardless of it being encryption-aware or not.
- */
- private boolean isServiceMissing() {
- final Intent intent = new Intent(mAction);
- final int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
- return mPm.queryIntentServicesAsUser(intent, flags, mCurrentUserId).isEmpty();
- }
-
- /**
- * Searches and binds to the best package, or do nothing if the best package
- * is already bound, unless force rebinding is requested.
- *
- * @param justCheckThisPackage Only consider this package, or consider all
- * packages if it is {@code null}.
- * @param forceRebind Force a rebinding to the best package if it's already
- * bound.
- * @returns {@code true} if a valid package was found to bind to.
- */
- @GuardedBy("mLock")
- private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
- Intent intent = new Intent(mAction);
- if (justCheckThisPackage != null) {
- intent.setPackage(justCheckThisPackage);
- }
- final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
- PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- mCurrentUserId);
- int bestVersion = Integer.MIN_VALUE;
- ComponentName bestComponent = null;
- boolean bestIsMultiuser = false;
- if (rInfos != null) {
- for (ResolveInfo rInfo : rInfos) {
- final ComponentName component = rInfo.serviceInfo.getComponentName();
- final String packageName = component.getPackageName();
-
- // check signature
- try {
- PackageInfo pInfo;
- pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
- | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
- if (!isSignatureMatch(pInfo.signatures)) {
- Log.w(mTag, packageName + " resolves service " + mAction
- + ", but has wrong signature, ignoring");
- continue;
- }
- } catch (NameNotFoundException e) {
- Log.wtf(mTag, e);
- continue;
- }
-
- // check metadata
- int version = Integer.MIN_VALUE;
- boolean isMultiuser = false;
- if (rInfo.serviceInfo.metaData != null) {
- version = rInfo.serviceInfo.metaData.getInt(
- EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
- isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
- }
-
- if (version > bestVersion) {
- bestVersion = version;
- bestComponent = component;
- bestIsMultiuser = isMultiuser;
- }
- }
-
- if (D) {
- Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
- (justCheckThisPackage == null ? ""
- : "(" + justCheckThisPackage + ") "), rInfos.size(),
- (bestComponent == null ? "no new best component"
- : "new best component: " + bestComponent)));
- }
- } else {
- if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
- }
-
- if (bestComponent == null) {
- Slog.w(mTag, "Odd, no component found for service " + mAction);
- unbindLocked();
- return false;
- }
-
- final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
- final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
- && bestVersion == mBoundVersion && userId == mBoundUserId;
- if (forceRebind || !alreadyBound) {
- unbindLocked();
- bindToPackageLocked(bestComponent, bestVersion, userId);
- }
- return true;
- }
-
- @GuardedBy("mLock")
- private void unbindLocked() {
- ComponentName component;
- component = mBoundComponent;
- mBoundComponent = null;
- mBoundPackageName = null;
- mBoundVersion = Integer.MIN_VALUE;
- mBoundUserId = UserHandle.USER_NULL;
- if (component != null) {
- if (D) Log.d(mTag, "unbinding " + component);
- mBoundService = null;
- mContext.unbindService(this);
- }
- }
-
- @GuardedBy("mLock")
- private void bindToPackageLocked(ComponentName component, int version, int userId) {
- Intent intent = new Intent(mAction);
- intent.setComponent(component);
- mBoundComponent = component;
- mBoundPackageName = component.getPackageName();
- mBoundVersion = version;
- mBoundUserId = userId;
- if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
- mContext.bindServiceAsUser(intent, this,
- Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
- new UserHandle(userId));
- }
-
+ /** Checks if signatures match. */
public static boolean isSignatureMatch(Signature[] signatures,
List<HashSet<Signature>> sigSets) {
if (signatures == null) return false;
// build hashset of input to test against
- HashSet<Signature> inputSet = new HashSet<Signature>();
- for (Signature s : signatures) {
- inputSet.add(s);
- }
+ HashSet<Signature> inputSet = new HashSet<>();
+ Collections.addAll(inputSet, signatures);
// test input against each of the signature sets
for (HashSet<Signature> referenceSet : sigSets) {
@@ -322,124 +114,318 @@
return false;
}
- private boolean isSignatureMatch(Signature[] signatures) {
- return isSignatureMatch(signatures, mSignatureSets);
+ private final Context mContext;
+ private final String mTag;
+ private final String mAction;
+ private final String mServicePackageName;
+ private final List<HashSet<Signature>> mSignatureSets;
+
+ private final Handler mHandler;
+
+ // this lock is held to ensure the service binder is not exposed (via runOnBinder) until after
+ // the new service initialization work has completed
+ private final Object mBindLock = new Object();
+
+ // read/write from handler thread
+ private int mCurrentUserId;
+
+ // read from any thread, write from handler thread
+ private volatile ComponentName mBestComponent;
+ private volatile int mBestVersion;
+ private volatile int mBestUserId;
+ private volatile IBinder mBestService;
+
+ public ServiceWatcher(Context context, String logTag, String action,
+ int overlaySwitchResId, int defaultServicePackageNameResId,
+ int initialPackageNamesResId, Handler handler) {
+ Resources resources = context.getResources();
+
+ mContext = context;
+ mTag = logTag;
+ mAction = action;
+
+ boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
+ if (enableOverlay) {
+ String[] pkgs = resources.getStringArray(initialPackageNamesResId);
+ mServicePackageName = null;
+ mSignatureSets = getSignatureSets(context, pkgs);
+ if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
+ } else {
+ mServicePackageName = resources.getString(defaultServicePackageNameResId);
+ mSignatureSets = getSignatureSets(context, mServicePackageName);
+ if (D) Log.d(mTag, "Overlay disabled, default package=" + mServicePackageName);
+ }
+
+ mHandler = handler;
+
+ mBestComponent = null;
+ mBestVersion = Integer.MIN_VALUE;
+ mBestUserId = UserHandle.USER_NULL;
+
+ mBestService = null;
}
- private final PackageMonitor mPackageMonitor = new PackageMonitor() {
- /**
- * Called when package has been reinstalled
- */
- @Override
- public void onPackageUpdateFinished(String packageName, int uid) {
- synchronized (mLock) {
- final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
- bindBestPackageLocked(null, forceRebind);
- }
- }
+ // called on handler thread
+ @GuardedBy("mBindLock")
+ protected void onBind() {
- @Override
- public void onPackageAdded(String packageName, int uid) {
- synchronized (mLock) {
- final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
- bindBestPackageLocked(null, forceRebind);
- }
- }
+ }
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- synchronized (mLock) {
- final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
- bindBestPackageLocked(null, forceRebind);
- }
- }
+ // called on handler thread
+ @GuardedBy("mBindLock")
+ protected void onUnbind() {
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- synchronized (mLock) {
- final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
- bindBestPackageLocked(null, forceRebind);
- }
- return super.onPackageChanged(packageName, uid, components);
- }
- };
+ }
- @Override
- public void onServiceConnected(ComponentName component, IBinder binder) {
- synchronized (mLock) {
- if (component.equals(mBoundComponent)) {
- if (D) Log.d(mTag, component + " connected");
- mBoundService = binder;
- if (mHandler !=null && mNewServiceWork != null) {
- mHandler.post(mNewServiceWork);
+ /**
+ * Start this watcher, including binding to the current best match and
+ * re-binding to any better matches down the road.
+ * <p>
+ * Note that if there are no matching encryption-aware services, we may not
+ * bind to a real service until after the current user is unlocked.
+ *
+ * @return {@code true} if a potential service implementation was found.
+ */
+ public final boolean start() {
+ // if we have to return false, do it before registering anything
+ if (isServiceMissing()) return false;
+
+ // listen for relevant package changes if service overlay is enabled on handler
+ if (mServicePackageName == null) {
+ new PackageMonitor() {
+ @Override
+ public void onPackageUpdateFinished(String packageName, int uid) {
+ bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
}
- } else {
- Log.w(mTag, "unexpected onServiceConnected: " + component);
+
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
+ }
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
+ return super.onPackageChanged(packageName, uid, components);
+ }
+ }.register(mContext, UserHandle.ALL, true, mHandler);
+ }
+
+ // listen for user change on handler
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
+ mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL);
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ mCurrentUserId = userId;
+ bindBestPackage(false);
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ if (userId == mCurrentUserId) {
+ bindBestPackage(false);
+ }
+ }
+ }
+ }, UserHandle.ALL, intentFilter, null, mHandler);
+
+ mCurrentUserId = ActivityManager.getCurrentUser();
+
+ mHandler.post(() -> bindBestPackage(false));
+ return true;
+ }
+
+ /** Returns thje name of the currently connected package or null. */
+ @Nullable
+ public String getCurrentPackageName() {
+ ComponentName bestComponent = mBestComponent;
+ return bestComponent == null ? null : bestComponent.getPackageName();
+ }
+
+ public int getCurrentPackageVersion() {
+ return mBestVersion;
+ }
+
+ /**
+ * Runs the given BinderRunner if currently connected. Returns true if it was run, and false
+ * otherwise. All invocations to runOnBinder are run serially.
+ */
+ public final void runOnBinder(BinderRunner runner) {
+ synchronized (mBindLock) {
+ IBinder service = mBestService;
+ if (service != null) {
+ try {
+ runner.run(service);
+ } catch (Exception e) {
+ // remote exceptions cannot be allowed to crash system server
+ Log.e(TAG, "exception while while running " + runner + " on " + service
+ + " from " + mBestComponent.toShortString(), e);
+ }
}
}
}
+ private boolean isServiceMissing() {
+ return mContext.getPackageManager().queryIntentServicesAsUser(new Intent(mAction),
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ UserHandle.USER_SYSTEM).isEmpty();
+ }
+
+ /**
+ * Searches and binds to the best package, or do nothing if the best package
+ * is already bound, unless force rebinding is requested.
+ *
+ * @param forceRebind Force a rebinding to the best package if it's already
+ * bound.
+ */
+ @WorkerThread
+ private void bindBestPackage(boolean forceRebind) {
+ Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+ Intent intent = new Intent(mAction);
+ if (mServicePackageName != null) {
+ intent.setPackage(mServicePackageName);
+ }
+
+ List<ResolveInfo> rInfos = mContext.getPackageManager().queryIntentServicesAsUser(intent,
+ PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AUTO,
+ mCurrentUserId);
+ if (rInfos == null) {
+ rInfos = Collections.emptyList();
+ }
+
+ ComponentName bestComponent = null;
+ int bestVersion = Integer.MIN_VALUE;
+ boolean bestIsMultiuser = false;
+
+ for (ResolveInfo rInfo : rInfos) {
+ ComponentName component = rInfo.serviceInfo.getComponentName();
+ String packageName = component.getPackageName();
+
+ // check signature
+ try {
+ PackageInfo pInfo = mContext.getPackageManager().getPackageInfo(packageName,
+ PackageManager.GET_SIGNATURES
+ | PackageManager.MATCH_DIRECT_BOOT_AUTO);
+ if (!isSignatureMatch(pInfo.signatures, mSignatureSets)) {
+ Log.w(mTag, packageName + " resolves service " + mAction
+ + ", but has wrong signature, ignoring");
+ continue;
+ }
+ } catch (NameNotFoundException e) {
+ Log.wtf(mTag, e);
+ continue;
+ }
+
+ // check metadata
+ Bundle metadata = rInfo.serviceInfo.metaData;
+ int version = Integer.MIN_VALUE;
+ boolean isMultiuser = false;
+ if (metadata != null) {
+ version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
+ isMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
+ }
+
+ if (version > bestVersion) {
+ bestComponent = component;
+ bestVersion = version;
+ bestIsMultiuser = isMultiuser;
+ }
+ }
+
+ if (D) {
+ Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
+ (mServicePackageName == null ? ""
+ : "(" + mServicePackageName + ") "), rInfos.size(),
+ (bestComponent == null ? "no new best component"
+ : "new best component: " + bestComponent)));
+ }
+
+ if (bestComponent == null) {
+ Slog.w(mTag, "Odd, no component found for service " + mAction);
+ unbind();
+ return;
+ }
+
+ int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
+ boolean alreadyBound = Objects.equals(bestComponent, mBestComponent)
+ && bestVersion == mBestVersion && userId == mBestUserId;
+ if (forceRebind || !alreadyBound) {
+ unbind();
+ bind(bestComponent, bestVersion, userId);
+ }
+ }
+
+ @WorkerThread
+ private void bind(ComponentName component, int version, int userId) {
+ Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+ Intent intent = new Intent(mAction);
+ intent.setComponent(component);
+
+ mBestComponent = component;
+ mBestVersion = version;
+ mBestUserId = userId;
+
+ if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
+ mContext.bindServiceAsUser(intent, this,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
+ UserHandle.of(userId));
+ }
+
+ @WorkerThread
+ private void unbind() {
+ Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+ if (mBestComponent != null) {
+ if (D) Log.d(mTag, "unbinding " + mBestComponent);
+ mContext.unbindService(this);
+ }
+
+ mBestComponent = null;
+ mBestVersion = Integer.MIN_VALUE;
+ mBestUserId = UserHandle.USER_NULL;
+ }
+
+ @MainThread
@Override
- public void onServiceDisconnected(ComponentName component) {
- synchronized (mLock) {
+ public final void onServiceConnected(ComponentName component, IBinder binder) {
+ mHandler.post(() -> {
+ if (D) Log.d(mTag, component + " connected");
+
+ // hold the lock so that mBestService cannot be used by runOnBinder until complete
+ synchronized (mBindLock) {
+ mBestService = binder;
+ onBind();
+ }
+ });
+ }
+
+ @MainThread
+ @Override
+ public final void onServiceDisconnected(ComponentName component) {
+ mHandler.post(() -> {
if (D) Log.d(mTag, component + " disconnected");
- if (component.equals(mBoundComponent)) {
- mBoundService = null;
+ mBestService = null;
+ synchronized (mBindLock) {
+ onUnbind();
}
- }
+ });
}
- public @Nullable String getBestPackageName() {
- synchronized (mLock) {
- return mBoundPackageName;
- }
- }
-
- public int getBestVersion() {
- synchronized (mLock) {
- return mBoundVersion;
- }
- }
-
- /**
- * The runner that runs on the binder retrieved from {@link ServiceWatcher}.
- */
- public interface BinderRunner {
- /**
- * Runs on the retrieved binder.
- * @param binder the binder retrieved from the {@link ServiceWatcher}.
- */
- public void run(@NonNull IBinder binder);
- }
-
- /**
- * Retrieves the binder from {@link ServiceWatcher} and runs it.
- * @return whether a valid service exists.
- */
- public boolean runOnBinder(@NonNull BinderRunner runner) {
- synchronized (mLock) {
- if (mBoundService == null) {
- return false;
- } else {
- runner.run(mBoundService);
- return true;
- }
- }
- }
-
- public void switchUser(int userId) {
- synchronized (mLock) {
- mCurrentUserId = userId;
- bindBestPackageLocked(mServicePackageName, false);
- }
- }
-
- public void unlockUser(int userId) {
- synchronized (mLock) {
- if (userId == mCurrentUserId) {
- bindBestPackageLocked(mServicePackageName, false);
- }
- }
+ @Override
+ public String toString() {
+ ComponentName bestComponent = mBestComponent;
+ return bestComponent == null ? "null" : bestComponent.toShortString() + "@" + mBestVersion;
}
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 26e22bf..bbb1d13 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -1193,6 +1193,8 @@
if (i >= timings.length) {
if (repeatIndex >= 0) {
i = repeatIndex;
+ // prevent infinite loop
+ repeatIndex = -1;
} else {
break;
}
@@ -1268,8 +1270,13 @@
public int onCommand(String cmd) {
if ("vibrate".equals(cmd)) {
return runVibrate();
+ } else if ("waveform".equals(cmd)) {
+ return runWaveform();
} else if ("prebaked".equals(cmd)) {
return runPrebaked();
+ } else if ("cancel".equals(cmd)) {
+ cancelVibrate(mToken);
+ return 0;
}
return handleDefaultCommands(cmd);
}
@@ -1316,6 +1323,62 @@
}
}
+ private int runWaveform() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runWaveform");
+ try {
+ if (checkDoNotDisturb()) {
+ return 0;
+ }
+
+ String description = "Shell command";
+ int repeat = -1;
+ ArrayList<Integer> amplitudesList = null;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-d":
+ description = getNextArgRequired();
+ break;
+ case "-r":
+ repeat = Integer.parseInt(getNextArgRequired());
+ break;
+ case "-a":
+ if (amplitudesList == null) {
+ amplitudesList = new ArrayList<Integer>();
+ }
+ break;
+ }
+ }
+
+ ArrayList<Long> timingsList = new ArrayList<Long>();
+
+ String arg;
+ while ((arg = getNextArg()) != null) {
+ if (amplitudesList != null && amplitudesList.size() < timingsList.size()) {
+ amplitudesList.add(Integer.parseInt(arg));
+ } else {
+ timingsList.add(Long.parseLong(arg));
+ }
+ }
+
+ VibrationEffect effect;
+ long[] timings = timingsList.stream().mapToLong(Long::longValue).toArray();
+ if (amplitudesList == null) {
+ effect = VibrationEffect.createWaveform(timings, repeat);
+ } else {
+ int[] amplitudes =
+ amplitudesList.stream().mapToInt(Integer::intValue).toArray();
+ effect = VibrationEffect.createWaveform(timings, amplitudes, repeat);
+ }
+ vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
+ "Shell Command", mToken);
+ return 0;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
+
private int runPrebaked() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runPrebaked");
try {
@@ -1350,9 +1413,19 @@
pw.println(" vibrate duration [description]");
pw.println(" Vibrates for duration milliseconds; ignored when device is on DND ");
pw.println(" (Do Not Disturb) mode.");
+ pw.println(" waveform [-d description] [-r index] [-a] duration [amplitude] ...");
+ pw.println(" Vibrates for durations and amplitudes in list;");
+ pw.println(" ignored when device is on DND (Do Not Disturb) mode.");
+ pw.println(" If -r is provided, the waveform loops back to the specified");
+ pw.println(" index (e.g. 0 loops from the beginning)");
+ pw.println(" If -a is provided, the command accepts duration-amplitude pairs;");
+ pw.println(" otherwise, it accepts durations only and alternates off/on");
+ pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255.");
pw.println(" prebaked effect-id [description]");
pw.println(" Vibrates with prebaked effect; ignored when device is on DND ");
pw.println(" (Do Not Disturb) mode.");
+ pw.println(" cancel");
+ pw.println(" Cancels any active vibration");
pw.println("");
}
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 9cc550d..d1b56e9 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -43,6 +43,7 @@
import com.android.internal.os.ZygoteConnectionConstants;
import com.android.server.am.ActivityManagerService;
+import com.android.server.wm.SurfaceAnimationThread;
import java.io.File;
import java.io.FileWriter;
@@ -280,6 +281,12 @@
// And the display thread.
mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
"display thread", DEFAULT_TIMEOUT));
+ // And the animation thread.
+ mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(),
+ "animation thread", DEFAULT_TIMEOUT));
+ // And the surface animation thread.
+ mHandlerCheckers.add(new HandlerChecker(SurfaceAnimationThread.getHandler(),
+ "surface animation thread", DEFAULT_TIMEOUT));
// Initialize monitor for Binder threads.
addMonitor(new BinderThreadMonitor());
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 52b0275..c52df2d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -127,6 +127,11 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
+import static com.android.server.am.MemoryStatUtil.hasMemcg;
+import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -144,11 +149,6 @@
import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString;
-import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
-import static com.android.server.am.MemoryStatUtil.hasMemcg;
-import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
import android.Manifest;
import android.Manifest.permission;
@@ -1134,9 +1134,46 @@
boolean mOrigWaitForDebugger = false;
boolean mAlwaysFinishActivities = false;
- String mProfileApp = null;
- ProcessRecord mProfileProc = null;
- ProfilerInfo mProfilerInfo = null;
+ class ProfileData {
+ private String mProfileApp = null;
+ private ProcessRecord mProfileProc = null;
+ private ProfilerInfo mProfilerInfo = null;
+
+ void setProfileApp(String profileApp) {
+ mProfileApp = profileApp;
+ if (mAtmInternal != null) {
+ mAtmInternal.setProfileApp(profileApp);
+ }
+ }
+
+ String getProfileApp() {
+ return mProfileApp;
+ }
+
+ void setProfileProc(ProcessRecord profileProc) {
+ mProfileProc = profileProc;
+ if (mAtmInternal != null) {
+ mAtmInternal.setProfileProc(
+ profileProc.getWindowProcessController());
+ }
+ }
+
+ ProcessRecord getProfileProc() {
+ return mProfileProc;
+ }
+
+ void setProfilerInfo(ProfilerInfo profilerInfo) {
+ mProfilerInfo = profilerInfo;
+ if (mAtmInternal != null) {
+ mAtmInternal.setProfilerInfo(profilerInfo);
+ }
+ }
+
+ ProfilerInfo getProfilerInfo() {
+ return mProfilerInfo;
+ }
+ }
+ final ProfileData mProfileData = new ProfileData();
/**
* Stores a map of process name -> agent string. When a process is started and mAgentAppMap
@@ -2225,8 +2262,7 @@
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mActivityTaskManager = atm;
- mActivityTaskManager.setActivityManagerService(this, mHandlerThread.getLooper(),
- mIntentFirewall, mPendingIntentController);
+ mActivityTaskManager.setActivityManagerService(mIntentFirewall, mPendingIntentController);
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mProcessCpuThread = new Thread("CpuTracker") {
@@ -3129,7 +3165,7 @@
}
}
- if (mProfileProc == app) {
+ if (mProfileData.getProfileProc() == app) {
clearProfilerLocked();
}
@@ -3852,7 +3888,7 @@
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
- final int userId = UserHandle.getUserId(callingUid);
+ final int callingUserId = UserHandle.getUserId(callingUid);
final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
callingUid) == PackageManager.PERMISSION_GRANTED;
// Check REAL_GET_TASKS to see if they are allowed to access other uids
@@ -3870,11 +3906,17 @@
oomAdj = proc != null ? proc.setAdj : 0;
}
}
- if (!allUids || (!allUsers && (proc == null
- || UserHandle.getUserId(proc.uid) != userId))) {
- // The caller is not allow to get information about this other process...
- // just leave it empty.
- continue;
+ final int targetUid = (proc != null) ? proc.uid : -1;
+ final int targetUserId = (proc != null) ? UserHandle.getUserId(targetUid) : -1;
+
+ if (callingUid != targetUid) {
+ if (!allUids) {
+ continue; // Not allowed to see other UIDs.
+ }
+
+ if (!allUsers && (targetUserId != callingUserId)) {
+ continue; // Not allowed to see other users.
+ }
}
if (proc != null && proc.lastMemInfoTime >= lastNow && proc.lastMemInfo != null) {
// It hasn't been long enough that we want to take another sample; return
@@ -4410,16 +4452,18 @@
ProfilerInfo profilerInfo = null;
String preBindAgent = null;
- if (mProfileApp != null && mProfileApp.equals(processName)) {
- mProfileProc = app;
- if (mProfilerInfo != null) {
+ if (mProfileData.getProfileApp() != null
+ && mProfileData.getProfileApp().equals(processName)) {
+ mProfileData.setProfileProc(app);
+ if (mProfileData.getProfilerInfo() != null) {
// Send a profiler info object to the app if either a file is given, or
// an agent should be loaded at bind-time.
- boolean needsInfo = mProfilerInfo.profileFile != null
- || mProfilerInfo.attachAgentDuringBind;
- profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null;
- if (mProfilerInfo.agent != null) {
- preBindAgent = mProfilerInfo.agent;
+ boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null
+ || mProfileData.getProfilerInfo().attachAgentDuringBind;
+ profilerInfo = needsInfo
+ ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null;
+ if (mProfileData.getProfilerInfo().agent != null) {
+ preBindAgent = mProfileData.getProfilerInfo().agent;
}
}
} else if (instr != null && instr.mProfileFile != null) {
@@ -4443,7 +4487,8 @@
if (profilerInfo != null && profilerInfo.profileFd != null) {
profilerInfo.profileFd = profilerInfo.profileFd.dup();
- if (TextUtils.equals(mProfileApp, processName) && mProfilerInfo != null) {
+ if (TextUtils.equals(mProfileData.getProfileApp(), processName)
+ && mProfileData.getProfilerInfo() != null) {
clearProfilerLocked();
}
}
@@ -7320,13 +7365,6 @@
}
@Override
- public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
- int secondaryDisplayShowing) {
- mActivityTaskManager.setLockScreenShown(
- keyguardShowing, aodShowing, secondaryDisplayShowing);
- }
-
- @Override
public void notifyLockedProfile(@UserIdInt int userId) {
mAtmInternal.notifyLockedProfile(userId, mUserController.getCurrentUserId());
}
@@ -7451,17 +7489,17 @@
throw new SecurityException("Process not debuggable: " + app.packageName);
}
}
- mProfileApp = processName;
+ mProfileData.setProfileApp(processName);
- if (mProfilerInfo != null) {
- if (mProfilerInfo.profileFd != null) {
+ if (mProfileData.getProfilerInfo() != null) {
+ if (mProfileData.getProfilerInfo().profileFd != null) {
try {
- mProfilerInfo.profileFd.close();
+ mProfileData.getProfilerInfo().profileFd.close();
} catch (IOException e) {
}
}
}
- mProfilerInfo = new ProfilerInfo(profilerInfo);
+ mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
mProfileType = 0;
}
}
@@ -9978,20 +10016,25 @@
pw.println(" mTrackAllocationApp=" + mTrackAllocationApp);
}
}
- if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null &&
- (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) {
- if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
+ if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
+ || (mProfileData.getProfilerInfo() != null &&
+ (mProfileData.getProfilerInfo().profileFile != null
+ || mProfileData.getProfilerInfo().profileFd != null))) {
+ if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
if (needSep) {
pw.println();
needSep = false;
}
- pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
- if (mProfilerInfo != null) {
- pw.println(" mProfileFile=" + mProfilerInfo.profileFile + " mProfileFd=" +
- mProfilerInfo.profileFd);
- pw.println(" mSamplingInterval=" + mProfilerInfo.samplingInterval +
- " mAutoStopProfiler=" + mProfilerInfo.autoStopProfiler +
- " mStreamingOutput=" + mProfilerInfo.streamingOutput);
+ pw.println(" mProfileApp=" + mProfileData.getProfileApp()
+ + " mProfileProc=" + mProfileData.getProfileProc());
+ if (mProfileData.getProfilerInfo() != null) {
+ pw.println(" mProfileFile=" + mProfileData.getProfilerInfo().profileFile
+ + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
+ pw.println(" mSamplingInterval="
+ + mProfileData.getProfilerInfo().samplingInterval +
+ " mAutoStopProfiler="
+ + mProfileData.getProfilerInfo().autoStopProfiler +
+ " mStreamingOutput=" + mProfileData.getProfilerInfo().streamingOutput);
pw.println(" mProfileType=" + mProfileType);
}
}
@@ -10271,19 +10314,26 @@
if (mTrackAllocationApp != null) {
if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
- proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP, mTrackAllocationApp);
+ proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP,
+ mTrackAllocationApp);
}
}
- if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null &&
- (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) {
- if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
+ if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
+ || (mProfileData.getProfilerInfo() != null &&
+ (mProfileData.getProfilerInfo().profileFile != null
+ || mProfileData.getProfilerInfo().profileFd != null))) {
+ if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE);
- proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME, mProfileApp);
- mProfileProc.writeToProto(proto,ActivityManagerServiceDumpProcessesProto.Profile.PROC);
- if (mProfilerInfo != null) {
- mProfilerInfo.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.Profile.INFO);
- proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE, mProfileType);
+ proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME,
+ mProfileData.getProfileApp());
+ mProfileData.getProfileProc().writeToProto(proto,
+ ActivityManagerServiceDumpProcessesProto.Profile.PROC);
+ if (mProfileData.getProfilerInfo() != null) {
+ mProfileData.getProfilerInfo().writeToProto(proto,
+ ActivityManagerServiceDumpProcessesProto.Profile.INFO);
+ proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE,
+ mProfileType);
}
proto.end(token);
}
@@ -18040,8 +18090,8 @@
}
private void stopProfilerLocked(ProcessRecord proc, int profileType) {
- if (proc == null || proc == mProfileProc) {
- proc = mProfileProc;
+ if (proc == null || proc == mProfileData.getProfileProc()) {
+ proc = mProfileData.getProfileProc();
profileType = mProfileType;
clearProfilerLocked();
}
@@ -18056,15 +18106,16 @@
}
void clearProfilerLocked() {
- if (mProfilerInfo !=null && mProfilerInfo.profileFd != null) {
+ if (mProfileData.getProfilerInfo() != null
+ && mProfileData.getProfilerInfo().profileFd != null) {
try {
- mProfilerInfo.profileFd.close();
+ mProfileData.getProfilerInfo().profileFd.close();
} catch (IOException e) {
}
}
- mProfileApp = null;
- mProfileProc = null;
- mProfilerInfo = null;
+ mProfileData.setProfileApp(null);
+ mProfileData.setProfileProc(null);
+ mProfileData.setProfilerInfo(null);
}
public boolean profileControl(String process, int userId, boolean start,
@@ -18096,7 +18147,7 @@
if (start) {
stopProfilerLocked(null, 0);
setProfileApp(proc.info, proc.processName, profilerInfo);
- mProfileProc = proc;
+ mProfileData.setProfileProc(proc);
mProfileType = profileType;
ParcelFileDescriptor fd = profilerInfo.profileFd;
try {
@@ -18108,10 +18159,10 @@
proc.thread.profilerControl(start, profilerInfo, profileType);
fd = null;
try {
- mProfilerInfo.profileFd.close();
+ mProfileData.getProfilerInfo().profileFd.close();
} catch (IOException e) {
}
- mProfilerInfo.profileFd = null;
+ mProfileData.getProfilerInfo().profileFd = null;
if (proc.pid == MY_PID) {
// When profiling the system server itself, avoid closing the file
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index fe402ea..9018006 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2105,8 +2105,13 @@
}
FeatureInfo[] features = pm.getSystemAvailableFeatures();
- Arrays.sort(features, (o1, o2) ->
- (o1.name == o2.name ? 0 : (o1.name == null ? -1 : o1.name.compareTo(o2.name))));
+ Arrays.sort(features, (o1, o2) -> {
+ if (o1.name == o2.name) return 0;
+ if (o1.name == null) return -1;
+ if (o2.name == null) return 1;
+ return o1.name.compareTo(o2.name);
+ });
+
for (int i = 0; i < features.length; i++) {
if (features[i].name != null) {
if (protoOutputStream != null) {
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 968c17f..8ac19d5 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -61,6 +61,7 @@
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, int.class);
// add other global settings here...
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index bb87ad0..8a3f139 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1123,8 +1123,9 @@
@Override
public void clearProfilerIfNeeded() {
synchronized (mService) {
- if (mService.mProfileProc == null || mService.mProfilerInfo == null
- || mService.mProfileProc != this) {
+ if (mService.mProfileData.getProfileProc() == null
+ || mService.mProfileData.getProfilerInfo() == null
+ || mService.mProfileData.getProfileProc() != this) {
return;
}
mService.clearProfilerLocked();
@@ -1198,32 +1199,15 @@
}
@Override
- public ProfilerInfo onStartActivity(int topProcessState) {
+ public void onStartActivity(int topProcessState, boolean setProfileProc) {
synchronized (mService) {
- ProfilerInfo profilerInfo = null;
- if (mService.mProfileApp != null && mService.mProfileApp.equals(processName)) {
- if (mService.mProfileProc == null || mService.mProfileProc == this) {
- mService.mProfileProc = this;
- final ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
- if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
- if (profilerInfoSvc.profileFd != null) {
- try {
- profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
- } catch (IOException e) {
- profilerInfoSvc.closeFd();
- }
- }
-
- profilerInfo = new ProfilerInfo(profilerInfoSvc);
- }
- }
+ if (setProfileProc) {
+ mService.mProfileData.setProfileProc(this);
}
hasShownUi = true;
setPendingUiClean(true);
forceProcessStateUpTo(topProcessState);
-
- return profilerInfo;
}
}
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 0ee55ed..527539d 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -21,6 +21,7 @@
import android.content.IntentFilter;
import android.hardware.ICameraService;
import android.hardware.ICameraServiceProxy;
+import android.media.AudioManager;
import android.metrics.LogMaker;
import android.nfc.INfcAdapter;
import android.os.Binder;
@@ -393,6 +394,19 @@
boolean wasEmpty = mActiveCameraUsage.isEmpty();
switch (newCameraState) {
case ICameraServiceProxy.CAMERA_STATE_OPEN:
+ // Notify the audio subsystem about the facing of the most-recently opened
+ // camera This can be used to select the best audio tuning in case video
+ // recording with that camera will happen. Since only open events are used, if
+ // multiple cameras are opened at once, the one opened last will be used to
+ // select audio tuning.
+ AudioManager audioManager = getContext().getSystemService(AudioManager.class);
+ if (audioManager != null) {
+ // Map external to front for audio tuning purposes
+ String facingStr = (facing == ICameraServiceProxy.CAMERA_FACING_BACK) ?
+ "back" : "front";
+ String facingParameter = "cameraFacing=" + facingStr;
+ audioManager.setParameters(facingParameter);
+ }
break;
case ICameraServiceProxy.CAMERA_STATE_ACTIVE:
CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel);
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index f96f6e8..6596d27 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -94,7 +94,7 @@
final boolean hasIPv4Address =
(nai.linkProperties != null) && nai.linkProperties.hasIPv4Address();
final boolean skip464xlat =
- (nai.networkMisc != null) && nai.networkMisc.skip464xlat;
+ (nai.netMisc() != null) && nai.netMisc().skip464xlat;
return supported && connected && !hasIPv4Address && !skip464xlat;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 505480e..262184b 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -266,6 +266,10 @@
return mConnService;
}
+ public NetworkMisc netMisc() {
+ return networkMisc;
+ }
+
public Handler handler() {
return mHandler;
}
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index deaa334..94c94a5 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -165,7 +165,7 @@
}
@VisibleForTesting
- int getDeviceFirstSdkInt() {
+ protected int getDeviceFirstSdkInt() {
return Build.VERSION.FIRST_SDK_INT;
}
diff --git a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
index f82b976..22fabb2 100644
--- a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
@@ -16,59 +16,26 @@
package com.android.server.location;
-import com.android.server.ServiceWatcher;
-
import android.content.Context;
import android.hardware.location.ActivityRecognitionHardware;
import android.hardware.location.IActivityRecognitionHardwareClient;
import android.hardware.location.IActivityRecognitionHardwareWatcher;
-import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.ServiceWatcher;
+
/**
* Proxy class to bind GmsCore to the ActivityRecognitionHardware.
*
* @hide
*/
public class ActivityRecognitionProxy {
+
private static final String TAG = "ActivityRecognitionProxy";
- private final ServiceWatcher mServiceWatcher;
- private final boolean mIsSupported;
- private final ActivityRecognitionHardware mInstance;
-
- private ActivityRecognitionProxy(
- Context context,
- Handler handler,
- boolean activityRecognitionHardwareIsSupported,
- ActivityRecognitionHardware activityRecognitionHardware,
- int overlaySwitchResId,
- int defaultServicePackageNameResId,
- int initialPackageNameResId) {
- mIsSupported = activityRecognitionHardwareIsSupported;
- mInstance = activityRecognitionHardware;
-
- Runnable newServiceWork = new Runnable() {
- @Override
- public void run() {
- bindProvider();
- }
- };
-
- // prepare the connection to the provider
- mServiceWatcher = new ServiceWatcher(
- context,
- TAG,
- "com.android.location.service.ActivityRecognitionProvider",
- overlaySwitchResId,
- defaultServicePackageNameResId,
- initialPackageNameResId,
- newServiceWork,
- handler);
- }
-
/**
* Creates an instance of the proxy and binds it to the appropriate FusedProvider.
*
@@ -76,7 +43,6 @@
*/
public static ActivityRecognitionProxy createAndBind(
Context context,
- Handler handler,
boolean activityRecognitionHardwareIsSupported,
ActivityRecognitionHardware activityRecognitionHardware,
int overlaySwitchResId,
@@ -84,74 +50,69 @@
int initialPackageNameResId) {
ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy(
context,
- handler,
activityRecognitionHardwareIsSupported,
activityRecognitionHardware,
overlaySwitchResId,
defaultServicePackageNameResId,
initialPackageNameResId);
- // try to bind the provider
- if (!activityRecognitionProxy.mServiceWatcher.start()) {
- Log.e(TAG, "ServiceWatcher could not start.");
+ if (activityRecognitionProxy.mServiceWatcher.start()) {
+ return activityRecognitionProxy;
+ } else {
return null;
}
- return activityRecognitionProxy;
}
- /**
- * Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance.
- */
- private void bindProvider() {
- if (!mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- String descriptor;
- try {
- descriptor = binder.getInterfaceDescriptor();
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to get interface descriptor.", e);
- return;
- }
+ private final ServiceWatcher mServiceWatcher;
+ private final boolean mIsSupported;
+ private final ActivityRecognitionHardware mInstance;
- if (IActivityRecognitionHardwareWatcher.class.getCanonicalName()
- .equals(descriptor)) {
- IActivityRecognitionHardwareWatcher watcher =
- IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
- if (watcher == null) {
- Log.e(TAG, "No watcher found on connection.");
- return;
- }
- if (mInstance == null) {
- // to keep backwards compatibility do not update the watcher when there is
- // no instance available, or it will cause an NPE
- Log.d(TAG, "AR HW instance not available, binding will be a no-op.");
- return;
- }
- try {
- watcher.onInstanceChanged(mInstance);
- } catch (RemoteException e) {
- Log.e(TAG, "Error delivering hardware interface to watcher.", e);
- }
- } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
- .equals(descriptor)) {
- IActivityRecognitionHardwareClient client =
- IActivityRecognitionHardwareClient.Stub.asInterface(binder);
- if (client == null) {
- Log.e(TAG, "No client found on connection.");
- return;
- }
- try {
- client.onAvailabilityChanged(mIsSupported, mInstance);
- } catch (RemoteException e) {
- Log.e(TAG, "Error delivering hardware interface to client.", e);
- }
- } else {
- Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
- }
+ private ActivityRecognitionProxy(
+ Context context,
+ boolean activityRecognitionHardwareIsSupported,
+ ActivityRecognitionHardware activityRecognitionHardware,
+ int overlaySwitchResId,
+ int defaultServicePackageNameResId,
+ int initialPackageNameResId) {
+ mIsSupported = activityRecognitionHardwareIsSupported;
+ mInstance = activityRecognitionHardware;
+
+ mServiceWatcher = new ServiceWatcher(
+ context,
+ TAG,
+ "com.android.location.service.ActivityRecognitionProvider",
+ overlaySwitchResId,
+ defaultServicePackageNameResId,
+ initialPackageNameResId,
+ BackgroundThread.getHandler()) {
+ @Override
+ protected void onBind() {
+ runOnBinder(ActivityRecognitionProxy.this::initializeService);
}
- })) {
- Log.e(TAG, "Null binder found on connection.");
+ };
+ }
+
+ private void initializeService(IBinder binder) {
+ try {
+ String descriptor = binder.getInterfaceDescriptor();
+
+ if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(
+ descriptor)) {
+ IActivityRecognitionHardwareWatcher watcher =
+ IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
+ if (mInstance != null) {
+ watcher.onInstanceChanged(mInstance);
+ }
+ } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
+ .equals(descriptor)) {
+ IActivityRecognitionHardwareClient client =
+ IActivityRecognitionHardwareClient.Stub.asInterface(binder);
+ client.onAvailabilityChanged(mIsSupported, mInstance);
+ } else {
+ Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
}
}
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 6423470..002d4e1 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -211,6 +211,10 @@
@Override
public boolean registerIntent(PendingIntent pendingIntent, long nanoAppId) {
ContextHubServiceUtil.checkPermissions(mContext);
+ if (mClientManager.isPendingIntentRegistered(pendingIntent)) {
+ Log.e(TAG, "Failed to register PendingIntent: already registered");
+ return false;
+ }
boolean success = false;
synchronized (this) {
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 72879dd..fe93a1a 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -24,7 +24,6 @@
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.NanoAppMessage;
-import android.os.RemoteException;
import android.util.Log;
import java.util.concurrent.ConcurrentHashMap;
@@ -204,6 +203,20 @@
}
/**
+ * @param pendingIntent the PendingIntent to check
+ * @return true if the given PendingIntent is registered by a client, false otherwise
+ */
+ /* package */ boolean isPendingIntentRegistered(PendingIntent pendingIntent) {
+ for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
+ if (broker.hasPendingIntent(pendingIntent)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Creates a new ContextHubClientBroker object for a client and registers it with the client
* manager.
*
diff --git a/services/core/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
index 9ad4aa1..f1de371 100644
--- a/services/core/java/com/android/server/location/GeocoderProxy.java
+++ b/services/core/java/com/android/server/location/GeocoderProxy.java
@@ -20,12 +20,12 @@
import android.location.Address;
import android.location.GeocoderParams;
import android.location.IGeocodeProvider;
-import android.os.Handler;
-import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.os.BackgroundThread;
import com.android.server.ServiceWatcher;
+
import java.util.List;
/**
@@ -36,14 +36,13 @@
private static final String SERVICE_ACTION = "com.android.location.service.GeocodeProvider";
- private final Context mContext;
private final ServiceWatcher mServiceWatcher;
public static GeocoderProxy createAndBind(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler) {
+ int initialPackageNamesResId) {
GeocoderProxy proxy = new GeocoderProxy(context, overlaySwitchResId,
- defaultServicePackageNameResId, initialPackageNamesResId, handler);
+ defaultServicePackageNameResId, initialPackageNamesResId);
if (proxy.bind()) {
return proxy;
} else {
@@ -53,34 +52,30 @@
private GeocoderProxy(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler) {
- mContext = context;
-
- mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, overlaySwitchResId,
- defaultServicePackageNameResId, initialPackageNamesResId, null, handler);
+ int initialPackageNamesResId) {
+ mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
+ defaultServicePackageNameResId, initialPackageNamesResId,
+ BackgroundThread.getHandler());
}
- private boolean bind () {
+ private boolean bind() {
return mServiceWatcher.start();
}
public String getConnectedPackageName() {
- return mServiceWatcher.getBestPackageName();
+ return mServiceWatcher.getCurrentPackageName();
}
public String getFromLocation(double latitude, double longitude, int maxResults,
GeocoderParams params, List<Address> addrs) {
- final String[] result = new String[] {"Service not Available"};
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
- try {
- result[0] = provider.getFromLocation(
- latitude, longitude, maxResults, params, addrs);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ final String[] result = new String[]{"Service not Available"};
+ mServiceWatcher.runOnBinder(binder -> {
+ IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
+ try {
+ result[0] = provider.getFromLocation(
+ latitude, longitude, maxResults, params, addrs);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
return result[0];
@@ -90,18 +85,15 @@
double lowerLeftLatitude, double lowerLeftLongitude,
double upperRightLatitude, double upperRightLongitude, int maxResults,
GeocoderParams params, List<Address> addrs) {
- final String[] result = new String[] {"Service not Available"};
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
- try {
- result[0] = provider.getFromLocationName(locationName, lowerLeftLatitude,
- lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
- maxResults, params, addrs);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
+ final String[] result = new String[]{"Service not Available"};
+ mServiceWatcher.runOnBinder(binder -> {
+ IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
+ try {
+ result[0] = provider.getFromLocationName(locationName, lowerLeftLatitude,
+ lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
+ maxResults, params, addrs);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
return result[0];
diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
index eb47b2f..ca4f7fe 100644
--- a/services/core/java/com/android/server/location/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/GeofenceProxy.java
@@ -15,61 +15,60 @@
*/
package com.android.server.location;
+import android.annotation.Nullable;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.hardware.location.GeofenceHardwareService;
import android.hardware.location.IGeofenceHardware;
+import android.location.IFusedGeofenceHardware;
import android.location.IGeofenceProvider;
import android.location.IGpsGeofenceHardware;
-import android.location.IFusedGeofenceHardware;
-import android.content.Context;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
+
+import com.android.internal.os.BackgroundThread;
import com.android.server.ServiceWatcher;
/**
* @hide
*/
public final class GeofenceProxy {
+
private static final String TAG = "GeofenceProxy";
- private static final String SERVICE_ACTION =
- "com.android.location.service.GeofenceProvider";
- private final ServiceWatcher mServiceWatcher;
+ private static final String SERVICE_ACTION = "com.android.location.service.GeofenceProvider";
+
private final Context mContext;
+ private final ServiceWatcher mServiceWatcher;
+
+ @Nullable
private final IGpsGeofenceHardware mGpsGeofenceHardware;
+ @Nullable
private final IFusedGeofenceHardware mFusedGeofenceHardware;
- private final Object mLock = new Object();
+ private volatile IGeofenceHardware mGeofenceHardware;
- // Access to mGeofenceHardware needs to be synchronized by mLock.
- private IGeofenceHardware mGeofenceHardware;
-
- private static final int GEOFENCE_PROVIDER_CONNECTED = 1;
- private static final int GEOFENCE_HARDWARE_CONNECTED = 2;
- private static final int GEOFENCE_HARDWARE_DISCONNECTED = 3;
- private static final int GEOFENCE_GPS_HARDWARE_CONNECTED = 4;
- private static final int GEOFENCE_GPS_HARDWARE_DISCONNECTED = 5;
-
- private Runnable mRunnable = new Runnable() {
- @Override
- public void run() {
- mHandler.sendEmptyMessage(GEOFENCE_PROVIDER_CONNECTED);
+ private final ServiceWatcher.BinderRunner mUpdateGeofenceHardware = (binder) -> {
+ IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface(binder);
+ try {
+ provider.setGeofenceHardware(mGeofenceHardware);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
};
public static GeofenceProxy createAndBind(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence,
- IFusedGeofenceHardware fusedGeofenceHardware) {
+ int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence,
+ @Nullable IFusedGeofenceHardware fusedGeofenceHardware) {
GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId,
- defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence,
- fusedGeofenceHardware);
- if (proxy.bindGeofenceProvider()) {
+ defaultServicePackageNameResId, initialPackageNamesResId, gpsGeofence,
+ fusedGeofenceHardware);
+
+ if (proxy.bind()) {
return proxy;
} else {
return null;
@@ -78,111 +77,56 @@
private GeofenceProxy(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence,
- IFusedGeofenceHardware fusedGeofenceHardware) {
+ int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence,
+ @Nullable IFusedGeofenceHardware fusedGeofenceHardware) {
mContext = context;
mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
- defaultServicePackageNameResId, initialPackageNamesResId, mRunnable, handler);
+ defaultServicePackageNameResId, initialPackageNamesResId,
+ BackgroundThread.getHandler()) {
+ @Override
+ protected void onBind() {
+ runOnBinder(mUpdateGeofenceHardware);
+ }
+ };
+
mGpsGeofenceHardware = gpsGeofence;
mFusedGeofenceHardware = fusedGeofenceHardware;
- bindHardwareGeofence();
+
+ mGeofenceHardware = null;
}
- private boolean bindGeofenceProvider() {
- return mServiceWatcher.start();
+ private boolean bind() {
+ if (mServiceWatcher.start()) {
+ mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
+ new GeofenceProxyServiceConnection(), Context.BIND_AUTO_CREATE,
+ UserHandle.SYSTEM);
+ return true;
+ }
+
+ return false;
}
- private void bindHardwareGeofence() {
- mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
- mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
- }
+ private class GeofenceProxyServiceConnection implements ServiceConnection {
- private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- synchronized (mLock) {
- mGeofenceHardware = IGeofenceHardware.Stub.asInterface(service);
- mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_CONNECTED);
+ IGeofenceHardware geofenceHardware = IGeofenceHardware.Stub.asInterface(service);
+
+ try {
+ geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
+ geofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware);
+
+ mGeofenceHardware = geofenceHardware;
+ mServiceWatcher.runOnBinder(mUpdateGeofenceHardware);
+ } catch (Exception e) {
+ Log.w(TAG, e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
- synchronized (mLock) {
- mGeofenceHardware = null;
- mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_DISCONNECTED);
- }
- }
- };
-
- private void setGeofenceHardwareInProviderLocked() {
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- final IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface(binder);
- try {
- provider.setGeofenceHardware(mGeofenceHardware);
- } catch (RemoteException e) {
- Log.e(TAG, "Remote Exception: setGeofenceHardwareInProviderLocked: " + e);
- }
- }
- });
- }
-
- private void setGpsGeofenceLocked() {
- try {
- if (mGpsGeofenceHardware != null) {
- mGeofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error while connecting to GeofenceHardwareService");
+ mGeofenceHardware = null;
+ mServiceWatcher.runOnBinder(mUpdateGeofenceHardware);
}
}
-
- private void setFusedGeofenceLocked() {
- try {
- mGeofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware);
- } catch(RemoteException e) {
- Log.e(TAG, "Error while connecting to GeofenceHardwareService");
- }
- }
-
- // This needs to be reworked, when more services get added,
- // Might need a state machine or add a framework utility class,
- private Handler mHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case GEOFENCE_PROVIDER_CONNECTED:
- synchronized (mLock) {
- if (mGeofenceHardware != null) {
- setGeofenceHardwareInProviderLocked();
- }
- // else: the geofence provider will be notified when the connection to
- // GeofenceHardwareService is established.
- }
- break;
- case GEOFENCE_HARDWARE_CONNECTED:
- synchronized (mLock) {
- // Theoretically this won't happen because once the GeofenceHardwareService
- // is connected to, we won't lose connection to it because it's a system
- // service. But this check does make the code more robust.
- if (mGeofenceHardware != null) {
- setGpsGeofenceLocked();
- setFusedGeofenceLocked();
- setGeofenceHardwareInProviderLocked();
- }
- }
- break;
- case GEOFENCE_HARDWARE_DISCONNECTED:
- synchronized (mLock) {
- if (mGeofenceHardware == null) {
- setGeofenceHardwareInProviderLocked();
- }
- }
- break;
- }
- }
- };
}
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 16eae62..bb86b48 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -16,26 +16,28 @@
package com.android.server.location;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-
+import android.annotation.Nullable;
import android.content.Context;
import android.location.LocationProvider;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.WorkSource;
import android.util.Log;
-import com.android.internal.location.ProviderProperties;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.location.ILocationProvider;
+import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.os.TransferPipe;
import com.android.server.LocationManagerService;
import com.android.server.ServiceWatcher;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+
/**
* Proxy for ILocationProvider implementations.
*/
@@ -43,25 +45,36 @@
private static final String TAG = "LocationProviderProxy";
private static final boolean D = LocationManagerService.D;
- private final Context mContext;
- private final String mName;
private final ServiceWatcher mServiceWatcher;
- private Object mLock = new Object();
+ private final String mName;
- // cached values set by the location manager, synchronized on mLock
- private ProviderProperties mProperties;
- private boolean mEnabled = false;
- private ProviderRequest mRequest = null;
- private WorkSource mWorksource = new WorkSource();
+ // used to ensure that updates to mRequest and mWorkSource are atomic
+ private final Object mRequestLock = new Object();
+
+ private volatile boolean mEnabled = false;
+ @Nullable
+ private volatile ProviderProperties mProperties;
+
+ @GuardedBy("mRequestLock")
+ @Nullable
+ private ProviderRequest mRequest;
+ @GuardedBy("mRequestLock")
+ private WorkSource mWorkSource;
+
+ /**
+ * Creates a new LocationProviderProxy and immediately begins binding to the best applicable
+ * service.
+ */
+ @Nullable
public static LocationProviderProxy createAndBind(
Context context, String name, String action,
int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler) {
- LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
- overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId,
- handler);
+ int initialPackageNamesResId) {
+ LocationProviderProxy proxy = new LocationProviderProxy(context, name,
+ action, overlaySwitchResId, defaultServicePackageNameResId,
+ initialPackageNamesResId);
if (proxy.bind()) {
return proxy;
} else {
@@ -69,78 +82,66 @@
}
}
- private LocationProviderProxy(Context context, String name, String action,
- int overlaySwitchResId, int defaultServicePackageNameResId,
- int initialPackageNamesResId, Handler handler) {
- mContext = context;
- mName = name;
- mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
+ private LocationProviderProxy(Context context, String name,
+ String action, int overlaySwitchResId, int defaultServicePackageNameResId,
+ int initialPackageNamesResId) {
+
+ mServiceWatcher = new ServiceWatcher(context, TAG, action, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId,
- mNewServiceWork, handler);
+ BackgroundThread.getHandler()) {
+ @Override
+ protected void onBind() {
+ runOnBinder(LocationProviderProxy.this::initializeService);
+ }
+ };
+ mName = name;
+
+ mProperties = null;
+ mRequest = null;
+ mWorkSource = new WorkSource();
}
- private boolean bind () {
+ private boolean bind() {
return mServiceWatcher.start();
}
- public String getConnectedPackageName() {
- return mServiceWatcher.getBestPackageName();
+ private void initializeService(IBinder binder) {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ if (D) Log.d(TAG, "applying state to connected service");
+
+ ProviderProperties[] properties = new ProviderProperties[1];
+ ProviderRequest request;
+ WorkSource source;
+ synchronized (mRequestLock) {
+ request = mRequest;
+ source = mWorkSource;
+ }
+
+ try {
+ // load properties from provider
+ properties[0] = service.getProperties();
+ if (properties[0] == null) {
+ Log.e(TAG, mServiceWatcher.getCurrentPackageName()
+ + " has invalid location provider properties");
+ }
+
+ // apply current state to new service
+ if (mEnabled) {
+ service.enable();
+ if (request != null) {
+ service.setRequest(request, source);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
+ }
+
+ mProperties = properties[0];
}
- /**
- * Work to apply current state to a newly connected provider.
- * Remember we can switch the service that implements a providers
- * at run-time, so need to apply current state.
- */
- private Runnable mNewServiceWork = new Runnable() {
- @Override
- public void run() {
- if (D) Log.d(TAG, "applying state to connected service");
-
- boolean enabled;
- final ProviderProperties[] properties = new ProviderProperties[1];
- ProviderRequest request;
- WorkSource source;
- synchronized (mLock) {
- enabled = mEnabled;
- request = mRequest;
- source = mWorksource;
- }
-
-
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- // load properties from provider
- properties[0] = service.getProperties();
- if (properties[0] == null) {
- Log.e(TAG, mServiceWatcher.getBestPackageName() +
- " has invalid location provider properties");
- }
-
- // apply current state to new service
- if (enabled) {
- service.enable();
- if (request != null) {
- service.setRequest(request, source);
- }
- }
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
- }
- });
-
- synchronized (mLock) {
- mProperties = properties[0];
- }
- }
- };
+ public String getConnectedPackageName() {
+ return mServiceWatcher.getCurrentPackageName();
+ }
@Override
public String getName() {
@@ -149,78 +150,52 @@
@Override
public ProviderProperties getProperties() {
- synchronized (mLock) {
- return mProperties;
- }
+ return mProperties;
}
@Override
public void enable() {
- synchronized (mLock) {
- mEnabled = true;
- }
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- service.enable();
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
+ mEnabled = true;
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ service.enable();
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
}
@Override
public void disable() {
- synchronized (mLock) {
- mEnabled = false;
- }
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- service.disable();
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
+ mEnabled = false;
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ service.disable();
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
}
@Override
public boolean isEnabled() {
- synchronized (mLock) {
- return mEnabled;
- }
+ return mEnabled;
}
@Override
public void setRequest(ProviderRequest request, WorkSource source) {
- synchronized (mLock) {
+ synchronized (mRequestLock) {
mRequest = request;
- mWorksource = source;
+ mWorkSource = source;
}
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- service.setRequest(request, source);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ service.setRequest(request, source);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
}
@@ -229,39 +204,28 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.append("REMOTE SERVICE");
pw.append(" name=").append(mName);
- pw.append(" pkg=").append(mServiceWatcher.getBestPackageName());
- pw.append(" version=").append("" + mServiceWatcher.getBestVersion());
+ pw.append(" pkg=").append(mServiceWatcher.getCurrentPackageName());
+ pw.append(" version=").append(Integer.toString(mServiceWatcher.getCurrentPackageVersion()));
pw.append('\n');
- if (!mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- TransferPipe.dumpAsync(service.asBinder(), fd, args);
- } catch (IOException | RemoteException e) {
- pw.println("Failed to dump location provider: " + e);
- }
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ TransferPipe.dumpAsync(service.asBinder(), fd, args);
+ } catch (IOException | RemoteException e) {
+ pw.println("Failed to dump location provider: " + e);
}
- })) {
- pw.println("service down (null)");
- }
+ });
}
@Override
public int getStatus(Bundle extras) {
- final int[] result = new int[] {LocationProvider.TEMPORARILY_UNAVAILABLE};
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- result[0] = service.getStatus(extras);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
+ int[] result = new int[]{LocationProvider.TEMPORARILY_UNAVAILABLE};
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ result[0] = service.getStatus(extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
return result[0];
@@ -269,19 +233,13 @@
@Override
public long getStatusUpdateTime() {
- final long[] result = new long[] {0L};
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- result[0] = service.getStatusUpdateTime();
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
+ long[] result = new long[]{0L};
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ result[0] = service.getStatusUpdateTime();
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
return result[0];
@@ -289,21 +247,15 @@
@Override
public boolean sendExtraCommand(String command, Bundle extras) {
- final boolean[] result = new boolean[] {false};
- mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
- @Override
- public void run(IBinder binder) {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- try {
- result[0] = service.sendExtraCommand(command, extras);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } catch (Exception e) {
- // never let remote service crash system server
- Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
- }
+ boolean[] result = new boolean[]{false};
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ try {
+ result[0] = service.sendExtraCommand(command, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
}
});
return result[0];
}
- }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 924b075..b404c41 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4756,6 +4756,10 @@
applyZenModeLocked(r);
mRankingHelper.sort(mNotificationList);
+ if (!r.isHidden()) {
+ buzzBeepBlinkLocked(r);
+ }
+
if (notification.getSmallIcon() != null) {
StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
mListeners.notifyPostedLocked(r, old);
@@ -4788,9 +4792,6 @@
+ n.getPackageName());
}
- if (!r.isHidden()) {
- buzzBeepBlinkLocked(r);
- }
maybeRecordInterruptionLocked(r);
} finally {
int N = mEnqueuedNotifications.size();
@@ -5157,6 +5158,7 @@
.setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
}
+ record.setAudiblyAlerted(buzz || beep);
}
@GuardedBy("mNotificationLock")
@@ -6561,6 +6563,8 @@
Bundle hidden = new Bundle();
Bundle smartActions = new Bundle();
Bundle smartReplies = new Bundle();
+ Bundle audiblyAlerted = new Bundle();
+ Bundle noisy = new Bundle();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
if (!isVisibleToListener(record.sbn, info)) {
@@ -6590,6 +6594,8 @@
hidden.putBoolean(key, record.isHidden());
smartActions.putParcelableArrayList(key, record.getSmartActions());
smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
+ audiblyAlerted.putBoolean(key, record.getAudiblyAlerted());
+ noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
}
final int M = keys.size();
String[] keysAr = keys.toArray(new String[M]);
@@ -6601,7 +6607,7 @@
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
- smartActions, smartReplies);
+ smartActions, smartReplies, audiblyAlerted, noisy);
}
boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index e9f2718..84d0c01 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -170,6 +170,7 @@
private final NotificationStats mStats;
private int mUserSentiment;
private boolean mIsInterruptive;
+ private boolean mAudiblyAlerted;
private boolean mTextChanged;
private boolean mRecordedInterruption;
private int mNumberOfSmartRepliesAdded;
@@ -1023,6 +1024,10 @@
}
}
+ public void setAudiblyAlerted(boolean audiblyAlerted) {
+ mAudiblyAlerted = audiblyAlerted;
+ }
+
public void setTextChanged(boolean textChanged) {
mTextChanged = textChanged;
}
@@ -1039,6 +1044,11 @@
return mIsInterruptive;
}
+ /** Returns true if the notification audibly alerted the user. */
+ public boolean getAudiblyAlerted() {
+ return mAudiblyAlerted;
+ }
+
protected void setPeopleOverride(ArrayList<String> people) {
mPeopleOverride = people;
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 404f152..275f3dc 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -77,7 +77,6 @@
*/
public class LauncherAppsService extends SystemService {
- private static final boolean SHOW_HIDDEN_APP_ENABLED = false;
private final LauncherAppsImpl mLauncherAppsImpl;
public LauncherAppsService(Context context) {
@@ -310,22 +309,28 @@
.addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(packageName),
user);
- if (!SHOW_HIDDEN_APP_ENABLED) {
+ if (Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 0) == 0) {
return launcherActivities;
}
final int callingUid = injectBinderCallingUid();
final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList());
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
if (packageName != null) {
- // If target package has launcher activities, then return those launcher
- // activities. Otherwise, return hidden activity that forwards user to app
- // details page.
+ // If this hidden app should not be shown, return the original list.
+ // Otherwise, inject hidden activity that forwards user to app details page.
if (result.size() > 0) {
return launcherActivities;
}
- ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
- if (info != null) {
- result.add(info);
+ ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName, /*flags*/ 0,
+ callingUid, user.getIdentifier());
+ if (shouldShowHiddenApp(appInfo)) {
+ ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
+ if (info != null) {
+ result.add(info);
+ }
}
return new ParceledListSlice<>(result);
}
@@ -336,8 +341,6 @@
for (ResolveInfo info : result) {
visiblePackages.add(info.activityInfo.packageName);
}
- final PackageManagerInternal pmInt =
- LocalServices.getService(PackageManagerInternal.class);
List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0,
user.getIdentifier(), callingUid);
for (ApplicationInfo applicationInfo : installedPackages) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 6ccd040..1a5b86c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -107,7 +107,9 @@
import java.util.Objects;
import java.util.Random;
-public class PackageInstallerService extends IPackageInstaller.Stub {
+/** The service responsible for installing packages. */
+public class PackageInstallerService extends IPackageInstaller.Stub implements
+ PackageSessionProvider {
private static final String TAG = "PackageInstaller";
private static final boolean LOGD = false;
@@ -296,6 +298,7 @@
in.setInput(fis, StandardCharsets.UTF_8.name());
int type;
+ PackageInstallerSession currentSession = null;
while ((type = in.next()) != END_DOCUMENT) {
if (type == START_TAG) {
final String tag = in.getName();
@@ -303,8 +306,10 @@
final PackageInstallerSession session;
try {
session = PackageInstallerSession.readFromXml(in, mInternalCallback,
- mContext, mPm, mInstallThread.getLooper(), mSessionsDir);
+ mContext, mPm, mInstallThread.getLooper(), mSessionsDir, this);
+ currentSession = session;
} catch (Exception e) {
+ currentSession = null;
Slog.e(TAG, "Could not read session", e);
continue;
}
@@ -329,6 +334,10 @@
addHistoricalSessionLocked(session);
}
mAllocatedSessions.put(session.sessionId, true);
+ } else if (currentSession != null
+ && PackageInstallerSession.TAG_CHILD_SESSION.equals(tag)) {
+ currentSession.addChildSessionIdInternal(
+ PackageInstallerSession.readChildSessionIdFromXml(in));
}
}
}
@@ -436,70 +445,72 @@
}
}
- // Only system components can circumvent runtime permissions when installing.
- if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
- && mContext.checkCallingOrSelfPermission(Manifest.permission
- .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
- throw new SecurityException("You need the "
- + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
- + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
- }
-
- if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
- || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
- throw new IllegalArgumentException(
- "New installs into ASEC containers no longer supported");
- }
-
- // Defensively resize giant app icons
- if (params.appIcon != null) {
- final ActivityManager am = (ActivityManager) mContext.getSystemService(
- Context.ACTIVITY_SERVICE);
- final int iconSize = am.getLauncherLargeIconSize();
- if ((params.appIcon.getWidth() > iconSize * 2)
- || (params.appIcon.getHeight() > iconSize * 2)) {
- params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
- true);
- }
- }
-
- switch (params.mode) {
- case SessionParams.MODE_FULL_INSTALL:
- case SessionParams.MODE_INHERIT_EXISTING:
- break;
- default:
- throw new IllegalArgumentException("Invalid install mode: " + params.mode);
- }
-
- // If caller requested explicit location, sanity check it, otherwise
- // resolve the best internal or adopted location.
- if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- if (!PackageHelper.fitsOnInternal(mContext, params)) {
- throw new IOException("No suitable internal storage available");
+ if (!params.isMultiPackage) {
+ // Only system components can circumvent runtime permissions when installing.
+ if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
+ && mContext.checkCallingOrSelfPermission(Manifest.permission
+ .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
+ throw new SecurityException("You need the "
+ + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
+ + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
- } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
- if (!PackageHelper.fitsOnExternal(mContext, params)) {
- throw new IOException("No suitable external storage available");
+ if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+ || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ throw new IllegalArgumentException(
+ "New installs into ASEC containers no longer supported");
}
- } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) {
- // For now, installs to adopted media are treated as internal from
- // an install flag point-of-view.
- params.setInstallFlagsInternal();
+ // Defensively resize giant app icons
+ if (params.appIcon != null) {
+ final ActivityManager am = (ActivityManager) mContext.getSystemService(
+ Context.ACTIVITY_SERVICE);
+ final int iconSize = am.getLauncherLargeIconSize();
+ if ((params.appIcon.getWidth() > iconSize * 2)
+ || (params.appIcon.getHeight() > iconSize * 2)) {
+ params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
+ true);
+ }
+ }
- } else {
- // For now, installs to adopted media are treated as internal from
- // an install flag point-of-view.
- params.setInstallFlagsInternal();
+ switch (params.mode) {
+ case SessionParams.MODE_FULL_INSTALL:
+ case SessionParams.MODE_INHERIT_EXISTING:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid install mode: " + params.mode);
+ }
- // Resolve best location for install, based on combination of
- // requested install flags, delta size, and manifest settings.
- final long ident = Binder.clearCallingIdentity();
- try {
- params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ // If caller requested explicit location, sanity check it, otherwise
+ // resolve the best internal or adopted location.
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ if (!PackageHelper.fitsOnInternal(mContext, params)) {
+ throw new IOException("No suitable internal storage available");
+ }
+
+ } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ if (!PackageHelper.fitsOnExternal(mContext, params)) {
+ throw new IOException("No suitable external storage available");
+ }
+
+ } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) {
+ // For now, installs to adopted media are treated as internal from
+ // an install flag point-of-view.
+ params.setInstallFlagsInternal();
+
+ } else {
+ // For now, installs to adopted media are treated as internal from
+ // an install flag point-of-view.
+ params.setInstallFlagsInternal();
+
+ // Resolve best location for install, based on combination of
+ // requested install flags, delta size, and manifest settings.
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
@@ -525,17 +536,19 @@
// We're staging to exactly one location
File stageDir = null;
String stageCid = null;
- if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- final boolean isInstant =
- (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
- stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
- } else {
- stageCid = buildExternalStageCid(sessionId);
+ if (!params.isMultiPackage) {
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ final boolean isInstant =
+ (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+ stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
+ } else {
+ stageCid = buildExternalStageCid(sessionId);
+ }
}
-
- session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
- mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
- params, createdMillis, stageDir, stageCid, false, false);
+ session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
+ mInstallThread.getLooper(), sessionId, userId, installerPackageName,
+ callingUid, params, createdMillis, stageDir, stageCid, false, false, null,
+ SessionInfo.INVALID_ID);
synchronized (mSessions) {
mSessions.put(sessionId, session);
@@ -678,7 +691,7 @@
synchronized (mSessions) {
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- if (session.userId == userId) {
+ if (session.userId == userId && !session.hasParentSessionId()) {
result.add(session.generateInfo(false));
}
}
@@ -699,7 +712,7 @@
SessionInfo info = session.generateInfo(false);
if (Objects.equals(info.getInstallerPackageName(), installerPackageName)
- && session.userId == userId) {
+ && session.userId == userId && !session.hasParentSessionId()) {
result.add(info);
}
}
@@ -781,6 +794,13 @@
mCallbacks.unregister(callback);
}
+ @Override
+ public PackageInstallerSession getSession(int sessionId) {
+ synchronized (mSessions) {
+ return mSessions.get(sessionId);
+ }
+ }
+
private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
int installerUid) {
int count = 0;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 6e45013..26f6e96 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -47,6 +47,8 @@
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
@@ -69,6 +71,7 @@
import android.os.FileBridge;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -90,6 +93,7 @@
import android.util.ExceptionUtils;
import android.util.MathUtils;
import android.util.Slog;
+import android.util.SparseIntArray;
import android.util.apk.ApkSignatureVerifier;
import com.android.internal.annotations.GuardedBy;
@@ -130,6 +134,7 @@
/** XML constants used for persisting a session */
static final String TAG_SESSION = "session";
+ static final String TAG_CHILD_SESSION = "childSession";
private static final String TAG_GRANTED_RUNTIME_PERMISSION = "granted-runtime-permission";
private static final String ATTR_SESSION_ID = "sessionId";
private static final String ATTR_USER_ID = "userId";
@@ -140,6 +145,8 @@
private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
private static final String ATTR_PREPARED = "prepared";
private static final String ATTR_SEALED = "sealed";
+ private static final String ATTR_MULTI_PACKAGE = "multiPackage";
+ private static final String ATTR_PARENT_SESSION_ID = "parentSessionId";
private static final String ATTR_MODE = "mode";
private static final String ATTR_INSTALL_FLAGS = "installFlags";
private static final String ATTR_INSTALL_LOCATION = "installLocation";
@@ -157,6 +164,7 @@
private static final String ATTR_INSTALL_REASON = "installRason";
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
+ private static final int[] EMPTY_CHILD_SESSION_ARRAY = {};
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -165,6 +173,7 @@
private final Context mContext;
private final PackageManagerService mPm;
private final Handler mHandler;
+ private final PackageSessionProvider mSessionProvider;
final int sessionId;
final int userId;
@@ -236,6 +245,10 @@
private long mVersionCode;
@GuardedBy("mLock")
private PackageParser.SigningDetails mSigningDetails;
+ @GuardedBy("mLock")
+ private SparseIntArray mChildSessionIds = new SparseIntArray();
+ @GuardedBy("mLock")
+ private int mParentSessionId;
/**
* Path to the validated base APK for this session, which may point at an
@@ -372,12 +385,16 @@
}
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
- Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
+ Context context, PackageManagerService pm,
+ PackageSessionProvider sessionProvider, Looper looper,
+ int sessionId, int userId,
String installerPackageName, int installerUid, SessionParams params, long createdMillis,
- File stageDir, String stageCid, boolean prepared, boolean sealed) {
+ File stageDir, String stageCid, boolean prepared, boolean sealed,
+ @Nullable int[] childSessionIds, int parentSessionId) {
mCallback = callback;
mContext = context;
mPm = pm;
+ mSessionProvider = sessionProvider;
mHandler = new Handler(looper, mHandlerCallback);
this.sessionId = sessionId;
@@ -389,8 +406,14 @@
this.createdMillis = createdMillis;
this.stageDir = stageDir;
this.stageCid = stageCid;
+ if (childSessionIds != null) {
+ for (int childSessionId : childSessionIds) {
+ mChildSessionIds.put(childSessionId, 0);
+ }
+ }
+ this.mParentSessionId = parentSessionId;
- if ((stageDir == null) == (stageCid == null)) {
+ if (!params.isMultiPackage && (stageDir == null) == (stageCid == null)) {
throw new IllegalArgumentException(
"Exactly one of stageDir or stageCid stage must be set");
}
@@ -439,6 +462,12 @@
info.referrerUri = params.referrerUri;
info.grantedRuntimePermissions = params.grantedRuntimePermissions;
info.installFlags = params.installFlags;
+ info.isMultiPackage = params.isMultiPackage;
+ info.parentSessionId = mParentSessionId;
+ info.childSessionIds = mChildSessionIds.copyKeys();
+ if (info.childSessionIds == null) {
+ info.childSessionIds = EMPTY_CHILD_SESSION_ARRAY;
+ }
}
return info;
}
@@ -762,6 +791,92 @@
@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
+ if (!markAsCommitted(statusReceiver, forTransfer /* enforce */)) {
+ return;
+ }
+ if (isMultiPackage()) {
+
+ final SparseIntArray remainingSessions = mChildSessionIds.clone();
+ final ChildStatusIntentReceiver localIntentReceiver =
+ new ChildStatusIntentReceiver(remainingSessions, statusReceiver);
+ for (int childSessionId : getChildSessionIds()) {
+ mSessionProvider.getSession(childSessionId)
+ .markAsCommitted(localIntentReceiver.getIntentSender(), forTransfer);
+ }
+ }
+ mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
+ }
+
+ private class ChildStatusIntentReceiver {
+ private final SparseIntArray mChildSessionsRemaining;
+ private final IntentSender mStatusReceiver;
+ private final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+ IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
+ statusUpdate(intent);
+ }
+ };
+
+ private ChildStatusIntentReceiver(SparseIntArray remainingSessions,
+ IntentSender statusReceiver) {
+ this.mChildSessionsRemaining = remainingSessions;
+ this.mStatusReceiver = statusReceiver;
+ }
+
+ public IntentSender getIntentSender() {
+ return new IntentSender((IIntentSender) mLocalSender);
+ }
+
+ public void statusUpdate(Intent intent) {
+ mHandler.post(() -> {
+ if (mChildSessionsRemaining.size() == 0) {
+ return;
+ }
+ final int sessionId = intent.getIntExtra(
+ PackageInstaller.EXTRA_SESSION_ID, 0);
+ final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ final int sessionIndex = mChildSessionsRemaining.indexOfKey(sessionId);
+ if (PackageInstaller.STATUS_SUCCESS == status) {
+ mChildSessionsRemaining.removeAt(sessionIndex);
+ if (mChildSessionsRemaining.size() == 0) {
+ try {
+ intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
+ PackageInstallerSession.this.sessionId);
+ mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+ } catch (IntentSender.SendIntentException ignore) {
+ }
+ }
+ } else if (PackageInstaller.STATUS_PENDING_USER_ACTION == status) {
+ try {
+ mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+ } catch (IntentSender.SendIntentException ignore) {
+ }
+ } else {
+ intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
+ PackageInstallerSession.this.sessionId);
+ mChildSessionsRemaining.clear(); // we're done. Don't send any more.
+ try {
+ mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+ } catch (IntentSender.SendIntentException ignore) {
+ }
+ }
+ });
+ }
+ }
+
+
+ /**
+ * Do everything but actually commit the session. If this was not already called, the session
+ * will be sealed and marked as committed. The caller of this method is responsible for
+ * subsequently submitting this session for processing.
+ *
+ * This method may be called multiple times to update the status receiver validate caller
+ * permissions.
+ */
+ public boolean markAsCommitted(
+ @NonNull IntentSender statusReceiver, boolean forTransfer) {
Preconditions.checkNotNull(statusReceiver);
final boolean wasSealed;
@@ -786,6 +901,12 @@
}
}
+ // After validations and updating the observer, we can skip re-sealing, etc. because we
+ // have already marked ourselves as committed.
+ if (mCommitted) {
+ return true;
+ }
+
wasSealed = mSealed;
if (!mSealed) {
try {
@@ -796,7 +917,7 @@
// Do now throw an exception here to stay compatible with O and older
destroyInternal();
dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
- return;
+ return false;
}
}
@@ -809,7 +930,6 @@
mActiveCount.incrementAndGet();
mCommitted = true;
- mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}
if (!wasSealed) {
@@ -818,6 +938,7 @@
// the session lock, since otherwise it's a lock inversion.
mCallback.onSessionSealedBlocking(this);
}
+ return true;
}
/**
@@ -833,32 +954,37 @@
assertNoWriteFileTransfersOpenLocked();
assertPreparedAndNotDestroyedLocked("sealing of session");
- final PackageInfo pkgInfo = mPm.getPackageInfo(
- params.appPackageName, PackageManager.GET_SIGNATURES
- | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
-
- resolveStageDirLocked();
-
mSealed = true;
- try {
- if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
- validateApexInstallLocked(pkgInfo);
- } else {
- // Verify that stage looks sane with respect to existing application.
- // This currently only ensures packageName, versionCode, and certificate
- // consistency.
- validateApkInstallLocked(pkgInfo);
- }
- } catch (PackageManagerException e) {
- throw e;
- } catch (Throwable e) {
- // Convert all exceptions into package manager exceptions as only those are handled
- // in the code above
- throw new PackageManagerException(e);
- }
// Read transfers from the original owner stay open, but as the session's data
// cannot be modified anymore, there is no leak of information.
+ if (!params.isMultiPackage) {
+ final PackageInfo pkgInfo = mPm.getPackageInfo(
+ params.appPackageName, PackageManager.GET_SIGNATURES
+ | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+
+ resolveStageDirLocked();
+
+ // Verify that stage looks sane with respect to existing application.
+ // This currently only ensures packageName, versionCode, and certificate
+ // consistency.
+ try {
+ if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+ validateApexInstallLocked(pkgInfo);
+ } else {
+ // Verify that stage looks sane with respect to existing application.
+ // This currently only ensures packageName, versionCode, and certificate
+ // consistency.
+ validateApkInstallLocked(pkgInfo);
+ }
+ } catch (PackageManagerException e) {
+ throw e;
+ } catch (Throwable e) {
+ // Convert all exceptions into package manager exceptions as only those are handled
+ // in the code above
+ throw new PackageManagerException(e);
+ }
+ }
}
@Override
@@ -916,25 +1042,52 @@
@GuardedBy("mLock")
private void commitLocked()
throws PackageManagerException {
- if (mRelinquished) {
- Slog.d(TAG, "Ignoring commit after previous commit relinquished control");
+ final PackageManagerService.ActiveInstallSession committingSession =
+ makeSessionActiveLocked();
+ if (committingSession == null) {
return;
}
- if (mDestroyed) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
- }
- if (!mSealed) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
- }
-
- Preconditions.checkNotNull(mPackageName);
- Preconditions.checkNotNull(mSigningDetails);
- Preconditions.checkNotNull(mResolvedBaseFile);
-
- if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
- commitApexLocked();
+ if (isMultiPackage()) {
+ final int[] childSessionIds = getChildSessionIds();
+ List<PackageManagerService.ActiveInstallSession> childSessions =
+ new ArrayList<>(childSessionIds.length);
+ boolean success = true;
+ PackageManagerException failure = null;
+ for (int childSessionId : getChildSessionIds()) {
+ final PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
+ try {
+ final PackageManagerService.ActiveInstallSession activeSession =
+ session.makeSessionActiveLocked();
+ if (activeSession != null) {
+ if ((activeSession.getSessionParams().installFlags
+ & PackageManager.INSTALL_APEX) != 0) {
+ // TODO(b/118865310): Add exception to this case for staged installs
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+ "Atomic install is not supported for APEX packages.");
+ }
+ childSessions.add(activeSession);
+ }
+ } catch (PackageManagerException e) {
+ failure = e;
+ success = false;
+ }
+ }
+ if (!success) {
+ try {
+ mRemoteObserver.onPackageInstalled(
+ null, failure.error, failure.getLocalizedMessage(), null);
+ } catch (RemoteException ignored) {
+ }
+ return;
+ }
+ mPm.installStage(childSessions);
} else {
- commitApkLocked();
+ if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+ commitApexLocked();
+ } else {
+ mPm.installStage(committingSession);
+ }
}
}
@@ -943,7 +1096,7 @@
try {
IApexService apex = IApexService.Stub.asInterface(
ServiceManager.getService("apexservice"));
- apex.installPackage(mResolvedBaseFile.toString());
+ apex.stagePackage(mResolvedBaseFile.toString());
} catch (Throwable e) {
// Convert all exceptions into package manager exceptions as only those are handled
// in the code above
@@ -954,81 +1107,105 @@
}
}
+ /**
+ * Stages this session for install and returns a
+ * {@link PackageManagerService.ActiveInstallSession} representing this new staged state or null
+ * in case permissions need to be requested before install can proceed.
+ */
@GuardedBy("mLock")
- private void commitApkLocked() throws PackageManagerException {
- if (needToAskForPermissionsLocked()) {
- // User needs to confirm installation; give installer an intent they can use to involve
- // user.
- final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
- intent.setPackage(mPm.getPackageInstallerPackageName());
- intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- try {
- mRemoteObserver.onUserActionRequired(intent);
- } catch (RemoteException ignored) {
- }
-
- // Commit was keeping session marked as active until now; release
- // that extra refcount so session appears idle.
- closeInternal(false);
- return;
+ private PackageManagerService.ActiveInstallSession makeSessionActiveLocked()
+ throws PackageManagerException {
+ if (mRelinquished) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session relinquished");
+ }
+ if (mDestroyed) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
+ }
+ if (!mSealed) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
}
- // Inherit any packages and native libraries from existing install that
- // haven't been overridden.
- if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- try {
- final List<File> fromFiles = mResolvedInheritedFiles;
- final File toDir = resolveStageDirLocked();
+ if (!params.isMultiPackage) {
+ Preconditions.checkNotNull(mPackageName);
+ Preconditions.checkNotNull(mSigningDetails);
+ Preconditions.checkNotNull(mResolvedBaseFile);
- if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
- if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
- throw new IllegalStateException("mInheritedFilesBase == null");
+ if (needToAskForPermissionsLocked()) {
+ // User needs to confirm installation;
+ // give installer an intent they can use to involve
+ // user.
+ final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
+ intent.setPackage(mPm.getPackageInstallerPackageName());
+ intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ try {
+ mRemoteObserver.onUserActionRequired(intent);
+ } catch (RemoteException ignored) {
}
- if (isLinkPossible(fromFiles, toDir)) {
- if (!mResolvedInstructionSets.isEmpty()) {
- final File oatDir = new File(toDir, "oat");
- createOatDirs(mResolvedInstructionSets, oatDir);
+ // Commit was keeping session marked as active until now; release
+ // that extra refcount so session appears idle.
+ closeInternal(false);
+ return null;
+ }
+
+ // Inherit any packages and native libraries from existing install that
+ // haven't been overridden.
+ if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+ try {
+ final List<File> fromFiles = mResolvedInheritedFiles;
+ final File toDir = resolveStageDirLocked();
+
+ if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
+ if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
+ throw new IllegalStateException("mInheritedFilesBase == null");
}
- // pre-create lib dirs for linking if necessary
- if (!mResolvedNativeLibPaths.isEmpty()) {
- for (String libPath : mResolvedNativeLibPaths) {
- // "/lib/arm64" -> ["lib", "arm64"]
- final int splitIndex = libPath.lastIndexOf('/');
- if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
- Slog.e(TAG, "Skipping native library creation for linking due to "
- + "invalid path: " + libPath);
- continue;
- }
- final String libDirPath = libPath.substring(1, splitIndex);
- final File libDir = new File(toDir, libDirPath);
- if (!libDir.exists()) {
- NativeLibraryHelper.createNativeLibrarySubdir(libDir);
- }
- final String archDirPath = libPath.substring(splitIndex + 1);
- NativeLibraryHelper.createNativeLibrarySubdir(
- new File(libDir, archDirPath));
+
+ if (isLinkPossible(fromFiles, toDir)) {
+ if (!mResolvedInstructionSets.isEmpty()) {
+ final File oatDir = new File(toDir, "oat");
+ createOatDirs(mResolvedInstructionSets, oatDir);
}
+ // pre-create lib dirs for linking if necessary
+ if (!mResolvedNativeLibPaths.isEmpty()) {
+ for (String libPath : mResolvedNativeLibPaths) {
+ // "/lib/arm64" -> ["lib", "arm64"]
+ final int splitIndex = libPath.lastIndexOf('/');
+ if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+ Slog.e(TAG,
+ "Skipping native library creation for linking due to "
+ + "invalid path: " + libPath);
+ continue;
+ }
+ final String libDirPath = libPath.substring(1, splitIndex);
+ final File libDir = new File(toDir, libDirPath);
+ if (!libDir.exists()) {
+ NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+ }
+ final String archDirPath = libPath.substring(splitIndex + 1);
+ NativeLibraryHelper.createNativeLibrarySubdir(
+ new File(libDir, archDirPath));
+ }
+ }
+ linkFiles(fromFiles, toDir, mInheritedFilesBase);
+ } else {
+ // TODO: this should delegate to DCS so the system process
+ // avoids holding open FDs into containers.
+ copyFiles(fromFiles, toDir);
}
- linkFiles(fromFiles, toDir, mInheritedFilesBase);
- } else {
- // TODO: this should delegate to DCS so the system process
- // avoids holding open FDs into containers.
- copyFiles(fromFiles, toDir);
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+ "Failed to inherit existing install", e);
}
- } catch (IOException e) {
- throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to inherit existing install", e);
}
+
+ // TODO: surface more granular state from dexopt
+ mInternalProgress = 0.5f;
+ computeProgressLocked(true);
+
+ // Unpack native libraries
+ extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
}
-
- // TODO: surface more granular state from dexopt
- mInternalProgress = 0.5f;
- computeProgressLocked(true);
-
- // Unpack native libraries
- extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
-
// We've reached point of no return; call into PMS to install the stage.
// Regardless of success or failure we always destroy session.
final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
@@ -1053,8 +1230,11 @@
}
mRelinquished = true;
- mPm.installStage(mPackageName, stageDir, localObserver, params,
- mInstallerPackageName, mInstallerUid, user, mSigningDetails);
+ final PackageManagerService.ActiveInstallSession activeInstallSession =
+ new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
+ localObserver, params, mInstallerPackageName, mInstallerUid, user,
+ mSigningDetails);
+ return activeInstallSession;
}
private static void maybeRenameFile(File from, File to) throws PackageManagerException {
@@ -1556,6 +1736,14 @@
}
}
+ /**
+ * Adds a child session ID without any safety / sanity checks. This should only be used to
+ * build a session from XML or similar.
+ */
+ void addChildSessionIdInternal(int sessionId) {
+ mChildSessionIds.put(sessionId, 0);
+ }
+
public void open() throws IOException {
if (mActiveCount.getAndIncrement() == 0) {
mCallback.onSessionActiveChanged(this, true);
@@ -1567,6 +1755,8 @@
if (!mPrepared) {
if (stageDir != null) {
prepareStageDir(stageDir);
+ } else if (params.isMultiPackage) {
+ // it's all ok
} else {
throw new IllegalArgumentException("stageDir must be set");
}
@@ -1615,6 +1805,81 @@
dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
}
+ @Override
+ public boolean isMultiPackage() {
+ return params.isMultiPackage;
+ }
+
+ @Override
+ public int[] getChildSessionIds() {
+ final int[] childSessionIds = mChildSessionIds.copyKeys();
+ if (childSessionIds != null) {
+ return childSessionIds;
+ }
+ return EMPTY_CHILD_SESSION_ARRAY;
+ }
+
+ @Override
+ public void addChildSessionId(int sessionId) {
+ final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
+ if (session == null) {
+ throw new RemoteException("Unable to add child.",
+ new PackageManagerException("Child session " + sessionId + " does not exist"),
+ false, true).rethrowAsRuntimeException();
+ }
+ synchronized (mLock) {
+ final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+ if (indexOfSession >= 0) {
+ return;
+ }
+ session.setParentSessionId(this.sessionId);
+ addChildSessionIdInternal(sessionId);
+ }
+ }
+
+ @Override
+ public void removeChildSessionId(int sessionId) {
+ final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
+ synchronized (mLock) {
+ final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+ if (session != null) {
+ session.setParentSessionId(SessionInfo.INVALID_ID);
+ }
+ if (indexOfSession < 0) {
+ // not added in the first place; no-op
+ return;
+ }
+ mChildSessionIds.removeAt(indexOfSession);
+ }
+ }
+
+ /**
+ * Sets the parent session ID if not already set.
+ * If {@link SessionInfo#INVALID_ID} is passed, it will be unset.
+ */
+ void setParentSessionId(int parentSessionId) {
+ synchronized (mLock) {
+ if (parentSessionId != SessionInfo.INVALID_ID
+ && mParentSessionId != SessionInfo.INVALID_ID) {
+ throw new RemoteException("Unable to set parent session.",
+ new PackageManagerException(
+ "The parent of " + sessionId + " is" + " already set to "
+ + mParentSessionId), false,
+ true).rethrowAsRuntimeException();
+ }
+ this.mParentSessionId = parentSessionId;
+ }
+ }
+
+ boolean hasParentSessionId() {
+ return mParentSessionId != SessionInfo.INVALID_ID;
+ }
+
+ @Override
+ public int getParentSessionId() {
+ return mParentSessionId;
+ }
+
private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
final IPackageInstallObserver2 observer;
final String packageName;
@@ -1704,6 +1969,7 @@
pw.printPair("mBridges", mBridges.size());
pw.printPair("mFinalStatus", mFinalStatus);
pw.printPair("mFinalMessage", mFinalMessage);
+ pw.printPair("params.isMultiPackage", params.isMultiPackage);
pw.println();
pw.decreaseIndent();
@@ -1754,6 +2020,10 @@
writeBooleanAttribute(out, ATTR_PREPARED, isPrepared());
writeBooleanAttribute(out, ATTR_SEALED, isSealed());
+ writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
+ // TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
+ // we've read all sessions.
+ writeIntAttribute(out, ATTR_PARENT_SESSION_ID, mParentSessionId);
writeIntAttribute(out, ATTR_MODE, params.mode);
writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags);
writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation);
@@ -1788,6 +2058,12 @@
params.appIconLastModified = appIconFile.lastModified();
}
+ final int[] childSessionIds = getChildSessionIds();
+ for (int childSessionId : childSessionIds) {
+ out.startTag(null, TAG_CHILD_SESSION);
+ writeIntAttribute(out, ATTR_SESSION_ID, childSessionId);
+ out.endTag(null, TAG_CHILD_SESSION);
+ }
}
out.endTag(null, TAG_SESSION);
@@ -1832,11 +2108,15 @@
* @param installerThread Thread to be used for callbacks of this session
* @param sessionsDir The directory the sessions are stored in
*
+ * @param sessionProvider
* @return The newly created session
*/
+ // TODO(patb,109941548): modify readFromXml to consume to the next tag session tag so we
+ // can have a complete session for the constructor
public static PackageInstallerSession readFromXml(@NonNull XmlPullParser in,
@NonNull PackageInstallerService.InternalCallback callback, @NonNull Context context,
- @NonNull PackageManagerService pm, Looper installerThread, @NonNull File sessionsDir)
+ @NonNull PackageManagerService pm, Looper installerThread, @NonNull File sessionsDir,
+ @NonNull PackageSessionProvider sessionProvider)
throws IOException, XmlPullParserException {
final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
final int userId = readIntAttribute(in, ATTR_USER_ID);
@@ -1849,9 +2129,12 @@
final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
+ final int parentSessionId = readIntAttribute(in, ATTR_PARENT_SESSION_ID,
+ SessionInfo.INVALID_ID);
final SessionParams params = new SessionParams(
SessionParams.MODE_INVALID);
+ params.isMultiPackage = readBooleanAttribute(in, ATTR_MULTI_PACKAGE, false);
params.mode = readIntAttribute(in, ATTR_MODE);
params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS);
params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION);
@@ -1874,9 +2157,16 @@
params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath());
params.appIconLastModified = appIconFile.lastModified();
}
-
- return new PackageInstallerSession(callback, context, pm,
+ return new PackageInstallerSession(callback, context, pm, sessionProvider,
installerThread, sessionId, userId, installerPackageName, installerUid,
- params, createdMillis, stageDir, stageCid, prepared, sealed);
+ params, createdMillis, stageDir, stageCid, prepared, sealed,
+ EMPTY_CHILD_SESSION_ARRAY, parentSessionId);
+ }
+
+ /**
+ * Reads the session ID from a child session tag stored in the provided {@link XmlPullParser}
+ */
+ static int readChildSessionIdFromXml(@NonNull XmlPullParser in) {
+ return readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0e37bca..ed5b33b6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -60,6 +60,7 @@
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
import static android.content.pm.PackageManager.INSTALL_INTERNAL;
+import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
@@ -239,7 +240,6 @@
import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
-import android.permission.PermissionManager;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.security.KeyStore;
@@ -2930,60 +2930,6 @@
checkDefaultBrowser();
- // If a granted permission is split, all new permissions should be granted too
- if (mIsUpgrade) {
- final int callingUid = getCallingUid();
-
- final List<PermissionManager.SplitPermissionInfo> splitPermissions =
- mContext.getSystemService(PermissionManager.class).getSplitPermissions();
- final int numSplitPerms = splitPermissions.size();
- for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
- final PermissionManager.SplitPermissionInfo splitPerm =
- splitPermissions.get(splitPermNum);
- final String rootPerm = splitPerm.getSplitPermission();
-
- if (preUpgradeSdkVersion >= splitPerm.getTargetSdk()) {
- continue;
- }
-
- final int numPackages = mPackages.size();
- for (int packageNum = 0; packageNum < numPackages; packageNum++) {
- final PackageParser.Package pkg = mPackages.valueAt(packageNum);
-
- if (pkg.applicationInfo.targetSdkVersion >= splitPerm.getTargetSdk()
- || !pkg.requestedPermissions.contains(rootPerm)) {
- continue;
- }
-
- final int userId = UserHandle.getUserId(pkg.applicationInfo.uid);
- final String pkgName = pkg.packageName;
-
- if (checkPermission(rootPerm, pkgName, userId) == PERMISSION_DENIED) {
- continue;
- }
-
- final List<String> newPerms = splitPerm.getNewPermissions();
-
- final int numNewPerms = newPerms.size();
- for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
- final String newPerm = newPerms.get(newPermNum);
- if (checkPermission(newPerm, pkgName, userId) == PERMISSION_GRANTED) {
- continue;
- }
-
- if (DEBUG_PERMISSIONS) {
- Slog.v(TAG, "Granting " + newPerm + " to " + pkgName
- + " as the root permission " + rootPerm
- + " is already granted");
- }
-
- mPermissionManager.grantRuntimePermission(newPerm, pkgName, true,
- callingUid, userId, null);
- }
- }
- }
- }
-
// clear only after permissions and other defaults have been updated
mExistingSystemPackages.clear();
mPromoteSystemApps = false;
@@ -12129,8 +12075,7 @@
void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
mComponentResolver.removeAllComponents(pkg, chatty);
- final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
- mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty);
+ mPermissionManager.removeAllPermissions(pkg, chatty);
final int instrumentationSize = pkg.instrumentation.size();
StringBuilder r = null;
@@ -12358,28 +12303,15 @@
return installReason;
}
- void installStage(String packageName, File stagedDir,
- IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
- String installerPackageName, int installerUid, UserHandle user,
- PackageParser.SigningDetails signingDetails) {
+ void installStage(ActiveInstallSession activeInstallSession) {
if (DEBUG_INSTANT) {
- if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
- Slog.d(TAG, "Ephemeral install of " + packageName);
+ if ((activeInstallSession.getSessionParams().installFlags
+ & PackageManager.INSTALL_INSTANT_APP) != 0) {
+ Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
}
}
- final VerificationInfo verificationInfo = new VerificationInfo(
- sessionParams.originatingUri, sessionParams.referrerUri,
- sessionParams.originatingUid, installerUid);
-
- final OriginInfo origin = OriginInfo.fromStagedFile(stagedDir);
-
final Message msg = mHandler.obtainMessage(INIT_COPY);
- final int installReason = fixUpInstallReason(installerPackageName, installerUid,
- sessionParams.installReason);
- final InstallParams params = new InstallParams(origin, null, observer,
- sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
- verificationInfo, user, sessionParams.abiOverride,
- sessionParams.grantedRuntimePermissions, signingDetails, installReason);
+ final InstallParams params = new InstallParams(activeInstallSession);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -12391,6 +12323,22 @@
mHandler.sendMessage(msg);
}
+ void installStage(List<ActiveInstallSession> children)
+ throws PackageManagerException {
+ final Message msg = mHandler.obtainMessage(INIT_COPY);
+ final MultiPackageInstallParams params =
+ new MultiPackageInstallParams(UserHandle.ALL, children);
+ params.setTraceMethod("installStageMultiPackage")
+ .setTraceCookie(System.identityHashCode(params));
+ msg.obj = params;
+
+ Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
+ System.identityHashCode(msg.obj));
+ Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
+ System.identityHashCode(msg.obj));
+ mHandler.sendMessage(msg);
+ }
+
private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting,
int userId) {
final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
@@ -13568,88 +13516,113 @@
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
- // Queue up an async operation since the package installation may take a little while.
- mHandler.post(new Runnable() {
- public void run() {
- mHandler.removeCallbacks(this);
- // Result object to be returned
- PackageInstalledInfo res = new PackageInstalledInfo();
- res.setReturnCode(currentStatus);
- res.uid = -1;
- res.pkg = null;
- res.removedInfo = null;
- if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- args.doPreInstall(res.returnCode);
- synchronized (mInstallLock) {
- installPackageTracedLI(args, res);
- }
- args.doPostInstall(res.returnCode, res.uid);
+ if (args.mMultiPackageInstallParams != null) {
+ args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
+ } else {
+ PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
+ processInstallRequestsAsync(
+ res.returnCode == PackageManager.INSTALL_SUCCEEDED,
+ Collections.singletonList(new InstallRequest(args, res)));
+ }
+ }
+
+ // Queue up an async operation since the package installation may take a little while.
+ private void processInstallRequestsAsync(boolean success,
+ List<InstallRequest> installRequests) {
+ mHandler.post(() -> {
+ if (success) {
+ for (InstallRequest request : installRequests) {
+ request.args.doPreInstall(request.installResult.returnCode);
}
-
- // A restore should be performed at this point if (a) the install
- // succeeded, (b) the operation is not an update, and (c) the new
- // package has not opted out of backup participation.
- final boolean update = res.removedInfo != null
- && res.removedInfo.removedPackage != null;
- final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
- boolean doRestore = !update
- && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
-
- // Set up the post-install work request bookkeeping. This will be used
- // and cleaned up by the post-install event handling regardless of whether
- // there's a restore pass performed. Token values are >= 1.
- int token;
- if (mNextInstallToken < 0) mNextInstallToken = 1;
- token = mNextInstallToken++;
-
- PostInstallData data = new PostInstallData(args, res);
- mRunningInstalls.put(token, data);
- if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
-
- if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
- // Pass responsibility to the Backup Manager. It will perform a
- // restore if appropriate, then pass responsibility back to the
- // Package Manager to run the post-install observer callbacks
- // and broadcasts.
- IBackupManager bm = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- if (bm != null) {
- if (DEBUG_INSTALL) Log.v(TAG, "token " + token
- + " to BM for possible restore");
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
- try {
- // TODO: http://b/22388012
- if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
- bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
- } else {
- doRestore = false;
- }
- } catch (RemoteException e) {
- // can't happen; the backup manager is local
- } catch (Exception e) {
- Slog.e(TAG, "Exception trying to enqueue restore", e);
- doRestore = false;
- }
- } else {
- Slog.e(TAG, "Backup Manager not found!");
- doRestore = false;
- }
+ synchronized (mInstallLock) {
+ installPackagesTracedLI(installRequests);
}
-
- if (!doRestore) {
- // No restore possible, or the Backup Manager was mysteriously not
- // available -- just fire the post-install work request directly.
- if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
-
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
-
- Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
- mHandler.sendMessage(msg);
+ for (InstallRequest request : installRequests) {
+ request.args.doPostInstall(
+ request.installResult.returnCode, request.installResult.uid);
}
}
+ for (InstallRequest request : installRequests) {
+ resolvePackageInstalledInfo(request.args,
+ request.installResult);
+ }
});
}
+ private PackageInstalledInfo createPackageInstalledInfo(
+ int currentStatus) {
+ PackageInstalledInfo res = new PackageInstalledInfo();
+ res.setReturnCode(currentStatus);
+ res.uid = -1;
+ res.pkg = null;
+ res.removedInfo = null;
+ return res;
+ }
+
+ private void resolvePackageInstalledInfo(InstallArgs args, PackageInstalledInfo res) {
+ // A restore should be performed at this point if (a) the install
+ // succeeded, (b) the operation is not an update, and (c) the new
+ // package has not opted out of backup participation.
+ final boolean update = res.removedInfo != null
+ && res.removedInfo.removedPackage != null;
+ final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
+ boolean doRestore = !update
+ && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
+
+ // Set up the post-install work request bookkeeping. This will be used
+ // and cleaned up by the post-install event handling regardless of whether
+ // there's a restore pass performed. Token values are >= 1.
+ int token;
+ if (mNextInstallToken < 0) mNextInstallToken = 1;
+ token = mNextInstallToken++;
+
+ PostInstallData data = new PostInstallData(args, res);
+ mRunningInstalls.put(token, data);
+ if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
+
+ if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
+ // Pass responsibility to the Backup Manager. It will perform a
+ // restore if appropriate, then pass responsibility back to the
+ // Package Manager to run the post-install observer callbacks
+ // and broadcasts.
+ IBackupManager bm = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ if (bm != null) {
+ if (DEBUG_INSTALL) {
+ Log.v(TAG, "token " + token + " to BM for possible restore");
+ }
+ Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
+ try {
+ // TODO: http://b/22388012
+ if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
+ bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
+ } else {
+ doRestore = false;
+ }
+ } catch (RemoteException e) {
+ // can't happen; the backup manager is local
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception trying to enqueue restore", e);
+ doRestore = false;
+ }
+ } else {
+ Slog.e(TAG, "Backup Manager not found!");
+ doRestore = false;
+ }
+ }
+
+ if (!doRestore) {
+ // No restore possible, or the Backup Manager was mysteriously not
+ // available -- just fire the post-install work request directly.
+ if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
+
+ Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
+
+ Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
+ mHandler.sendMessage(msg);
+ }
+ }
+
/**
* Callback from PackageSettings whenever an app is first transitioned out of the
* 'stopped' state. Normally we just issue the broadcast, but we can't do that if
@@ -13837,7 +13810,83 @@
}
}
+ /**
+ * Container for a multi-package install which refers to all install sessions and args being
+ * committed together.
+ */
+ class MultiPackageInstallParams extends HandlerParams {
+
+ private int mRet = INSTALL_SUCCEEDED;
+ @NonNull
+ private final ArrayList<InstallParams> mChildParams;
+ @NonNull
+ private final Map<InstallArgs, Integer> mVerifiedState;
+
+ MultiPackageInstallParams(
+ @NonNull UserHandle user,
+ @NonNull List<ActiveInstallSession> activeInstallSessions)
+ throws PackageManagerException {
+ super(user);
+ if (activeInstallSessions.size() == 0) {
+ throw new PackageManagerException("No child sessions found!");
+ }
+ mChildParams = new ArrayList<>(activeInstallSessions.size());
+ for (int i = 0; i < activeInstallSessions.size(); i++) {
+ final InstallParams childParams = new InstallParams(activeInstallSessions.get(i));
+ childParams.mParentInstallParams = this;
+ this.mChildParams.add(childParams);
+ }
+ this.mVerifiedState = new ArrayMap<>(mChildParams.size());
+ }
+
+ @Override
+ void handleStartCopy() {
+ for (InstallParams params : mChildParams) {
+ params.handleStartCopy();
+ if (params.mRet != INSTALL_SUCCEEDED) {
+ mRet = params.mRet;
+ break;
+ }
+ }
+ }
+
+ @Override
+ void handleReturnCode() {
+ for (InstallParams params : mChildParams) {
+ params.handleReturnCode();
+ if (params.mRet != INSTALL_SUCCEEDED) {
+ mRet = params.mRet;
+ break;
+ }
+ }
+ }
+
+ void tryProcessInstallRequest(InstallArgs args, int currentStatus) {
+ mVerifiedState.put(args, currentStatus);
+ boolean success = true;
+ if (mVerifiedState.size() != mChildParams.size()) {
+ return;
+ }
+ for (Integer status : mVerifiedState.values()) {
+ if (status == PackageManager.INSTALL_UNKNOWN) {
+ return;
+ } else if (status != PackageManager.INSTALL_SUCCEEDED) {
+ success = false;
+ break;
+ }
+ }
+ final List<InstallRequest> installRequests = new ArrayList<>(mVerifiedState.size());
+ for (Map.Entry<InstallArgs, Integer> entry : mVerifiedState.entrySet()) {
+ installRequests.add(new InstallRequest(entry.getKey(),
+ createPackageInstalledInfo(entry.getValue())));
+ }
+ processInstallRequestsAsync(success, installRequests);
+ }
+ }
+
class InstallParams extends HandlerParams {
+ // TODO: see if we can collapse this into ActiveInstallSession
+
final OriginInfo origin;
final MoveInfo move;
final IPackageInstallObserver2 observer;
@@ -13845,17 +13894,20 @@
final String installerPackageName;
final String volumeUuid;
private InstallArgs mArgs;
- private int mRet;
+ int mRet;
final String packageAbiOverride;
final String[] grantedRuntimePermissions;
final VerificationInfo verificationInfo;
final PackageParser.SigningDetails signingDetails;
final int installReason;
+ @Nullable
+ MultiPackageInstallParams mParentInstallParams;
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
- String[] grantedPermissions, PackageParser.SigningDetails signingDetails, int installReason) {
+ String[] grantedPermissions, PackageParser.SigningDetails signingDetails,
+ int installReason) {
super(user);
this.origin = origin;
this.move = move;
@@ -13870,6 +13922,34 @@
this.installReason = installReason;
}
+ InstallParams(ActiveInstallSession activeInstallSession) {
+ super(activeInstallSession.getUser());
+ if (DEBUG_INSTANT) {
+ if ((activeInstallSession.getSessionParams().installFlags
+ & PackageManager.INSTALL_INSTANT_APP) != 0) {
+ Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
+ }
+ }
+ verificationInfo = new VerificationInfo(
+ activeInstallSession.getSessionParams().originatingUri,
+ activeInstallSession.getSessionParams().referrerUri,
+ activeInstallSession.getSessionParams().originatingUid,
+ activeInstallSession.getInstallerUid());
+ origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
+ move = null;
+ installReason = fixUpInstallReason(activeInstallSession.getInstallerPackageName(),
+ activeInstallSession.getInstallerUid(),
+ activeInstallSession.getSessionParams().installReason);
+ observer = activeInstallSession.getObserver();
+ installFlags = activeInstallSession.getSessionParams().installFlags;
+ installerPackageName = activeInstallSession.getInstallerPackageName();
+ volumeUuid = activeInstallSession.getSessionParams().volumeUuid;
+ packageAbiOverride = activeInstallSession.getSessionParams().abiOverride;
+ grantedRuntimePermissions =
+ activeInstallSession.getSessionParams().grantedRuntimePermissions;
+ signingDetails = activeInstallSession.getSigningDetails();
+ }
+
@Override
public String toString() {
return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
@@ -14291,6 +14371,7 @@
final int traceCookie;
final PackageParser.SigningDetails signingDetails;
final int installReason;
+ @Nullable final MultiPackageInstallParams mMultiPackageInstallParams;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -14301,8 +14382,9 @@
int installFlags, String installerPackageName, String volumeUuid,
UserHandle user, String[] instructionSets,
String abiOverride, String[] installGrantPermissions,
- String traceMethod, int traceCookie, PackageParser.SigningDetails signingDetails,
- int installReason) {
+ String traceMethod, int traceCookie, SigningDetails signingDetails,
+ int installReason,
+ MultiPackageInstallParams multiPackageInstallParams) {
this.origin = origin;
this.move = move;
this.installFlags = installFlags;
@@ -14317,6 +14399,7 @@
this.traceCookie = traceCookie;
this.signingDetails = signingDetails;
this.installReason = installReason;
+ this.mMultiPackageInstallParams = multiPackageInstallParams;
}
abstract int copyApk();
@@ -14412,7 +14495,7 @@
params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
params.grantedRuntimePermissions,
params.traceMethod, params.traceCookie, params.signingDetails,
- params.installReason);
+ params.installReason, params.mParentInstallParams);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -14422,7 +14505,7 @@
FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
null, null, null, 0, PackageParser.SigningDetails.UNKNOWN,
- PackageManager.INSTALL_REASON_UNKNOWN);
+ PackageManager.INSTALL_REASON_UNKNOWN, null /* parent */);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
}
@@ -14614,7 +14697,7 @@
params.getUser(), null /* instruction sets */, params.packageAbiOverride,
params.grantedRuntimePermissions,
params.traceMethod, params.traceCookie, params.signingDetails,
- params.installReason);
+ params.installReason, params.mParentInstallParams);
}
int copyApk() {
@@ -15019,10 +15102,10 @@
}
@GuardedBy({"mInstallLock", "mPackages"})
- private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo installResult) {
+ private void installPackagesTracedLI(List<InstallRequest> requests) {
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
- installPackagesLI(Collections.singletonList(new InstallRequest(args, installResult)));
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
+ installPackagesLI(requests);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -15362,7 +15445,7 @@
request.installResult.setError(
PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
"Duplicate package " + result.pkgSetting.pkg.packageName
- + " in atomic install request.");
+ + " in multi-package install request.");
return;
}
}
@@ -23434,6 +23517,62 @@
return mProtectedPackages.isPackageStateProtected(userId, packageName);
}
+
+ static class ActiveInstallSession {
+ private final String mPackageName;
+ private final File mStagedDir;
+ private final IPackageInstallObserver2 mObserver;
+ private final PackageInstaller.SessionParams mSessionParams;
+ private final String mInstallerPackageName;
+ private final int mInstallerUid;
+ private final UserHandle mUser;
+ private final SigningDetails mSigningDetails;
+
+ ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer,
+ PackageInstaller.SessionParams sessionParams, String installerPackageName,
+ int installerUid, UserHandle user, SigningDetails signingDetails) {
+ mPackageName = packageName;
+ mStagedDir = stagedDir;
+ mObserver = observer;
+ mSessionParams = sessionParams;
+ mInstallerPackageName = installerPackageName;
+ mInstallerUid = installerUid;
+ mUser = user;
+ mSigningDetails = signingDetails;
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public File getStagedDir() {
+ return mStagedDir;
+ }
+
+ public IPackageInstallObserver2 getObserver() {
+ return mObserver;
+ }
+
+ public PackageInstaller.SessionParams getSessionParams() {
+ return mSessionParams;
+ }
+
+ public String getInstallerPackageName() {
+ return mInstallerPackageName;
+ }
+
+ public int getInstallerUid() {
+ return mInstallerUid;
+ }
+
+ public UserHandle getUser() {
+ return mUser;
+ }
+
+ public SigningDetails getSigningDetails() {
+ return mSigningDetails;
+ }
+ }
}
interface PackageSender {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 38bd172..31711e5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -173,6 +173,8 @@
return runSetInstallLocation();
case "get-install-location":
return runGetInstallLocation();
+ case "install-add-session":
+ return runInstallAddSession();
case "move-package":
return runMovePackage();
case "move-primary-storage":
@@ -983,6 +985,23 @@
return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
}
+ private int runInstallAddSession() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final int parentSessionId = Integer.parseInt(getNextArg());
+
+ List<Integer> otherSessionIds = new ArrayList<>();
+ String opt;
+ while ((opt = getNextArg()) != null) {
+ otherSessionIds.add(Integer.parseInt(opt));
+ }
+ if (otherSessionIds.size() == 0) {
+ pw.println("Error: At least two sessions are required.");
+ return 1;
+ }
+ return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
+ true /*logSuccess*/);
+ }
+
private int runInstallRemove() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
@@ -2268,6 +2287,9 @@
case "--apex":
sessionParams.installFlags |= PackageManager.INSTALL_APEX;
break;
+ case "--multi-package":
+ sessionParams.setMultiPackage();
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
@@ -2500,6 +2522,30 @@
}
}
+ private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
+ throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ PackageInstaller.Session session = null;
+ try {
+ session = new PackageInstaller.Session(
+ mInterface.getPackageInstaller().openSession(parentId));
+ if (!session.isMultiPackage()) {
+ getErrPrintWriter().println(
+ "Error: parent session ID is not a multi-package session");
+ return 1;
+ }
+ for (int i = 0; i < sessionIds.length; i++) {
+ session.addChildSessionId(sessionIds[i]);
+ }
+ if (logSuccess) {
+ pw.println("Success");
+ }
+ return 0;
+ } finally {
+ IoUtils.closeQuietly(session);
+ }
+ }
+
private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
@@ -2521,24 +2567,26 @@
}
}
- private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
+ private int doCommitSession(int sessionId, boolean logSuccess)
+ throws RemoteException {
+
final PrintWriter pw = getOutPrintWriter();
PackageInstaller.Session session = null;
try {
session = new PackageInstaller.Session(
mInterface.getPackageInstaller().openSession(sessionId));
-
- // Sanity check that all .dm files match an apk.
- // (The installer does not support standalone .dm files and will not process them.)
- try {
- DexMetadataHelper.validateDexPaths(session.getNames());
- } catch (IllegalStateException | IOException e) {
- pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
+ if (!session.isMultiPackage()) {
+ // Sanity check that all .dm files match an apk.
+ // (The installer does not support standalone .dm files and will not process them.)
+ try {
+ DexMetadataHelper.validateDexPaths(session.getNames());
+ } catch (IllegalStateException | IOException e) {
+ pw.println(
+ "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
+ }
}
-
final LocalIntentReceiver receiver = new LocalIntentReceiver();
session.commit(receiver.getIntentSender());
-
final Intent result = receiver.getResult();
final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
@@ -2809,6 +2857,7 @@
pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
+ pw.println(" [--multi-package]");
pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
pw.println(" to push data into the session, and \"install-commit\" to finish.");
pw.println("");
@@ -2817,6 +2866,9 @@
pw.println(" will be read from stdin. Options are:");
pw.println(" -S: size in bytes of package, required for stdin");
pw.println("");
+ pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
+ pw.println(" Add one or more session IDs to a multi-package session.");
+ pw.println("");
pw.println(" install-commit SESSION_ID");
pw.println(" Commit the given active install session, installing the app.");
pw.println("");
diff --git a/services/core/java/com/android/server/pm/PackageSessionProvider.java b/services/core/java/com/android/server/pm/PackageSessionProvider.java
new file mode 100644
index 0000000..af11e77
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageSessionProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+/** Provides access to individual sessions managed by the install service */
+public interface PackageSessionProvider {
+
+ /**
+ * Get the sessions for the provided session IDs. Null will be returned for session IDs that
+ * do not exist.
+ */
+ PackageInstallerSession getSession(int sessionId);
+
+}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e2818b7..13bb817 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -20,6 +20,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -256,6 +257,7 @@
private static final String ATTR_USER_SET = "set";
private static final String ATTR_USER_FIXED = "fixed";
private static final String ATTR_REVOKE_ON_UPGRADE = "rou";
+ private static final String ATTR_REVOKE_WHEN_REQUESTED = "rwr";
// Flag mask of restored permission grants that are applied at install time
private static final int USER_RUNTIME_GRANT_MASK =
@@ -2775,13 +2777,13 @@
// dataPath - path to package's data path
// seinfo - seinfo label for the app (assigned at install time)
// gids - supplementary gids this app launches with
+ // profileableFromShellFlag - 0 or 1 if the package is profileable from shell.
//
// NOTE: We prefer not to expose all ApplicationInfo flags for now.
//
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
- // frameworks/base/libs/packagelistparser
- // system/core/run-as/run-as.c
+ // system/core/libpackagelistparser
//
sb.setLength(0);
sb.append(ai.packageName);
@@ -2801,6 +2803,8 @@
} else {
sb.append("none");
}
+ sb.append(" ");
+ sb.append(ai.isProfileableByShell() ? "1" : "0");
sb.append("\n");
writer.append(sb);
}
@@ -5011,6 +5015,9 @@
if ((g.grantBits&FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
pw.print(" revoke_on_upgrade");
}
+ if ((g.grantBits & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
+ pw.print(" revoke_when_requested");
+ }
pw.println();
}
}
@@ -5326,6 +5333,11 @@
if ((g.grantBits&FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
serializer.attribute(null, ATTR_REVOKE_ON_UPGRADE, "true");
}
+ if ((g.grantBits & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)
+ != 0) {
+ serializer.attribute(null, ATTR_REVOKE_WHEN_REQUESTED,
+ "true");
+ }
serializer.endTag(null, TAG_PERMISSION_ENTRY);
}
serializer.endTag(null, TAG_RESTORED_RUNTIME_PERMISSIONS);
@@ -5512,6 +5524,10 @@
if ("true".equals(parser.getAttributeValue(null, ATTR_REVOKE_ON_UPGRADE))) {
permBits |= FLAG_PERMISSION_REVOKE_ON_UPGRADE;
}
+ if ("true".equals(parser.getAttributeValue(null,
+ ATTR_REVOKE_WHEN_REQUESTED))) {
+ permBits |= FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+ }
if (isGranted || permBits != 0) {
rememberRestoredUserGrantLPr(pkgName, permName, isGranted, permBits, userId);
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 753c283..580e4f4 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -35,6 +35,7 @@
import android.util.jar.StrictJarFile;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
@@ -153,7 +154,7 @@
* @param classPaths the class paths corresponding to the class loaders names from
* {@param classLoadersNames}. The the first element corresponds to the first class loader
* and so on. A classpath is represented as a list of dex files separated by
- * {@code File.pathSeparator}.
+ * {@code File.pathSeparator}, or null if the class loader's classpath is not known.
* The dex files found in the first class path will be recorded in the usage file.
* @param loaderIsa the ISA of the app loading the dex files
* @param loaderUserId the user id which runs the code loading the dex files
@@ -169,7 +170,8 @@
}
}
- private void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
+ @VisibleForTesting
+ /*package*/ void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
List<String> classLoaderNames, List<String> classPaths, String loaderIsa,
int loaderUserId) {
if (classLoaderNames.size() != classPaths.size()) {
@@ -186,8 +188,14 @@
return;
}
+ // The first classpath should never be null because the first classloader
+ // should always be an instance of BaseDexClassLoader.
+ String firstClassPath = classPaths.get(0);
+ if (firstClassPath == null) {
+ return;
+ }
// The classpath is represented as a list of dex files separated by File.pathSeparator.
- String[] dexPathsToRegister = classPaths.get(0).split(File.pathSeparator);
+ String[] dexPathsToRegister = firstClassPath.split(File.pathSeparator);
// Encode the class loader contexts for the dexPathsToRegister.
String[] classLoaderContexts = DexoptUtils.processContextForDexLoad(
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index e1310a2..d2600b5 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -318,7 +318,8 @@
// is fine (they come over binder). Even if something changes we expect the sizes to be
// very small and it shouldn't matter much.
for (int i = 1; i < classLoadersNames.size(); i++) {
- if (!ClassLoaderFactory.isValidClassLoaderName(classLoadersNames.get(i))) {
+ if (!ClassLoaderFactory.isValidClassLoaderName(classLoadersNames.get(i))
+ || classPaths.get(i) == null) {
return null;
}
String classpath = encodeClasspath(classPaths.get(i).split(File.pathSeparator));
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 9d1a301..32b2bf0 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.app.DownloadManager;
import android.app.SearchManager;
import android.app.admin.DevicePolicyManager;
@@ -1009,6 +1010,41 @@
}
}
+ /**
+ * Check if a permission is already fixed or is set by the user.
+ *
+ * <p>A permission should not be set by the default policy if the user or other policies already
+ * set the permission.
+ *
+ * @param flags The flags of the permission
+ *
+ * @return {@code true} iff the permission can be set without violating a policy of the users
+ * intention
+ */
+ private boolean isFixedOrUserSet(int flags) {
+ return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
+ | PackageManager.FLAG_PERMISSION_USER_FIXED
+ | PackageManager.FLAG_PERMISSION_POLICY_FIXED
+ | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) != 0;
+ }
+
+ /**
+ * Return the background permission for a permission.
+ *
+ * @param permission The name of the foreground permission
+ *
+ * @return The name of the background permission or {@code null} if the permission has no
+ * background permission
+ */
+ private @Nullable String getBackgroundPermission(@NonNull String permission) {
+ try {
+ return mContext.getPackageManager().getPermissionInfo(permission,
+ 0).backgroundPermission;
+ } catch (NameNotFoundException e) {
+ return null;
+ }
+ }
+
private void grantRuntimePermissions(PackageInfo pkg,
Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
int userId) {
@@ -1021,9 +1057,15 @@
return;
}
+ PackageManager pm = mContext.getPackageManager();
final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
ApplicationInfo applicationInfo = pkg.applicationInfo;
+ int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+ if (systemFixed) {
+ newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+ }
+
// Automatically attempt to grant split permissions to older APKs
final List<PermissionManager.SplitPermissionInfo> splitPermissions =
mContext.getSystemService(PermissionManager.class).getSplitPermissions();
@@ -1063,9 +1105,28 @@
}
}
- final int grantablePermissionCount = requestedPermissions.length;
- for (int i = 0; i < grantablePermissionCount; i++) {
+ final int numRequestedPermissions = requestedPermissions.length;
+
+ // Sort requested permissions so that all permissions that are a foreground permission (i.e.
+ // permisions that have background permission) are before their background permissions.
+ final String[] sortedRequestedPermissions = new String[numRequestedPermissions];
+ int numForeground = 0;
+ int numOther = 0;
+ for (int i = 0; i < numRequestedPermissions; i++) {
String permission = requestedPermissions[i];
+ if (getBackgroundPermission(permission) != null) {
+ sortedRequestedPermissions[numForeground] = permission;
+ numForeground++;
+ } else {
+ sortedRequestedPermissions[numRequestedPermissions - 1 - numOther] =
+ permission;
+ numOther++;
+ }
+ }
+
+ for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions;
+ requestedPermissionNum++) {
+ String permission = requestedPermissions[requestedPermissionNum];
// If there is a disabled system app it may request a permission the updated
// version ot the data partition doesn't, In this case skip the permission.
@@ -1078,13 +1139,14 @@
final int flags = mContext.getPackageManager().getPermissionFlags(
permission, pkg.packageName, user);
- // If any flags are set to the permission, then it is either set in
- // its current state by the system or device/profile owner or the user.
- // In all these cases we do not want to clobber the current state.
+ // Certain flags imply that the permission's current state by the system or
+ // device/profile owner or the user. In these cases we do not want to clobber the
+ // current state.
+ //
// 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 || ignoreSystemPackage) {
+ if (!isFixedOrUserSet(flags) || ignoreSystemPackage) {
// Never clobber policy fixed permissions.
// We must allow the grant of a system-fixed permission because
// system-fixed is sticky, but the permission itself may be revoked.
@@ -1092,20 +1154,58 @@
continue;
}
+ int uid = UserHandle.getUid(userId,
+ UserHandle.getAppId(pkg.applicationInfo.uid));
+ String op = AppOpsManager.permissionToOp(permission);
+
mContext.getPackageManager()
.grantRuntimePermission(pkg.packageName, permission, user);
+
+ mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
+ newFlags, newFlags, user);
+
+ List<String> fgPerms = mPermissionManager.getBackgroundPermissions()
+ .get(permission);
+ if (fgPerms != null) {
+ int numFgPerms = fgPerms.size();
+ for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
+ String fgPerm = fgPerms.get(fgPermNum);
+
+ if (pm.checkPermission(fgPerm, pkg.packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ // Upgrade the app-op state of the fg permission to allow bg access
+ mContext.getSystemService(AppOpsManager.class).setMode(
+ AppOpsManager.permissionToOp(fgPerm), uid,
+ pkg.packageName, AppOpsManager.MODE_ALLOWED);
+
+ break;
+ }
+ }
+ }
+
+ String bgPerm = getBackgroundPermission(permission);
+ if (bgPerm == null) {
+ if (op != null) {
+ mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
+ pkg.packageName, AppOpsManager.MODE_ALLOWED);
+ }
+ } else {
+ int mode;
+ if (pm.checkPermission(bgPerm, pkg.packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ mode = AppOpsManager.MODE_ALLOWED;
+ } else {
+ mode = AppOpsManager.MODE_FOREGROUND;
+ }
+
+ mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
+ pkg.packageName, mode);
+ }
+
if (DEBUG) {
Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
+ permission + " to default handler " + pkg);
}
-
- int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
- if (systemFixed) {
- newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
- }
-
- mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
- newFlags, newFlags, user);
}
// If a component gets a permission for being the default handler A
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index ffc4731..88b97ea 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -1,8 +1,9 @@
per-file DefaultPermissionGrantPolicy.java = bpoiesz@google.com
-per-file DefaultPermissionGrantPolicy.java = fkupolov@google.com
per-file DefaultPermissionGrantPolicy.java = hackbod@android.com
per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com
per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com
per-file DefaultPermissionGrantPolicy.java = toddke@google.com
per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
per-file DefaultPermissionGrantPolicy.java = patb@google.com
+per-file DefaultPermissionGrantPolicy.java = eugenesusla@google.com
+per-file DefaultPermissionGrantPolicy.java = moltmann@google.com
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index 80a5fbb6..ec15c16 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -107,11 +107,7 @@
*/
public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty);
- public abstract void removeAllPermissions(
- @NonNull PackageParser.Package pkg,
- @NonNull List<String> allPackageNames,
- @Nullable PermissionCallback permissionCallback,
- boolean chatty);
+ public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,
int callingUid, @Nullable PermissionCallback callback);
public abstract void removeDynamicPermission(@NonNull String permName, int callingUid,
@@ -185,4 +181,4 @@
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 4b6760c..b788935 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -16,10 +16,28 @@
package com.android.server.pm.permission;
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
+import static android.app.AppOpsManager.MODE_ERRORED;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.permissionToOp;
+import static android.app.AppOpsManager.permissionToOpCode;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.UserHandle.getAppId;
+import static android.os.UserHandle.getUid;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
@@ -30,8 +48,10 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
@@ -39,7 +59,6 @@
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.metrics.LogMaker;
-import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -51,6 +70,7 @@
import android.os.UserManagerInternal;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.permission.PermissionManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -154,6 +174,13 @@
@GuardedBy("mLock")
private boolean mSystemReady;
+ /**
+ * For each foreground/background permission the mapping:
+ * Background permission -> foreground permissions
+ */
+ @GuardedBy("mLock")
+ private ArrayMap<String, List<String>> mBackgroundPermissions;
+
PermissionManagerService(Context context,
@Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
@NonNull Object externalLock) {
@@ -478,9 +505,8 @@
" to " + newPermissionGroupName);
try {
- revokeRuntimePermission(permissionName, packageName,
- mSettings.getPermission(permissionName), false,
- Process.SYSTEM_UID, userId, permissionCallback, false);
+ revokeRuntimePermission(permissionName, packageName, false,
+ Process.SYSTEM_UID, userId, permissionCallback);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Could not revoke " + permissionName + " from "
+ packageName, e);
@@ -573,59 +599,9 @@
}
- private void revokeAllPermissions(
- @NonNull List<BasePermission> bps,
- @NonNull List<String> allPackageNames,
- @Nullable PermissionCallback permissionCallback) {
- AsyncTask.execute(() -> {
- final int numRemovedPermissions = bps.size();
- for (int permissionNum = 0; permissionNum < numRemovedPermissions; permissionNum++) {
- final int[] userIds = mUserManagerInt.getUserIds();
- final int numUserIds = userIds.length;
-
- final int numPackages = allPackageNames.size();
- for (int packageNum = 0; packageNum < numPackages; packageNum++) {
- final String packageName = allPackageNames.get(packageNum);
- final ApplicationInfo applicationInfo = mPackageManagerInt.getApplicationInfo(
- packageName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
- if (applicationInfo != null
- && applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- continue;
- }
- for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
- final int userId = userIds[userIdNum];
- final String permissionName = bps.get(permissionNum).getName();
- if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM,
- userId) == PackageManager.PERMISSION_GRANTED) {
- try {
- revokeRuntimePermission(
- permissionName,
- packageName,
- bps.get(permissionNum),
- false,
- Process.SYSTEM_UID,
- userId,
- permissionCallback,
- true);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Could not revoke " + permissionName + " from "
- + packageName, e);
- }
- }
- }
- }
- }
- });
- }
-
- private void removeAllPermissions(
- @NonNull PackageParser.Package pkg,
- @NonNull List<String> allPackageNames,
- @Nullable PermissionCallback permissionCallback,
- boolean chatty) {
+ private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
synchronized (mLock) {
int N = pkg.permissions.size();
- List<BasePermission> bps = new ArrayList<BasePermission>(N);
StringBuilder r = null;
for (int i=0; i<N; i++) {
PackageParser.Permission p = pkg.permissions.get(i);
@@ -634,9 +610,6 @@
bp = mSettings.mPermissionTrees.get(p.info.name);
}
if (bp != null && bp.isPermission(p)) {
- if ((p.info.getProtection() & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
- bps.add(bp);
- }
bp.setPermission(null);
if (DEBUG_REMOVE && chatty) {
if (r == null) {
@@ -655,7 +628,6 @@
}
}
}
- revokeAllPermissions(bps, allPackageNames, permissionCallback);
if (r != null) {
if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
}
@@ -737,8 +709,24 @@
}
}
- private void grantPermissions(PackageParser.Package pkg, boolean replace,
- String packageOfInterest, PermissionCallback callback) {
+ /**
+ * Restore the permission state for a package.
+ *
+ * <ul>
+ * <li>During boot the state gets restored from the disk</li>
+ * <li>During app update the state gets restored from the last version of the app</li>
+ * </ul>
+ *
+ * <p>This restores the permission state for all users.
+ *
+ * @param pkg the package the permissions belong to
+ * @param replace if the package is getting replaced (this might change the requested
+ * permissions of this package)
+ * @param packageOfInterest If this is the name of {@code pkg} add extra logging
+ * @param callback Result call back
+ */
+ private void restorePermissionState(@NonNull PackageParser.Package pkg, boolean replace,
+ @Nullable String packageOfInterest, @Nullable PermissionCallback callback) {
// IMPORTANT: There are two types of permissions: install and runtime.
// Install time permissions are granted when the app is installed to
// all device users and users added in the future. Runtime permissions
@@ -866,7 +854,8 @@
}
if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Granting permission " + perm + " to package " + pkg.packageName);
+ Slog.i(TAG, "Considering granting permission " + perm + " to package "
+ + pkg.packageName);
}
if (grant != GRANT_DENIED) {
@@ -1055,6 +1044,11 @@
// changed.
ps.setInstallPermissionsFixed(true);
}
+
+ updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg,
+ updatedUserIds);
+ updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
+ permissionsState, pkg, updatedUserIds);
}
// Persist the runtime permissions state for users with changes. If permissions
@@ -1065,6 +1059,317 @@
}
}
+ /**
+ * Set app op for a app-op related to a permission.
+ *
+ * @param permission The permission the app-op belongs to
+ * @param pkg The package the permission belongs to
+ * @param userId The user to be changed
+ * @param mode The new mode to set
+ */
+ private void setAppOpMode(@NonNull String permission, @NonNull PackageParser.Package pkg,
+ @UserIdInt int userId, int mode) {
+ AppOpsManagerInternal appOpsInternal = LocalServices.getService(
+ AppOpsManagerInternal.class);
+
+ appOpsInternal.setMode(permissionToOpCode(permission),
+ getUid(userId, getAppId(pkg.applicationInfo.uid)), pkg.packageName, mode,
+ (pkg.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0);
+ }
+
+ /**
+ * Revoke permissions that are not implicit anymore and that have
+ * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set.
+ *
+ * @param ps The state of the permissions of the package
+ * @param pkg The package that is currently looked at
+ * @param updatedUserIds a list of user ids that needs to be amended if the permission state
+ * for a user is changed.
+ *
+ * @return The updated value of the {@code updatedUserIds} parameter
+ */
+ private @NonNull int[] revokePermissionsNoLongerImplicitLocked(
+ @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+ @NonNull int[] updatedUserIds) {
+ AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+
+ String pkgName = pkg.packageName;
+
+ int[] users = UserManagerService.getInstance().getUserIds();
+ int numUsers = users.length;
+ for (int i = 0; i < numUsers; i++) {
+ int userId = users[i];
+
+ for (String permission : ps.getPermissions(userId)) {
+ if (!pkg.implicitPermissions.contains(permission)) {
+ if (!ps.hasInstallPermission(permission)) {
+ int flags = ps.getRuntimePermissionState(permission, userId).getFlags();
+
+ if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
+ BasePermission bp = mSettings.getPermissionLocked(permission);
+
+ ps.updatePermissionFlags(bp, userId,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
+ | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_USER_SET,
+ 0);
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds,
+ userId);
+
+ if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
+ | FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
+ == 0) {
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ if (permissionToOpCode(permission) != OP_NONE) {
+ setAppOpMode(permission, pkg, userId, MODE_IGNORED);
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking app-op "
+ + permissionToOp(permission) + " for " + pkgName
+ + " as it is now requested");
+ }
+ }
+ } else {
+ int revokeResult = ps.revokeRuntimePermission(bp, userId);
+ if (revokeResult
+ != PermissionsState.PERMISSION_OPERATION_FAILURE) {
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking runtime permission " + permission
+ + " for " + pkgName
+ + " as it is now requested");
+ }
+ }
+ }
+
+ List<String> fgPerms = mBackgroundPermissions.get(permission);
+ if (fgPerms != null) {
+ int numFgPerms = fgPerms.size();
+ for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
+ String fgPerm = fgPerms.get(fgPermNum);
+
+ int mode = appOpsManager.unsafeCheckOpRaw(
+ permissionToOp(fgPerm),
+ getUid(userId, getAppId(pkg.applicationInfo.uid)),
+ pkgName);
+
+ if (mode == MODE_ALLOWED) {
+ setAppOpMode(fgPerm, pkg, userId, MODE_FOREGROUND);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return updatedUserIds;
+ }
+
+ /**
+ * {@code newPerm} is newly added; Inherit the state from {@code sourcePerms}.
+ *
+ * <p>A single new permission can be split off from several source permissions. In this case
+ * the most leniant state is inherited.
+ *
+ * <p>Warning: This does not handle foreground / background permissions
+ *
+ * @param sourcePerms The permissions to inherit from
+ * @param newPerm The permission to inherit to
+ * @param ps The permission state of the package
+ * @param pkg The package requesting the permissions
+ * @param userId The user the permission belongs to
+ */
+ private void inheritPermissionStateToNewImplicitPermissionLocked(
+ @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
+ @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+ @UserIdInt int userId) {
+ AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+ String pkgName = pkg.packageName;
+
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ if (permissionToOp(newPerm) != null) {
+ int mostLenientSourceMode = MODE_ERRORED;
+
+ // Find most lenient source permission state.
+ int numSourcePerms = sourcePerms.size();
+ for (int i = 0; i < numSourcePerms; i++) {
+ String sourcePerm = sourcePerms.valueAt(i);
+
+ if (ps.hasRuntimePermission(sourcePerm, userId)) {
+ String sourceOp = permissionToOp(sourcePerm);
+
+ if (sourceOp != null) {
+ int mode = appOpsManager.unsafeCheckOpRaw(sourceOp,
+ getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName);
+
+ if (mode == MODE_FOREGROUND) {
+ throw new IllegalArgumentException("split permission" + sourcePerm
+ + " has app-op state " + AppOpsManager.MODE_NAMES[mode]);
+ }
+
+ // Leniency order: allowed > ignored > default
+ if (mode == MODE_ALLOWED) {
+ mostLenientSourceMode = MODE_ALLOWED;
+ break;
+ } else if (mode == MODE_IGNORED) {
+ mostLenientSourceMode = MODE_IGNORED;
+ } else if (mode == MODE_DEFAULT
+ && mostLenientSourceMode != MODE_IGNORED) {
+ mostLenientSourceMode = MODE_DEFAULT;
+ }
+ }
+ }
+ }
+
+ if (mostLenientSourceMode != MODE_ERRORED) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, newPerm + " inherits app-ops state " + mostLenientSourceMode
+ + " from " + sourcePerms + " for " + pkgName);
+ }
+
+ setAppOpMode(newPerm, pkg, userId, mostLenientSourceMode);
+ }
+ }
+ } else {
+ boolean isGranted = false;
+
+ int numSourcePerm = sourcePerms.size();
+ for (int i = 0; i < numSourcePerm; i++) {
+ String sourcePerm = sourcePerms.valueAt(i);
+ if (ps.hasRuntimePermission(sourcePerm, userId)
+ && ps.getRuntimePermissionState(sourcePerm, userId).isGranted()) {
+ isGranted = true;
+ break;
+ }
+ }
+
+ if (isGranted) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms
+ + " for " + pkgName);
+ }
+
+ ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId);
+ }
+ }
+ }
+
+ /**
+ * Set the state of a implicit permission that is seen for the first time.
+ *
+ * @param origPs The permission state of the package before the split
+ * @param ps The new permission state
+ * @param pkg The package the permission belongs to
+ * @param updatedUserIds List of users for which the permission state has already been changed
+ *
+ * @return List of users for which the permission state has been changed
+ */
+ private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
+ @NonNull PermissionsState origPs,
+ @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+ @NonNull int[] updatedUserIds) {
+ AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+
+ String pkgName = pkg.packageName;
+ ArraySet<String> newImplicitPermissions = new ArraySet<>();
+
+ int numRequestedPerms = pkg.requestedPermissions.size();
+ for (int i = 0; i < numRequestedPerms; i++) {
+ BasePermission bp = mSettings.getPermissionLocked(pkg.requestedPermissions.get(i));
+ if (bp != null) {
+ String perm = bp.getName();
+
+ if (!origPs.hasRequestedPermission(perm) && pkg.implicitPermissions.contains(
+ perm)) {
+ newImplicitPermissions.add(perm);
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, perm + " is newly added for " + pkgName);
+ }
+ }
+ }
+ }
+
+ ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
+
+ int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+ for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+ PermissionManager.SplitPermissionInfo spi =
+ PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+
+ List<String> newPerms = spi.getNewPermissions();
+ int numNewPerms = newPerms.size();
+ for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
+ String newPerm = newPerms.get(newPermNum);
+
+ ArraySet<String> splitPerms = newToSplitPerms.get(newPerm);
+ if (splitPerms == null) {
+ splitPerms = new ArraySet<>();
+ newToSplitPerms.put(newPerm, splitPerms);
+ }
+
+ splitPerms.add(spi.getSplitPermission());
+ }
+ }
+
+ int numNewImplicitPerms = newImplicitPermissions.size();
+ for (int newImplicitPermNum = 0; newImplicitPermNum < numNewImplicitPerms;
+ newImplicitPermNum++) {
+ String newPerm = newImplicitPermissions.valueAt(newImplicitPermNum);
+ ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
+
+ if (sourcePerms != null) {
+ if (!ps.hasInstallPermission(newPerm)) {
+ BasePermission bp = mSettings.getPermissionLocked(newPerm);
+
+ int[] users = UserManagerService.getInstance().getUserIds();
+ int numUsers = users.length;
+ for (int userNum = 0; userNum < numUsers; userNum++) {
+ int userId = users[userNum];
+
+ ps.updatePermissionFlags(bp, userId,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+
+ // SPECIAL BEHAVIOR for background location. Foreground only by default.
+ if (newPerm.equals(ACCESS_BACKGROUND_LOCATION)) {
+ int numSourcePerms = sourcePerms.size();
+ for (int sourcePermNum = 0; sourcePermNum < numSourcePerms;
+ sourcePermNum++) {
+ String sourcePerm = sourcePerms.valueAt(sourcePermNum);
+
+ if (appOpsManager.unsafeCheckOpNoThrow(permissionToOp(sourcePerm),
+ getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName)
+ == MODE_ALLOWED) {
+ setAppOpMode(sourcePerm, pkg, userId, MODE_FOREGROUND);
+ }
+ }
+ } else {
+ if (!origPs.hasRequestedPermission(sourcePerms)) {
+ // Both permissions are new, do nothing
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
+ + " for " + pkgName
+ + " as split permission is also new");
+ }
+
+ break;
+ } else {
+ inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms,
+ newPerm, ps, pkg, userId);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return updatedUserIds;
+ }
+
private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
boolean allowed = false;
final int NP = PackageParser.NEW_PERMISSIONS.length;
@@ -1571,10 +1876,9 @@
}
}
-
- private void revokeRuntimePermission(String permName, String packageName, BasePermission bp,
- boolean overridePolicy, int callingUid, int userId, PermissionCallback callback,
- boolean permissionRemoved) {
+
+ private void revokeRuntimePermission(String permName, String packageName,
+ boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
if (!mUserManagerInt.exists(userId)) {
Log.e(TAG, "No such user:" + userId);
return;
@@ -1599,7 +1903,7 @@
if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
-
+ final BasePermission bp = mSettings.getPermissionLocked(permName);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
@@ -1812,7 +2116,30 @@
// and make sure there are no dangling permissions.
flags = updatePermissions(changingPkgName, changingPkg, flags);
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
+ synchronized (mLock) {
+ if (mBackgroundPermissions == null) {
+ // Cache background -> foreground permission mapping.
+ // Only system declares background permissions, hence mapping does never change.
+ mBackgroundPermissions = new ArrayMap<>();
+ for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
+ if (bp.perm != null && bp.perm.info != null
+ && bp.perm.info.backgroundPermission != null) {
+ String fgPerm = bp.name;
+ String bgPerm = bp.perm.info.backgroundPermission;
+
+ List<String> fgPerms = mBackgroundPermissions.get(bgPerm);
+ if (fgPerms == null) {
+ fgPerms = new ArrayList<>();
+ mBackgroundPermissions.put(bgPerm, fgPerms);
+ }
+
+ fgPerms.add(fgPerm);
+ }
+ }
+ }
+ }
+
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
// Now update the permissions for all packages, in particular
// replace the granted permissions of the system packages.
if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
@@ -1822,7 +2149,7 @@
final String volumeUuid = getVolumeUuidForPackage(pkg);
final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
&& Objects.equals(replaceVolumeUuid, volumeUuid);
- grantPermissions(pkg, replace, changingPkgName, callback);
+ restorePermissionState(pkg, replace, changingPkgName, callback);
}
}
}
@@ -1832,7 +2159,7 @@
final String volumeUuid = getVolumeUuidForPackage(changingPkg);
final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
&& Objects.equals(replaceVolumeUuid, volumeUuid);
- grantPermissions(changingPkg, replace, changingPkgName, callback);
+ restorePermissionState(changingPkg, replace, changingPkgName, callback);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -2129,6 +2456,17 @@
mMetricsLogger.write(log);
}
+ /**
+ * Get the mapping of background permissions to their foreground permissions.
+ *
+ * <p>Only initialized in the system server.
+ *
+ * @return the map <bg permission -> list<fg perm>>
+ */
+ public @Nullable ArrayMap<String, List<String>> getBackgroundPermissions() {
+ return mBackgroundPermissions;
+ }
+
private class PermissionManagerInternalImpl extends PermissionManagerInternal {
@Override
public void systemReady() {
@@ -2156,10 +2494,8 @@
PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
}
@Override
- public void removeAllPermissions(Package pkg, List<String> allPackageNames,
- PermissionCallback permissionCallback, boolean chatty) {
- PermissionManagerService.this.removeAllPermissions(
- pkg, allPackageNames, permissionCallback, chatty);
+ public void removeAllPermissions(Package pkg, boolean chatty) {
+ PermissionManagerService.this.removeAllPermissions(pkg, chatty);
}
@Override
public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
@@ -2195,8 +2531,7 @@
boolean overridePolicy, int callingUid, int userId,
PermissionCallback callback) {
PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
- mSettings.getPermission(permName), overridePolicy, callingUid, userId,
- callback, false);
+ overridePolicy, callingUid, userId, callback);
}
@Override
public void updatePermissions(String packageName, Package pkg, boolean replaceGrant,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1dae396..97af045 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -41,6 +41,7 @@
import static android.os.Build.VERSION_CODES.O;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.STATE_OFF;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
@@ -155,6 +156,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.AppOpsManager;
@@ -665,9 +667,6 @@
SleepToken mDreamingSleepToken;
SleepToken mScreenOffSleepToken;
volatile boolean mKeyguardOccluded;
- boolean mHomePressed;
- boolean mHomeConsumed;
- boolean mHomeDoubleTapPending;
Intent mHomeIntent;
Intent mCarDockIntent;
Intent mDeskDockIntent;
@@ -865,7 +864,7 @@
launchVoiceAssistWithWakeLock();
break;
case MSG_POWER_DELAYED_PRESS:
- powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
+ powerPress((Long) msg.obj, msg.arg1 != 0, msg.arg2);
finishPowerKeyPress();
break;
case MSG_POWER_LONG_PRESS:
@@ -1340,7 +1339,7 @@
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- launchHomeFromHotKey();
+ launchHomeFromHotKey(DEFAULT_DISPLAY);
break;
case SHORT_PRESS_POWER_GO_HOME:
shortPressPowerGoHome();
@@ -1369,7 +1368,8 @@
}
private void shortPressPowerGoHome() {
- launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+ launchHomeFromHotKey(DEFAULT_DISPLAY, true /* awakenFromDreams */,
+ false /*respectKeyguard*/);
if (isKeyguardShowingAndNotOccluded()) {
// Notify keyguard so it can do any special handling for the power button since the
// device will not power off and only launch home.
@@ -1505,7 +1505,8 @@
private void sleepPress() {
if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
- launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
+ launchHomeFromHotKey(DEFAULT_DISPLAY, false /* awakenDreams */,
+ true /*respectKeyguard*/);
}
}
@@ -1683,7 +1684,7 @@
Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
}
- private void handleShortPressOnHome() {
+ private void handleShortPressOnHome(int displayId) {
// Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
final HdmiControl hdmiControl = getHdmiControl();
if (hdmiControl != null) {
@@ -1698,7 +1699,7 @@
}
// Go home!
- launchHomeFromHotKey();
+ launchHomeFromHotKey(displayId);
}
/**
@@ -1745,26 +1746,6 @@
}
}
- private void handleLongPressOnHome(int deviceId) {
- if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
- return;
- }
- mHomeConsumed = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
- "Home - Long Press");
- switch (mLongPressOnHomeBehavior) {
- case LONG_PRESS_HOME_ALL_APPS:
- launchAllAppsAction();
- break;
- case LONG_PRESS_HOME_ASSIST:
- launchAssistAction(null, deviceId);
- break;
- default:
- Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
- break;
- }
- }
-
private void launchAllAppsAction() {
Intent intent = new Intent(Intent.ACTION_ALL_APPS);
if (mHasFeatureLeanback) {
@@ -1781,13 +1762,6 @@
startActivityAsUser(intent, UserHandle.CURRENT);
}
- private void handleDoubleTapOnHome() {
- if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
- mHomeConsumed = true;
- toggleRecentApps();
- }
- }
-
private void showPictureInPictureMenu(KeyEvent event) {
if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
@@ -1803,15 +1777,147 @@
}
}
- private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
- @Override
- public void run() {
- if (mHomeDoubleTapPending) {
- mHomeDoubleTapPending = false;
- handleShortPressOnHome();
+ /** A handler to handle home keys per display */
+ private class DisplayHomeButtonHandler {
+
+ private final int mDisplayId;
+
+ private boolean mHomeDoubleTapPending;
+ private boolean mHomePressed;
+ private boolean mHomeConsumed;
+
+ private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mHomeDoubleTapPending) {
+ mHomeDoubleTapPending = false;
+ handleShortPressOnHome(mDisplayId);
+ }
+ }
+ };
+
+ DisplayHomeButtonHandler(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ int handleHomeButton(WindowState win, KeyEvent event) {
+ final boolean keyguardOn = keyguardOn();
+ final int repeatCount = event.getRepeatCount();
+ final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
+ final boolean canceled = event.isCanceled();
+
+ if (DEBUG_INPUT) {
+ Log.d(TAG, String.format("handleHomeButton in display#%d mHomePressed = %b",
+ mDisplayId, mHomePressed));
+ }
+
+ // If we have released the home key, and didn't do anything else
+ // while it was pressed, then it is time to go home!
+ if (!down) {
+ if (mDisplayId == DEFAULT_DISPLAY) {
+ cancelPreloadRecentApps();
+ }
+
+ mHomePressed = false;
+ if (mHomeConsumed) {
+ mHomeConsumed = false;
+ return -1;
+ }
+
+ if (canceled) {
+ Log.i(TAG, "Ignoring HOME; event canceled.");
+ return -1;
+ }
+
+ // Delay handling home if a double-tap is possible.
+ if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
+ mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
+ mHomeDoubleTapPending = true;
+ mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
+ ViewConfiguration.getDoubleTapTimeout());
+ return -1;
+ }
+
+ handleShortPressOnHome(mDisplayId);
+ return -1;
+ }
+
+ // If a system window has focus, then it doesn't make sense
+ // right now to interact with applications.
+ WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
+ if (attrs != null) {
+ final int type = attrs.type;
+ if (type == TYPE_KEYGUARD_DIALOG
+ || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ // the "app" is keyguard, so give it the key
+ return 0;
+ }
+ for (int t : WINDOW_TYPES_WHERE_HOME_DOESNT_WORK) {
+ if (type == t) {
+ // don't do anything, but also don't pass it to the app
+ return -1;
+ }
+ }
+ }
+
+ // Remember that home is pressed and handle special actions.
+ if (repeatCount == 0) {
+ mHomePressed = true;
+ if (mHomeDoubleTapPending) {
+ mHomeDoubleTapPending = false;
+ mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
+ handleDoubleTapOnHome();
+ // TODO(multi-display): Remove display id check once we support recents on
+ // multi-display
+ } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI
+ && mDisplayId == DEFAULT_DISPLAY) {
+ preloadRecentApps();
+ }
+ } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+ if (!keyguardOn) {
+ handleLongPressOnHome(event.getDeviceId());
+ }
+ }
+ return -1;
+ }
+
+ private void handleDoubleTapOnHome() {
+ if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
+ mHomeConsumed = true;
+ toggleRecentApps();
}
}
- };
+
+ private void handleLongPressOnHome(int deviceId) {
+ if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
+ return;
+ }
+ mHomeConsumed = true;
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ "Home - Long Press");
+ switch (mLongPressOnHomeBehavior) {
+ case LONG_PRESS_HOME_ALL_APPS:
+ launchAllAppsAction();
+ break;
+ case LONG_PRESS_HOME_ASSIST:
+ launchAssistAction(null, deviceId);
+ break;
+ default:
+ Log.w(TAG, "Undefined home long press behavior: "
+ + mLongPressOnHomeBehavior);
+ break;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("mDisplayId = %d, mHomePressed = %b", mDisplayId, mHomePressed);
+ }
+ }
+
+ /** A DisplayHomeButtonHandler map indexed by display id */
+ private final SparseArray<DisplayHomeButtonHandler> mDisplayHomeButtonHandlers =
+ new SparseArray<>();
private boolean isRoundWindow() {
return mContext.getResources().getConfiguration().isScreenRound();
@@ -3259,6 +3365,7 @@
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
};
+ // TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
@@ -3269,11 +3376,11 @@
final int flags = event.getFlags();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
+ final int displayId = event.getDisplayId();
if (DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
- + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
- + " canceled=" + canceled);
+ + repeatCount + " keyguardOn=" + keyguardOn + " canceled=" + canceled);
}
// If we think we might have a volume down & power key chord on the way
@@ -3358,71 +3465,12 @@
// it handle it, because that gives us the correct 5 second
// timeout.
if (keyCode == KeyEvent.KEYCODE_HOME) {
-
- // If we have released the home key, and didn't do anything else
- // while it was pressed, then it is time to go home!
- if (!down) {
- cancelPreloadRecentApps();
-
- mHomePressed = false;
- if (mHomeConsumed) {
- mHomeConsumed = false;
- return -1;
- }
-
- if (canceled) {
- Log.i(TAG, "Ignoring HOME; event canceled.");
- return -1;
- }
-
- // Delay handling home if a double-tap is possible.
- if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
- mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
- mHomeDoubleTapPending = true;
- mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
- ViewConfiguration.getDoubleTapTimeout());
- return -1;
- }
-
- handleShortPressOnHome();
- return -1;
+ DisplayHomeButtonHandler handler = mDisplayHomeButtonHandlers.get(displayId);
+ if (handler == null) {
+ handler = new DisplayHomeButtonHandler(displayId);
+ mDisplayHomeButtonHandlers.put(displayId, handler);
}
-
- // If a system window has focus, then it doesn't make sense
- // right now to interact with applications.
- WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
- if (attrs != null) {
- final int type = attrs.type;
- if (type == TYPE_KEYGUARD_DIALOG
- || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- // the "app" is keyguard, so give it the key
- return 0;
- }
- final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
- for (int i=0; i<typeCount; i++) {
- if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
- // don't do anything, but also don't pass it to the app
- return -1;
- }
- }
- }
-
- // Remember that home is pressed and handle special actions.
- if (repeatCount == 0) {
- mHomePressed = true;
- if (mHomeDoubleTapPending) {
- mHomeDoubleTapPending = false;
- mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
- handleDoubleTapOnHome();
- } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
- preloadRecentApps();
- }
- } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
- if (!keyguardOn) {
- handleLongPressOnHome(event.getDeviceId());
- }
- }
- return -1;
+ return handler.handleHomeButton(win, event);
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
// Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON;
@@ -3820,6 +3868,7 @@
}
}
+ // TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
@@ -3862,7 +3911,7 @@
event.getAction(), fallbackAction.keyCode,
event.getRepeatCount(), fallbackAction.metaState,
event.getDeviceId(), event.getScanCode(),
- flags, event.getSource(), null);
+ flags, event.getSource(), event.getDisplayId(), null);
if (!interceptFallback(win, fallbackEvent, policyFlags)) {
fallbackEvent.recycle();
@@ -3991,8 +4040,12 @@
}
private void startActivityAsUser(Intent intent, UserHandle handle) {
+ startActivityAsUser(intent, null, handle);
+ }
+
+ private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle) {
if (isUserSetupComplete()) {
- mContext.startActivityAsUser(intent, handle);
+ mContext.startActivityAsUser(intent, bundle, handle);
} else {
Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
}
@@ -4067,15 +4120,16 @@
}
}
- void launchHomeFromHotKey() {
- launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
+ void launchHomeFromHotKey(int displayId) {
+ launchHomeFromHotKey(displayId, true /* awakenFromDreams */, true /*respectKeyguard*/);
}
/**
* A home key -> launch home action was detected. Take the appropriate action
* given the situation with the keyguard.
*/
- void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
+ void launchHomeFromHotKey(int displayId, final boolean awakenFromDreams,
+ final boolean respectKeyguard) {
// Abort possibly stuck animations.
mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
@@ -4092,7 +4146,7 @@
@Override
public void onKeyguardExitResult(boolean success) {
if (success) {
- startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
+ startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams);
}
}
});
@@ -4113,7 +4167,7 @@
hideRecentApps(false, true);
} else {
// Otherwise, just launch Home
- startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
+ startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams);
}
}
@@ -5677,7 +5731,7 @@
mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
}
-
+ // TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
@@ -5690,6 +5744,7 @@
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
+ final int displayId = event.getDisplayId();
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
@@ -6193,7 +6248,7 @@
return true;
}
-
+ // TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
@@ -7269,7 +7324,7 @@
return null;
}
- void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
+ void startDockOrHome(int displayId, boolean fromHomeKey, boolean awakenFromDreams) {
try {
ActivityManager.getService().stopAppSwitches();
} catch (RemoteException e) {}
@@ -7299,8 +7354,13 @@
} else {
intent = mHomeIntent;
}
+ final Bundle bundle = getLaunchDisplayIdBundle(displayId);
+ startActivityAsUser(intent, bundle, UserHandle.CURRENT);
+ }
- startActivityAsUser(intent, UserHandle.CURRENT);
+ private @Nullable Bundle getLaunchDisplayIdBundle(int displayId) {
+ return (displayId == INVALID_DISPLAY) ? null
+ : ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
}
/**
@@ -7314,7 +7374,7 @@
}
if (false) {
// This code always brings home to the front.
- startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
+ startDockOrHome(DEFAULT_DISPLAY, false /*fromHomeKey*/, true /* awakenFromDreams */);
} else {
// This code brings home to the front or, if it is already
// at the front, puts the device to sleep.
@@ -7325,7 +7385,7 @@
} else {
ActivityManager.getService().stopAppSwitches();
sendCloseSystemWindows();
- Intent dock = createHomeDockIntent();
+ final Intent dock = createHomeDockIntent();
if (dock != null) {
int result = ActivityTaskManager.getService()
.startActivityAsUser(null, null, dock,
@@ -8013,7 +8073,13 @@
pw.print(incallBackBehaviorToString(mIncallBackBehavior));
pw.print(" mEndcallBehavior=");
pw.println(endcallBehaviorToString(mEndcallBehavior));
- pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
+ pw.print(prefix);
+ // TODO(b/117479243): handle it in InputPolicy
+ pw.print("mDisplayHomeButtonHandlers=");
+ for (int i = 0; i < mDisplayHomeButtonHandlers.size(); i++) {
+ final int key = mDisplayHomeButtonHandlers.keyAt(i);
+ pw.println(mDisplayHomeButtonHandlers.get(key));
+ }
pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 1e0b52a..ae1090c 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,13 +1,11 @@
package com.android.server.policy.keyguard;
-import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.wm.KeyguardServiceDelegateProto.INTERACTIVE_STATE;
import static com.android.server.wm.KeyguardServiceDelegateProto.OCCLUDED;
import static com.android.server.wm.KeyguardServiceDelegateProto.SCREEN_STATE;
import static com.android.server.wm.KeyguardServiceDelegateProto.SECURE;
import static com.android.server.wm.KeyguardServiceDelegateProto.SHOWING;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
@@ -212,10 +210,10 @@
mHandler.post(() -> {
try {
// There are no longer any keyguard windows on secondary displays, so pass
- // INVALID_DISPLAY. All that means is that showWhenLocked activities on
- // secondary displays now get to show.
+ // {@code null}. All that means is that showWhenLocked activities on
+ // external displays now get to show.
ActivityTaskManager.getService().setLockScreenShown(true /* keyguardShowing */,
- false /* aodShowing */, INVALID_DISPLAY);
+ false /* aodShowing */, null /* secondaryDisplaysShowing */);
} catch (RemoteException e) {
// Local call.
}
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 4f8e6b6..6d7b04c 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -57,16 +57,32 @@
public static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
- // Secure setting for GPS behavior when battery saver mode is on.
- public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
-
private static final String KEY_GPS_MODE = "gps_mode";
private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
- private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
+
+ /**
+ * Disable turning on the network firewall when Battery Saver is turned on.
+ * If set to false, the firewall WILL be turned on when Battery Saver is turned on.
+ * If set to true, the firewall WILL NOT be turned on when Battery Saver is turned on.
+ */
+ private static final String KEY_ACTIVATE_FIREWALL_DISABLED = "firewall_disabled";
+
+ /**
+ * Disable turning on the special low power screen brightness dimming when Battery Saver is
+ * turned on.
+ * If set to false, the screen brightness dimming WILL be turned on by Battery Saver.
+ * If set to true, the screen brightness WILL NOT be turned on by Battery Saver.
+ */
private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
- private static final String KEY_DATASAVER_DISABLED = "datasaver_disabled";
+
+ /**
+ * Disable turning on Data Saver when Battery Saver is turned on.
+ * If set to false, Data Saver WILL be turned on when Battery Saver is turned on.
+ * If set to true, Data Saver WILL NOT be turned on when Battery Saver is turned on.
+ */
+ private static final String KEY_ACTIVATE_DATASAVER_DISABLED = "datasaver_disabled";
private static final String KEY_LAUNCH_BOOST_DISABLED = "launch_boost_disabled";
private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
@@ -82,6 +98,28 @@
private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n";
+ private static final Policy sDefaultPolicy = new Policy(
+ 0.5f, /* adjustBrightnessFactor */
+ true, /* deferFullBackup */
+ true, /* deferKeyValueBackup */
+ false, /* disableAnimation */
+ true, /* disableAod */
+ true, /* disableLaunchBoost */
+ true, /* disableOptionalSensors */
+ true, /* disableSoundTrigger */
+ true, /* disableVibration */
+ false, /* enableAdjustBrightness */
+ false, /* enableDataSaver */
+ true, /* enableFirewall */
+ false, /* enableQuickDoze */
+ new ArrayMap<>(), /* filesForInteractive */
+ new ArrayMap<>(), /* filesForNoninteractive */
+ true, /* forceAllAppsStandby */
+ true, /* forceBackgroundCheck */
+ PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF, /* gpsMode */
+ false /* sendTronLog */
+ );
+
private final Object mLock;
private final Handler mHandler;
@@ -101,145 +139,20 @@
private String mEventLogKeys;
/**
- * {@code true} if vibration is disabled in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_VIBRATION_DISABLED
- */
- @GuardedBy("mLock")
- private boolean mVibrationDisabledConfig;
-
- /**
- * Whether vibration should *really* be disabled -- i.e. {@link #mVibrationDisabledConfig}
+ * Whether vibration should *really* be disabled -- i.e. {@link Policy#disableVibration}
* is true *and* {@link #mAccessibilityEnabled} is false.
*/
@GuardedBy("mLock")
- private boolean mVibrationDisabledEffective;
+ private boolean mDisableVibrationEffective;
/**
- * {@code true} if animation is disabled in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_ANIMATION_DISABLED
+ * Whether accessibility is currently enabled or not.
*/
@GuardedBy("mLock")
- private boolean mAnimationDisabled;
+ private boolean mAccessibilityEnabled;
- /**
- * {@code true} if sound trigger is disabled in battery saver mode
- * in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_SOUNDTRIGGER_DISABLED
- */
@GuardedBy("mLock")
- private boolean mSoundTriggerDisabled;
-
- /**
- * {@code true} if full backup is deferred in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_FULLBACKUP_DEFERRED
- */
- @GuardedBy("mLock")
- private boolean mFullBackupDeferred;
-
- /**
- * {@code true} if key value backup is deferred in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_KEYVALUE_DEFERRED
- */
- @GuardedBy("mLock")
- private boolean mKeyValueBackupDeferred;
-
- /**
- * {@code true} if network policy firewall is disabled in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_FIREWALL_DISABLED
- */
- @GuardedBy("mLock")
- private boolean mFireWallDisabled;
-
- /**
- * {@code true} if adjust brightness is disabled in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
- */
- @GuardedBy("mLock")
- private boolean mAdjustBrightnessDisabled;
-
- /**
- * {@code true} if data saver is disabled in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_DATASAVER_DISABLED
- */
- @GuardedBy("mLock")
- private boolean mDataSaverDisabled;
-
- /**
- * {@code true} if launch boost should be disabled on battery saver.
- */
- @GuardedBy("mLock")
- private boolean mLaunchBoostDisabled;
-
- /**
- * This is the flag to decide the gps mode in battery saver mode.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_GPS_MODE
- */
- @GuardedBy("mLock")
- private int mGpsMode;
-
- /**
- * This is the flag to decide the how much to adjust the screen brightness. This is
- * the float value from 0 to 1 where 1 means don't change brightness.
- *
- * @see Settings.Global#BATTERY_SAVER_CONSTANTS
- * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
- */
- @GuardedBy("mLock")
- private float mAdjustBrightnessFactor;
-
- /**
- * Whether to put all apps in the stand-by mode.
- */
- @GuardedBy("mLock")
- private boolean mForceAllAppsStandby;
-
- /**
- * Whether to put all apps in the stand-by mode.
- */
- @GuardedBy("mLock")
- private boolean mForceBackgroundCheck;
-
- /**
- * Whether to show non-essential sensors (e.g. edge sensors) or not.
- */
- @GuardedBy("mLock")
- private boolean mOptionalSensorsDisabled;
-
- /**
- * Whether AOD is enabled or not.
- */
- @GuardedBy("mLock")
- private boolean mAodDisabled;
-
- /**
- * Whether Quick Doze is enabled or not.
- */
- @GuardedBy("mLock")
- private boolean mQuickDozeEnabled;
-
- /**
- * Whether BatterySavingStats should send tron events.
- */
- @GuardedBy("mLock")
- private boolean mSendTronLog;
+ private Policy mCurrPolicy = sDefaultPolicy;
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -248,30 +161,6 @@
@GuardedBy("mLock")
private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>();
- /**
- * List of [Filename -> content] that should be written when battery saver is activated
- * and the device is interactive.
- *
- * We use this to change the max CPU frequencies.
- */
- @GuardedBy("mLock")
- private ArrayMap<String, String> mFilesForInteractive;
-
- /**
- * List of [Filename -> content] that should be written when battery saver is activated
- * and the device is non-interactive.
- *
- * We use this to change the max CPU frequencies.
- */
- @GuardedBy("mLock")
- private ArrayMap<String, String> mFilesForNoninteractive;
-
- /**
- * Whether accessibility is enabled or not.
- */
- @GuardedBy("mLock")
- private boolean mAccessibilityEnabled;
-
public interface BatterySaverPolicyListener {
void onBatterySaverPolicyChanged(BatterySaverPolicy policy);
}
@@ -379,36 +268,7 @@
final KeyValueListParser parser = new KeyValueListParser(',');
- // Non-device-specific parameters.
- try {
- parser.setString(setting);
- } catch (IllegalArgumentException e) {
- Slog.wtf(TAG, "Bad battery saver constants: " + setting);
- }
-
- mVibrationDisabledConfig = parser.getBoolean(KEY_VIBRATION_DISABLED, true);
- mAnimationDisabled = parser.getBoolean(KEY_ANIMATION_DISABLED, false);
- mSoundTriggerDisabled = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true);
- mFullBackupDeferred = parser.getBoolean(KEY_FULLBACKUP_DEFERRED, true);
- mKeyValueBackupDeferred = parser.getBoolean(KEY_KEYVALUE_DEFERRED, true);
- mFireWallDisabled = parser.getBoolean(KEY_FIREWALL_DISABLED, false);
- mAdjustBrightnessDisabled = parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, true);
- mAdjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
- mDataSaverDisabled = parser.getBoolean(KEY_DATASAVER_DISABLED, true);
- mLaunchBoostDisabled = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED, true);
- mForceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, true);
- mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true);
- mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true);
- mAodDisabled = parser.getBoolean(KEY_AOD_DISABLED, true);
- mQuickDozeEnabled = parser.getBoolean(KEY_QUICK_DOZE_ENABLED, false);
- mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, false);
-
- // Get default value from Settings.Secure
- final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
- PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
- mGpsMode = parser.getInt(KEY_GPS_MODE, defaultGpsMode);
-
- // Non-device-specific parameters.
+ // Device-specific parameters.
try {
parser.setString(deviceSpecificSetting);
} catch (IllegalArgumentException e) {
@@ -416,41 +276,280 @@
+ deviceSpecificSetting);
}
- mFilesForInteractive = (new CpuFrequencies()).parseString(
- parser.getString(KEY_CPU_FREQ_INTERACTIVE, "")).toSysFileMap();
+ final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, "");
+ final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "");
- mFilesForNoninteractive = (new CpuFrequencies()).parseString(
- parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "")).toSysFileMap();
+ // Non-device-specific parameters.
+ try {
+ parser.setString(setting);
+ } catch (IllegalArgumentException e) {
+ Slog.wtf(TAG, "Bad battery saver constants: " + setting);
+ }
+
+ float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
+ sDefaultPolicy.adjustBrightnessFactor);
+ boolean deferFullBackup = parser.getBoolean(KEY_FULLBACKUP_DEFERRED,
+ sDefaultPolicy.deferFullBackup);
+ boolean deferKeyValueBackup = parser.getBoolean(KEY_KEYVALUE_DEFERRED,
+ sDefaultPolicy.deferKeyValueBackup);
+ boolean disableAnimation = parser.getBoolean(KEY_ANIMATION_DISABLED,
+ sDefaultPolicy.disableAnimation);
+ boolean disableAod = parser.getBoolean(KEY_AOD_DISABLED, sDefaultPolicy.disableAod);
+ boolean disableLaunchBoost = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED,
+ sDefaultPolicy.disableLaunchBoost);
+ boolean disableOptionalSensors = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED,
+ sDefaultPolicy.disableOptionalSensors);
+ boolean disableSoundTrigger = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED,
+ sDefaultPolicy.disableSoundTrigger);
+ boolean disableVibrationConfig = parser.getBoolean(KEY_VIBRATION_DISABLED,
+ sDefaultPolicy.disableVibration);
+ boolean enableAdjustBrightness = !parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED,
+ !sDefaultPolicy.enableAdjustBrightness);
+ boolean enableDataSaver = !parser.getBoolean(KEY_ACTIVATE_DATASAVER_DISABLED,
+ !sDefaultPolicy.enableDataSaver);
+ boolean enableFirewall = !parser.getBoolean(KEY_ACTIVATE_FIREWALL_DISABLED,
+ !sDefaultPolicy.enableFirewall);
+ boolean enableQuickDoze = parser.getBoolean(KEY_QUICK_DOZE_ENABLED,
+ sDefaultPolicy.enableQuickDoze);
+ boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
+ sDefaultPolicy.forceAllAppsStandby);
+ boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
+ sDefaultPolicy.forceBackgroundCheck);
+ int gpsMode = parser.getInt(KEY_GPS_MODE, sDefaultPolicy.gpsMode);
+ boolean sendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, sDefaultPolicy.sendTronLog);
+
+ mCurrPolicy = new Policy(
+ adjustBrightnessFactor,
+ deferFullBackup,
+ deferKeyValueBackup,
+ disableAnimation,
+ disableAod,
+ disableLaunchBoost,
+ disableOptionalSensors,
+ disableSoundTrigger,
+ /* disableVibration */
+ disableVibrationConfig,
+ enableAdjustBrightness,
+ enableDataSaver,
+ enableFirewall,
+ enableQuickDoze,
+ /* filesForInteractive */
+ (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
+ /* filesForNoninteractive */
+ (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
+ forceAllAppsStandby,
+ forceBackgroundCheck,
+ gpsMode,
+ sendTronLog
+ );
// Update the effective policy.
- mVibrationDisabledEffective = mVibrationDisabledConfig
+ mDisableVibrationEffective = mCurrPolicy.disableVibration
&& !mAccessibilityEnabled; // Don't disable vibration when accessibility is on.
final StringBuilder sb = new StringBuilder();
- if (mForceAllAppsStandby) sb.append("A");
- if (mForceBackgroundCheck) sb.append("B");
+ if (mCurrPolicy.forceAllAppsStandby) sb.append("A");
+ if (mCurrPolicy.forceBackgroundCheck) sb.append("B");
- if (mVibrationDisabledEffective) sb.append("v");
- if (mAnimationDisabled) sb.append("a");
- if (mSoundTriggerDisabled) sb.append("s");
- if (mFullBackupDeferred) sb.append("F");
- if (mKeyValueBackupDeferred) sb.append("K");
- if (!mFireWallDisabled) sb.append("f");
- if (!mDataSaverDisabled) sb.append("d");
- if (!mAdjustBrightnessDisabled) sb.append("b");
+ if (mDisableVibrationEffective) sb.append("v");
+ if (mCurrPolicy.disableAnimation) sb.append("a");
+ if (mCurrPolicy.disableSoundTrigger) sb.append("s");
+ if (mCurrPolicy.deferFullBackup) sb.append("F");
+ if (mCurrPolicy.deferKeyValueBackup) sb.append("K");
+ if (mCurrPolicy.enableFirewall) sb.append("f");
+ if (mCurrPolicy.enableDataSaver) sb.append("d");
+ if (mCurrPolicy.enableAdjustBrightness) sb.append("b");
- if (mLaunchBoostDisabled) sb.append("l");
- if (mOptionalSensorsDisabled) sb.append("S");
- if (mAodDisabled) sb.append("o");
- if (mQuickDozeEnabled) sb.append("q");
- if (mSendTronLog) sb.append("t");
+ if (mCurrPolicy.disableLaunchBoost) sb.append("l");
+ if (mCurrPolicy.disableOptionalSensors) sb.append("S");
+ if (mCurrPolicy.disableAod) sb.append("o");
+ if (mCurrPolicy.enableQuickDoze) sb.append("q");
+ if (mCurrPolicy.sendTronLog) sb.append("t");
- sb.append(mGpsMode);
+ sb.append(mCurrPolicy.gpsMode);
mEventLogKeys = sb.toString();
- mBatterySavingStats.setSendTronLog(mSendTronLog);
+ mBatterySavingStats.setSendTronLog(mCurrPolicy.sendTronLog);
+ }
+
+ private static class Policy {
+ /**
+ * This is the flag to decide the how much to adjust the screen brightness. This is
+ * the float value from 0 to 1 where 1 means don't change brightness.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
+ */
+ public final float adjustBrightnessFactor;
+
+ /**
+ * {@code true} if full backup is deferred in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_FULLBACKUP_DEFERRED
+ */
+ public final boolean deferFullBackup;
+
+ /**
+ * {@code true} if key value backup is deferred in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_KEYVALUE_DEFERRED
+ */
+ public final boolean deferKeyValueBackup;
+
+ /**
+ * {@code true} if animation is disabled in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ANIMATION_DISABLED
+ */
+ public final boolean disableAnimation;
+
+ /**
+ * {@code true} if AOD is disabled in battery saver mode.
+ */
+ public final boolean disableAod;
+
+ /**
+ * {@code true} if launch boost should be disabled on battery saver.
+ */
+ public final boolean disableLaunchBoost;
+
+ /**
+ * Whether to show non-essential sensors (e.g. edge sensors) or not.
+ */
+ public final boolean disableOptionalSensors;
+
+ /**
+ * {@code true} if sound trigger is disabled in battery saver mode
+ * in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_SOUNDTRIGGER_DISABLED
+ */
+ public final boolean disableSoundTrigger;
+
+ /**
+ * {@code true} if vibration is disabled in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_VIBRATION_DISABLED
+ */
+ public final boolean disableVibration;
+
+ /**
+ * {@code true} if low power mode brightness adjustment should be turned on in battery saver
+ * mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
+ */
+ public final boolean enableAdjustBrightness;
+
+ /**
+ * {@code true} if data saver should be turned on in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ACTIVATE_DATASAVER_DISABLED
+ */
+ public final boolean enableDataSaver;
+
+ /**
+ * {@code true} if network policy firewall should be turned on in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ACTIVATE_FIREWALL_DISABLED
+ */
+ public final boolean enableFirewall;
+
+ /**
+ * Whether Quick Doze is enabled or not.
+ */
+ public final boolean enableQuickDoze;
+
+ /**
+ * List of [Filename -> content] that should be written when battery saver is activated
+ * and the device is interactive.
+ *
+ * We use this to change the max CPU frequencies.
+ */
+ public final ArrayMap<String, String> filesForInteractive;
+
+ /**
+ * List of [Filename -> content] that should be written when battery saver is activated
+ * and the device is non-interactive.
+ *
+ * We use this to change the max CPU frequencies.
+ */
+ public final ArrayMap<String, String> filesForNoninteractive;
+
+ /**
+ * Whether to put all apps in the stand-by mode.
+ */
+ public final boolean forceAllAppsStandby;
+
+ /**
+ * Whether to put all apps in the stand-by mode.
+ */
+ public final boolean forceBackgroundCheck;
+
+ /**
+ * This is the flag to decide the gps mode in battery saver mode.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_GPS_MODE
+ */
+ public final int gpsMode;
+
+ /**
+ * Whether BatterySavingStats should send tron events.
+ */
+ public final boolean sendTronLog;
+
+ Policy(
+ float adjustBrightnessFactor,
+ boolean deferFullBackup,
+ boolean deferKeyValueBackup,
+ boolean disableAnimation,
+ boolean disableAod,
+ boolean disableLaunchBoost,
+ boolean disableOptionalSensors,
+ boolean disableSoundTrigger,
+ boolean disableVibration,
+ boolean enableAdjustBrightness,
+ boolean enableDataSaver,
+ boolean enableFirewall,
+ boolean enableQuickDoze,
+ ArrayMap<String, String> filesForInteractive,
+ ArrayMap<String, String> filesForNoninteractive,
+ boolean forceAllAppsStandby,
+ boolean forceBackgroundCheck,
+ int gpsMode,
+ boolean sendTronLog) {
+
+ this.adjustBrightnessFactor = adjustBrightnessFactor;
+ this.deferFullBackup = deferFullBackup;
+ this.deferKeyValueBackup = deferKeyValueBackup;
+ this.disableAnimation = disableAnimation;
+ this.disableAod = disableAod;
+ this.disableLaunchBoost = disableLaunchBoost;
+ this.disableOptionalSensors = disableOptionalSensors;
+ this.disableSoundTrigger = disableSoundTrigger;
+ this.disableVibration = disableVibration;
+ this.enableAdjustBrightness = enableAdjustBrightness;
+ this.enableDataSaver = enableDataSaver;
+ this.enableFirewall = enableFirewall;
+ this.enableQuickDoze = enableQuickDoze;
+ this.filesForInteractive = filesForInteractive;
+ this.filesForNoninteractive = filesForNoninteractive;
+ this.forceAllAppsStandby = forceAllAppsStandby;
+ this.forceBackgroundCheck = forceBackgroundCheck;
+ this.gpsMode = gpsMode;
+ this.sendTronLog = sendTronLog;
+ }
}
/**
@@ -473,47 +572,47 @@
switch (type) {
case ServiceType.GPS:
return builder.setBatterySaverEnabled(realMode)
- .setGpsMode(mGpsMode)
+ .setGpsMode(mCurrPolicy.gpsMode)
.build();
case ServiceType.ANIMATION:
- return builder.setBatterySaverEnabled(mAnimationDisabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.disableAnimation)
.build();
case ServiceType.FULL_BACKUP:
- return builder.setBatterySaverEnabled(mFullBackupDeferred)
+ return builder.setBatterySaverEnabled(mCurrPolicy.deferFullBackup)
.build();
case ServiceType.KEYVALUE_BACKUP:
- return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
+ return builder.setBatterySaverEnabled(mCurrPolicy.deferKeyValueBackup)
.build();
case ServiceType.NETWORK_FIREWALL:
- return builder.setBatterySaverEnabled(!mFireWallDisabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.enableFirewall)
.build();
case ServiceType.SCREEN_BRIGHTNESS:
- return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
- .setBrightnessFactor(mAdjustBrightnessFactor)
+ return builder.setBatterySaverEnabled(mCurrPolicy.enableAdjustBrightness)
+ .setBrightnessFactor(mCurrPolicy.adjustBrightnessFactor)
.build();
case ServiceType.DATA_SAVER:
- return builder.setBatterySaverEnabled(!mDataSaverDisabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.enableDataSaver)
.build();
case ServiceType.SOUND:
- return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.disableSoundTrigger)
.build();
case ServiceType.VIBRATION:
- return builder.setBatterySaverEnabled(mVibrationDisabledEffective)
+ return builder.setBatterySaverEnabled(mDisableVibrationEffective)
.build();
case ServiceType.FORCE_ALL_APPS_STANDBY:
- return builder.setBatterySaverEnabled(mForceAllAppsStandby)
+ return builder.setBatterySaverEnabled(mCurrPolicy.forceAllAppsStandby)
.build();
case ServiceType.FORCE_BACKGROUND_CHECK:
- return builder.setBatterySaverEnabled(mForceBackgroundCheck)
+ return builder.setBatterySaverEnabled(mCurrPolicy.forceBackgroundCheck)
.build();
case ServiceType.OPTIONAL_SENSORS:
- return builder.setBatterySaverEnabled(mOptionalSensorsDisabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.disableOptionalSensors)
.build();
case ServiceType.AOD:
- return builder.setBatterySaverEnabled(mAodDisabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.disableAod)
.build();
case ServiceType.QUICK_DOZE:
- return builder.setBatterySaverEnabled(mQuickDozeEnabled)
+ return builder.setBatterySaverEnabled(mCurrPolicy.enableQuickDoze)
.build();
default:
return builder.setBatterySaverEnabled(realMode)
@@ -524,19 +623,20 @@
public int getGpsMode() {
synchronized (mLock) {
- return mGpsMode;
+ return mCurrPolicy.gpsMode;
}
}
public ArrayMap<String, String> getFileValues(boolean interactive) {
synchronized (mLock) {
- return interactive ? mFilesForInteractive : mFilesForNoninteractive;
+ return interactive ? mCurrPolicy.filesForInteractive
+ : mCurrPolicy.filesForNoninteractive;
}
}
public boolean isLaunchBoostDisabled() {
synchronized (mLock) {
- return mLaunchBoostDisabled;
+ return mCurrPolicy.disableLaunchBoost;
}
}
@@ -560,31 +660,35 @@
pw.println();
pw.println(" mAccessibilityEnabled=" + mAccessibilityEnabled);
- pw.println(" " + KEY_VIBRATION_DISABLED + ":config=" + mVibrationDisabledConfig);
- pw.println(" " + KEY_VIBRATION_DISABLED + ":effective=" + mVibrationDisabledEffective);
- pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled);
- pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
- pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
- pw.println(" " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
- pw.println(" " + KEY_DATASAVER_DISABLED + "=" + mDataSaverDisabled);
- pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + mLaunchBoostDisabled);
- pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
- pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
- pw.println(" " + KEY_GPS_MODE + "=" + mGpsMode);
- pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mForceAllAppsStandby);
- pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mForceBackgroundCheck);
- pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled);
- pw.println(" " + KEY_AOD_DISABLED + "=" + mAodDisabled);
- pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + mQuickDozeEnabled);
- pw.println(" " + KEY_SEND_TRON_LOG + "=" + mSendTronLog);
+ pw.println(" " + KEY_VIBRATION_DISABLED + ":config=" + mCurrPolicy.disableVibration);
+ pw.println(" " + KEY_VIBRATION_DISABLED + ":effective=" + mDisableVibrationEffective);
+ pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mCurrPolicy.disableAnimation);
+ pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mCurrPolicy.deferFullBackup);
+ pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mCurrPolicy.deferKeyValueBackup);
+ pw.println(" " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !mCurrPolicy.enableFirewall);
+ pw.println(" " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !mCurrPolicy.enableDataSaver);
+ pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + mCurrPolicy.disableLaunchBoost);
+ pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "="
+ + !mCurrPolicy.enableAdjustBrightness);
+ pw.println(
+ " " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mCurrPolicy.adjustBrightnessFactor);
+ pw.println(" " + KEY_GPS_MODE + "=" + mCurrPolicy.gpsMode);
+ pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mCurrPolicy.forceAllAppsStandby);
+ pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mCurrPolicy.forceBackgroundCheck);
+ pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "="
+ + mCurrPolicy.disableOptionalSensors);
+ pw.println(" " + KEY_AOD_DISABLED + "=" + mCurrPolicy.disableAod);
+ pw.println(" " + KEY_SOUNDTRIGGER_DISABLED + "=" + mCurrPolicy.disableSoundTrigger);
+ pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + mCurrPolicy.enableQuickDoze);
+ pw.println(" " + KEY_SEND_TRON_LOG + "=" + mCurrPolicy.sendTronLog);
pw.println();
pw.print(" Interactive File values:\n");
- dumpMap(pw, " ", mFilesForInteractive);
+ dumpMap(pw, " ", mCurrPolicy.filesForInteractive);
pw.println();
pw.print(" Noninteractive File values:\n");
- dumpMap(pw, " ", mFilesForNoninteractive);
+ dumpMap(pw, " ", mCurrPolicy.filesForNoninteractive);
}
}
diff --git a/services/core/java/com/android/server/power/OWNERS b/services/core/java/com/android/server/power/OWNERS
index d118c4e..20e4985 100644
--- a/services/core/java/com/android/server/power/OWNERS
+++ b/services/core/java/com/android/server/power/OWNERS
@@ -2,3 +2,4 @@
per-file BatterySaverPolicy.java=omakoto@google.com
per-file ShutdownThread.java=fkupolov@google.com
+per-file ThermalManagerService.java=wvw@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
new file mode 100644
index 0000000..812fd82
--- /dev/null
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.content.Context;
+import android.hardware.thermal.V1_0.ThermalStatus;
+import android.hardware.thermal.V1_0.ThermalStatusCode;
+import android.hardware.thermal.V1_1.IThermalCallback;
+import android.hardware.thermal.V2_0.IThermalChangedCallback;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
+import android.os.Binder;
+import android.os.HwBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.server.FgThread;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * This is a system service that listens to HAL thermal events and dispatch those to listeners.
+ * <p>The service will also trigger actions based on severity of the throttling status.</p>
+ *
+ * @hide
+ */
+public class ThermalManagerService extends SystemService {
+ private static final String TAG = ThermalManagerService.class.getSimpleName();
+
+ /** Registered observers of the thermal changed events. Cookie is used to store type */
+ @GuardedBy("mLock")
+ private final RemoteCallbackList<IThermalEventListener> mThermalEventListeners =
+ new RemoteCallbackList<>();
+
+ /** Lock to protect HAL handles and listen list. */
+ private final Object mLock = new Object();
+
+ /** Newly registered callback. */
+ @GuardedBy("mLock")
+ private IThermalEventListener mNewListenerCallback = null;
+
+ /** Newly registered callback type, null means not filter type. */
+ @GuardedBy("mLock")
+ private Integer mNewListenerType = null;
+
+ /** Local PMS handle. */
+ private final PowerManager mPowerManager;
+
+ /** Proxy object for the Thermal HAL 2.0 service. */
+ @GuardedBy("mLock")
+ private android.hardware.thermal.V2_0.IThermal mThermalHal20 = null;
+
+ /** Proxy object for the Thermal HAL 1.1 service. */
+ @GuardedBy("mLock")
+ private android.hardware.thermal.V1_1.IThermal mThermalHal11 = null;
+
+ /** Cookie for matching the right end point. */
+ private static final int THERMAL_HAL_DEATH_COOKIE = 5612;
+
+ /** HWbinder callback for Thermal HAL 2.0. */
+ private final IThermalChangedCallback.Stub mThermalCallback20 =
+ new IThermalChangedCallback.Stub() {
+ @Override
+ public void notifyThrottling(
+ android.hardware.thermal.V2_0.Temperature temperature) {
+ android.os.Temperature thermalSvcTemp = new android.os.Temperature(
+ temperature.value, temperature.type, temperature.name,
+ temperature.throttlingStatus);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ notifyThrottlingImpl(thermalSvcTemp);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ /** HWbinder callback for Thermal HAL 1.1. */
+ private final IThermalCallback.Stub mThermalCallback11 =
+ new IThermalCallback.Stub() {
+ @Override
+ public void notifyThrottling(boolean isThrottling,
+ android.hardware.thermal.V1_0.Temperature temperature) {
+ android.os.Temperature thermalSvcTemp = new android.os.Temperature(
+ temperature.currentValue, temperature.type, temperature.name,
+ isThrottling ? ThrottlingSeverity.SEVERE : ThrottlingSeverity.NONE);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ notifyThrottlingImpl(thermalSvcTemp);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ public ThermalManagerService(Context context) {
+ super(context);
+ mPowerManager = context.getSystemService(PowerManager.class);
+ }
+
+ private void setNewListener(IThermalEventListener listener, Integer type) {
+ synchronized (mLock) {
+ mNewListenerCallback = listener;
+ mNewListenerType = type;
+ }
+ }
+
+ private void clearNewListener() {
+ synchronized (mLock) {
+ mNewListenerCallback = null;
+ mNewListenerType = null;
+ }
+ }
+
+ private final IThermalService.Stub mService = new IThermalService.Stub() {
+ @Override
+ public void registerThermalEventListener(IThermalEventListener listener) {
+ synchronized (mLock) {
+ mThermalEventListeners.register(listener, null);
+ // Notify its callback after new client registered.
+ setNewListener(listener, null);
+ long token = Binder.clearCallingIdentity();
+ try {
+ notifyCurrentTemperaturesLocked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ clearNewListener();
+ }
+ }
+ }
+
+ @Override
+ public void registerThermalEventListenerWithType(IThermalEventListener listener, int type) {
+ synchronized (mLock) {
+ mThermalEventListeners.register(listener, new Integer(type));
+ setNewListener(listener, new Integer(type));
+ // Notify its callback after new client registered.
+ long token = Binder.clearCallingIdentity();
+ try {
+ notifyCurrentTemperaturesLocked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ clearNewListener();
+ }
+ }
+ }
+
+ @Override
+ public void unregisterThermalEventListener(IThermalEventListener listener) {
+ synchronized (mLock) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mThermalEventListeners.unregister(listener);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ @Override
+ public List<android.os.Temperature> getCurrentTemperatures() {
+ List<android.os.Temperature> ret;
+ long token = Binder.clearCallingIdentity();
+ try {
+ ret = getCurrentTemperaturesInternal(false, 0 /* not used */);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return ret;
+ }
+
+ @Override
+ public List<android.os.Temperature> getCurrentTemperaturesWithType(int type) {
+ List<android.os.Temperature> ret;
+ long token = Binder.clearCallingIdentity();
+ try {
+ ret = getCurrentTemperaturesInternal(true, type);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return ret;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+ pw.println("ThermalEventListeners dump:");
+ synchronized (mLock) {
+ mThermalEventListeners.dump(pw, "\t");
+ pw.println("ThermalHAL 1.1 connected: " + (mThermalHal11 != null ? "yes" : "no"));
+ pw.println("ThermalHAL 2.0 connected: " + (mThermalHal20 != null ? "yes" : "no"));
+ }
+ }
+ };
+
+ private List<android.os.Temperature> getCurrentTemperaturesInternal(boolean shouldFilter,
+ int type) {
+ List<android.os.Temperature> ret = new ArrayList<>();
+ synchronized (mLock) {
+ if (mThermalHal20 == null) {
+ return ret;
+ }
+ try {
+ mThermalHal20.getCurrentTemperatures(shouldFilter, type,
+ (ThermalStatus status,
+ ArrayList<android.hardware.thermal.V2_0.Temperature>
+ temperatures) -> {
+ if (ThermalStatusCode.SUCCESS == status.code) {
+ for (android.hardware.thermal.V2_0.Temperature
+ temperature : temperatures) {
+ ret.add(new android.os.Temperature(
+ temperature.value, temperature.type, temperature.name,
+ temperature.throttlingStatus));
+ }
+ } else {
+ Slog.e(TAG,
+ "Couldn't get temperatures because of HAL error: "
+ + status.debugMessage);
+ }
+
+ });
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Couldn't getCurrentTemperatures, reconnecting...", e);
+ connectToHalLocked();
+ // Post to listeners after reconnect to HAL.
+ notifyCurrentTemperaturesLocked();
+ }
+ }
+ return ret;
+ }
+
+ private void notifyListener(android.os.Temperature temperature, IThermalEventListener listener,
+ Integer type) {
+ // Skip if listener registered with a different type
+ if (type != null && type != temperature.getType()) {
+ return;
+ }
+ final boolean thermalCallbackQueued = FgThread.getHandler().post(() -> {
+ try {
+ listener.notifyThrottling(temperature);
+ } catch (RemoteException | RuntimeException e) {
+ Slog.e(TAG, "Thermal callback failed to call", e);
+ }
+ });
+ if (!thermalCallbackQueued) {
+ Slog.e(TAG, "Thermal callback failed to queue");
+ }
+ }
+
+ private void notifyThrottlingImpl(android.os.Temperature temperature) {
+ synchronized (mLock) {
+ // Thermal Shutdown for Skin temperature
+ if (temperature.getStatus() == android.os.Temperature.THROTTLING_SHUTDOWN
+ && temperature.getType() == android.os.Temperature.TYPE_SKIN) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ if (mNewListenerCallback != null) {
+ // Only notify current newly added callback.
+ notifyListener(temperature, mNewListenerCallback, mNewListenerType);
+ } else {
+ final int length = mThermalEventListeners.beginBroadcast();
+ try {
+ for (int i = 0; i < length; i++) {
+ final IThermalEventListener listener =
+ mThermalEventListeners.getBroadcastItem(i);
+ final Integer type = (Integer) mThermalEventListeners.getBroadcastCookie(i);
+ notifyListener(temperature, listener, type);
+ }
+ } finally {
+ mThermalEventListeners.finishBroadcast();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.THERMAL_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ onActivityManagerReady();
+ }
+ }
+
+ private void notifyCurrentTemperaturesCallbackLocked(ThermalStatus status,
+ ArrayList<android.hardware.thermal.V2_0.Temperature> temperatures) {
+ if (ThermalStatusCode.SUCCESS != status.code) {
+ Slog.e(TAG, "Couldn't get temperatures because of HAL error: "
+ + status.debugMessage);
+ return;
+ }
+ for (android.hardware.thermal.V2_0.Temperature temperature : temperatures) {
+ android.os.Temperature thermal_svc_temp =
+ new android.os.Temperature(
+ temperature.value, temperature.type,
+ temperature.name,
+ temperature.throttlingStatus);
+ notifyThrottlingImpl(thermal_svc_temp);
+ }
+ }
+
+ private void notifyCurrentTemperaturesLocked() {
+ if (mThermalHal20 == null) {
+ return;
+ }
+ try {
+ mThermalHal20.getCurrentTemperatures(false, 0,
+ this::notifyCurrentTemperaturesCallbackLocked);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Couldn't get temperatures, reconnecting...", e);
+ connectToHalLocked();
+ }
+ }
+
+ private void onActivityManagerReady() {
+ synchronized (mLock) {
+ connectToHalLocked();
+ // Post to listeners after connect to HAL.
+ notifyCurrentTemperaturesLocked();
+ }
+ }
+
+ final class DeathRecipient implements HwBinder.DeathRecipient {
+ @Override
+ public void serviceDied(long cookie) {
+ if (cookie == THERMAL_HAL_DEATH_COOKIE) {
+ Slog.e(TAG, "Thermal HAL service died cookie: " + cookie);
+ synchronized (mLock) {
+ connectToHalLocked();
+ // Post to listeners after reconnect to HAL.
+ notifyCurrentTemperaturesLocked();
+ }
+ }
+ }
+ }
+
+ private void connectToHalLocked() {
+ try {
+ mThermalHal20 = android.hardware.thermal.V2_0.IThermal.getService();
+ mThermalHal20.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
+ mThermalHal20.registerThermalChangedCallback(mThermalCallback20, false,
+ 0 /* not used */);
+ } catch (NoSuchElementException | RemoteException e) {
+ Slog.e(TAG, "Thermal HAL 2.0 service not connected, trying 1.1.");
+ mThermalHal20 = null;
+ try {
+ mThermalHal11 = android.hardware.thermal.V1_1.IThermal.getService();
+ mThermalHal11.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
+ mThermalHal11.registerThermalCallback(mThermalCallback11);
+ } catch (NoSuchElementException | RemoteException e2) {
+ Slog.e(TAG,
+ "Thermal HAL 1.1 service not connected, no thermal call back "
+ + "will be called.");
+ mThermalHal11 = null;
+ }
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 4d3fc1a..2be55c0 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -253,8 +253,8 @@
if (b != null) {
sThermalService = IThermalService.Stub.asInterface(b);
try {
- sThermalService.registerThermalEventListener(
- new ThermalEventListener());
+ sThermalService.registerThermalEventListenerWithType(
+ new ThermalEventListener(), Temperature.TYPE_SKIN);
Slog.i(TAG, "register thermal listener successfully");
} catch (RemoteException e) {
// Should never happen.
@@ -1853,7 +1853,8 @@
// Thermal event received from vendor thermal management subsystem
private static final class ThermalEventListener extends IThermalEventListener.Stub {
@Override
- public void notifyThrottling(boolean isThrottling, Temperature temp) {
+ public void notifyThrottling(Temperature temp) {
+ boolean isThrottling = temp.getStatus() >= Temperature.THROTTLING_SEVERE;
StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
isThrottling ? 1 : 0, temp.getValue());
}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 5fb1def..751ae0d 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
@@ -51,6 +52,7 @@
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.os.UserHandle;
import android.util.IntArray;
@@ -156,7 +158,7 @@
}
void updateBounds() {
- mDisplay.getSize(mTmpDisplaySize);
+ mDisplay.getRealSize(mTmpDisplaySize);
setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
}
@@ -938,6 +940,25 @@
return mStacks.indexOf(stack);
}
+ @Override
+ public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ final int currRotation = getOverrideConfiguration().windowConfiguration.getRotation();
+ if (currRotation != ROTATION_UNDEFINED
+ && currRotation != overrideConfiguration.windowConfiguration.getRotation()
+ && getWindowContainerController() != null) {
+ getWindowContainerController().applyRotation(currRotation,
+ overrideConfiguration.windowConfiguration.getRotation());
+ }
+ super.onOverrideConfigurationChanged(overrideConfiguration);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newParentConfig) {
+ // update resources before cascade so that docked/pinned stacks use the correct info
+ getWindowContainerController().preOnConfigurationChanged();
+ super.onConfigurationChanged(newParentConfig);
+ }
+
void onLockTaskPackagesUpdated() {
for (int i = mStacks.size() - 1; i >= 0; --i) {
mStacks.get(i).onLockTaskPackagesUpdated();
@@ -1010,29 +1031,50 @@
void remove() {
final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
+ ActivityStack lastReparentedStack = null;
+ mPreferredTopFocusableStack = null;
// Stacks could be reparented from the removed display to other display. While
// reparenting the last stack of the removed display, the remove display is ready to be
// released (no more ActivityStack). But, we cannot release it at that moment or the
// related WindowContainer and WindowContainerController will also be removed. So, we
// set display as removed after reparenting stack finished.
- for (int i = mStacks.size() - 1; i >= 0; --i) {
- final ActivityStack stack = mStacks.get(i);
- // Always finish non-standard type stacks.
- if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
- stack.finishAllActivitiesLocked(true /* immediately */);
- } else {
- // If default display is in split-window mode, set windowing mode of the stack to
- // split-screen secondary. Otherwise, set the windowing mode to undefined by
- // default to let stack inherited the windowing mode from the new display.
- int windowingMode = mSupervisor.getDefaultDisplay().hasSplitScreenPrimaryStack()
- ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_UNDEFINED;
- mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, true);
- stack.setWindowingMode(windowingMode);
+ final ActivityDisplay toDisplay = mSupervisor.getDefaultDisplay();
+ mSupervisor.beginDeferResume();
+ try {
+ int numStacks = mStacks.size();
+ // Keep the order from bottom to top.
+ for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
+ final ActivityStack stack = mStacks.get(stackNdx);
+ // Always finish non-standard type stacks.
+ if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
+ stack.finishAllActivitiesLocked(true /* immediately */);
+ } else {
+ // If default display is in split-window mode, set windowing mode of the stack
+ // to split-screen secondary. Otherwise, set the windowing mode to undefined by
+ // default to let stack inherited the windowing mode from the new display.
+ final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
+ ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ : WINDOWING_MODE_UNDEFINED;
+ stack.reparent(toDisplay, true /* onTop */, true /* displayRemoved */);
+ stack.setWindowingMode(windowingMode);
+ lastReparentedStack = stack;
+ }
+ // Stacks may be removed from this display. Ensure each stack will be processed and
+ // the loop will end.
+ stackNdx -= numStacks - mStacks.size();
+ numStacks = mStacks.size();
}
+ } finally {
+ mSupervisor.endDeferResume();
}
mRemoved = true;
+ // Only update focus/visibility for the last one because there may be many stacks are
+ // reparented and the intermediate states are unnecessary.
+ if (lastReparentedStack != null) {
+ lastReparentedStack.postReparent();
+ }
releaseSelfIfNeeded();
if (!mAllSleepTokens.isEmpty()) {
@@ -1061,16 +1103,16 @@
}
/**
+ * Checks if system decorations should be shown on this display.
+ *
* @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
*/
boolean supportsSystemDecorations() {
- return mDisplay.supportsSystemDecorations()
- // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
- // (b/114338689) whenever vr 2d display id is set.
- || mDisplayId == mSupervisor.mService.mVr2dDisplayId;
+ return mWindowContainerController.supportsSystemDecorations();
}
- private boolean shouldDestroyContentOnRemove() {
+ @VisibleForTesting
+ boolean shouldDestroyContentOnRemove() {
return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
new file mode 100644
index 0000000..e3133ef
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Observe activity manager launch sequences.
+ *
+ * The activity manager can have at most 1 concurrent launch sequences. Calls to this interface
+ * are ordered by a happens-before relation for each defined state transition (see below).
+ *
+ * When a new launch sequence is made, that sequence is in the {@code INTENT_STARTED} state which
+ * is communicated by the {@link #onIntentStarted} callback. This is a transient state.
+ *
+ * The intent can fail to launch the activity, in which case the sequence's state transitions to
+ * {@code INTENT_FAILED} via {@link #onIntentFailed}. This is a terminal state.
+ *
+ * If an activity is successfully started, the launch sequence's state will transition into
+ * {@code STARTED} via {@link #onActivityLaunched}. This is a transient state.
+ *
+ * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled}
+ * or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states.
+ *
+ * Note that the {@link ActivityRecord} provided as a parameter to some state transitions isn't
+ * necessarily the same within a single launch sequence: it is only the top-most activity at the
+ * time (if any). Trampoline activities coalesce several activity starts into a single launch
+ * sequence.
+ *
+ * Upon reaching a terminal state, it is considered that there are no active launch sequences
+ * until a subsequent transition into {@code INTENT_STARTED} initiates a new launch sequence.
+ *
+ * <pre>
+ * ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐ ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐ ╔══════════════════════════╗
+ * ╴╴▶ ⋮ INTENT_STARTED ⋮ ──▶ ⋮ ACTIVITY_LAUNCHED ⋮ ──▶ ║ ACTIVITY_LAUNCH_FINISHED ║
+ * └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘ └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘ ╚══════════════════════════╝
+ * : :
+ * : :
+ * ▼ ▼
+ * ╔════════════════╗ ╔═══════════════════════════╗
+ * ║ INTENT_FAILED ║ ║ ACTIVITY_LAUNCH_CANCELLED ║
+ * ╚════════════════╝ ╚═══════════════════════════╝
+ * </pre>
+ */
+public interface ActivityMetricsLaunchObserver {
+ /**
+ * The 'temperature' at which a launch sequence had started.
+ *
+ * The lower the temperature the more work has to be done during start-up.
+ * A 'cold' temperature means that a new process has been started and likely
+ * nothing is cached.
+ *
+ * A hot temperature means the existing activity is brought to the foreground.
+ * It may need to regenerate some objects as a result of {@code onTrimMemory}.
+ *
+ * A warm temperature is in the middle; an existing process is used, but the activity
+ * has to be created from scratch with {@code #onCreate}.
+ *
+ * @see https://developer.android.com/topic/performance/vitals/launch-time
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ TEMPERATURE_COLD,
+ TEMPERATURE_WARM,
+ TEMPERATURE_HOT
+ })
+ @interface Temperature {}
+
+ /** Cold launch sequence: a new process has started. */
+ public static final int TEMPERATURE_COLD = 1;
+ /** Warm launch sequence: process reused, but activity has to be created. */
+ public static final int TEMPERATURE_WARM = 2;
+ /** Hot launch sequence: process reused, activity brought-to-top. */
+ public static final int TEMPERATURE_HOT = 3;
+
+ /**
+ * Notifies the observer that a new launch sequence has begun as a result of a new intent.
+ *
+ * Once a launch sequence begins, the resolved activity will either subsequently start with
+ * {@link #onActivityLaunched} or abort early (for example due to a resolution error or due to
+ * a security error) with {@link #onIntentFailed}.
+ *
+ * Multiple calls to this method cannot occur without first terminating the current
+ * launch sequence.
+ */
+ public void onIntentStarted(@NonNull Intent intent);
+
+ /**
+ * Notifies the observer that the current launch sequence has failed to launch an activity.
+ *
+ * This function call terminates the current launch sequence. The next method call, if any,
+ * must be {@link #onIntentStarted}.
+ *
+ * Examples of this happening:
+ * - Failure to resolve to an activity
+ * - Calling package did not have the security permissions to call the requested activity
+ * - Resolved activity was already running and only needed to be brought to the top
+ *
+ * Multiple calls to this method cannot occur without first terminating the current
+ * launch sequence.
+ */
+ public void onIntentFailed();
+
+ /**
+ * Notifies the observer that the current launch sequence had begun starting an activity.
+ *
+ * This is an intermediate state: once an activity begins starting, the entire launch sequence
+ * will later terminate by either finishing or cancelling.
+ *
+ * The initial activity is the first activity to be started as part of a launch sequence:
+ * it is represented by {@param activity} However, it isn't
+ * necessarily the activity which will be considered as displayed when the activity
+ * finishes launching (e.g. {@code activity} in {@link #onActivityLaunchFinished}).
+ *
+ * Multiple calls to this method cannot occur without first terminating the current
+ * launch sequence.
+ */
+ public void onActivityLaunched(@NonNull ActivityRecord activity,
+ @Temperature int temperature);
+
+ /**
+ * Notifies the observer that the current launch sequence has been aborted.
+ *
+ * This function call terminates the current launch sequence. The next method call, if any,
+ * must be {@link #onIntentStarted}.
+ *
+ * This can happen for many reasons, for example the user switches away to another app
+ * prior to the launch sequence completing, or the application being killed.
+ *
+ * Multiple calls to this method cannot occur without first terminating the current
+ * launch sequence.
+ *
+ * @param abortingActivity the last activity that had the top-most window during abort
+ * (this can be {@code null} in rare situations its unknown).
+ *
+ * @apiNote The aborting activity isn't necessarily the same as the starting activity;
+ * in the case of a trampoline, multiple activities could've been started
+ * and only the latest activity is reported here.
+ */
+ public void onActivityLaunchCancelled(@Nullable ActivityRecord abortingActivity);
+
+ /**
+ * Notifies the observer that the current launch sequence has been successfully finished.
+ *
+ * This function call terminates the current launch sequence. The next method call, if any,
+ * must be {@link #onIntentStarted}.
+ *
+ * A launch sequence is considered to be successfully finished when a frame is fully
+ * drawn for the first time: the top-most activity at the time is what's reported here.
+ *
+ * @param finalActivity the top-most activity whose windows were first to fully draw
+ *
+ * Multiple calls to this method cannot occur without first terminating the current
+ * launch sequence.
+ *
+ * @apiNote The finishing activity isn't necessarily the same as the starting activity;
+ * in the case of a trampoline, multiple activities could've been started
+ * and only the latest activity that was top-most during first-frame drawn
+ * is reported here.
+ */
+ public void onActivityLaunchFinished(@NonNull ActivityRecord finalActivity);
+}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 8bde7dd..61e1414 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -72,14 +72,15 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
+import android.app.WindowConfiguration.WindowingMode;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -141,15 +142,21 @@
private final Context mContext;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
+ // set to INVALID_START_TIME in reset.
+ // set to valid value in notifyActivityLaunching
private long mCurrentTransitionStartTime = INVALID_START_TIME;
private long mLastTransitionStartTime = INVALID_START_TIME;
private int mCurrentTransitionDeviceUptime;
private int mCurrentTransitionDelayMs;
+
+ /** If the any app transitions have been logged as starting, after the latest reset. */
private boolean mLoggedTransitionStarting;
+ /** Map : @WindowingMode int => WindowingModeTransitionInfo */
private final SparseArray<WindowingModeTransitionInfo> mWindowingModeTransitionInfo =
new SparseArray<>();
+ /** Map : @WindowingMode int => WindowingModeTransitionInfo */
private final SparseArray<WindowingModeTransitionInfo> mLastWindowingModeTransitionInfo =
new SparseArray<>();
private final H mHandler;
@@ -157,6 +164,12 @@
private ArtManagerInternal mArtManagerInternal;
private final StringBuilder mStringBuilder = new StringBuilder();
+ /**
+ * Due to the global single concurrent launch sequence, all calls to this observer must be made
+ * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver.
+ */
+ private final ActivityMetricsLaunchObserver mLaunchObserver = null;
+
private final class H extends Handler {
public H(Looper looper) {
@@ -175,6 +188,7 @@
}
private final class WindowingModeTransitionInfo {
+ /** The latest activity to have been launched. */
private ActivityRecord launchedActivity;
private int startResult;
private boolean currentTransitionProcessRunning;
@@ -273,7 +287,7 @@
return;
}
- int windowingMode = stack.getWindowingMode();
+ @WindowingMode int windowingMode = stack.getWindowingMode();
if (windowingMode == WINDOWING_MODE_PINNED) {
stack = mSupervisor.findStackBehind(stack);
windowingMode = stack.getWindowingMode();
@@ -301,11 +315,19 @@
* Notifies the tracker at the earliest possible point when we are starting to launch an
* activity.
*/
- void notifyActivityLaunching() {
+ void notifyActivityLaunching(Intent intent) {
+ if (DEBUG_METRICS) {
+ Slog.i(TAG, String.format("notifyActivityLaunching: active:%b, intent:%s",
+ isAnyTransitionActive(),
+ intent));
+ }
+
if (!isAnyTransitionActive()) {
- if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunching");
+
mCurrentTransitionStartTime = SystemClock.uptimeMillis();
mLastTransitionStartTime = mCurrentTransitionStartTime;
+
+ launchObserverNotifyIntentStarted(intent);
}
}
@@ -350,7 +372,9 @@
+ " processRunning=" + processRunning
+ " processSwitch=" + processSwitch);
- final int windowingMode = launchedActivity != null
+ // If we are already in an existing transition, only update the activity name, but not the
+ // other attributes.
+ final @WindowingMode int windowingMode = launchedActivity != null
? launchedActivity.getWindowingMode()
: WINDOWING_MODE_UNDEFINED;
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
@@ -361,13 +385,15 @@
if (launchedActivity != null && launchedActivity.nowVisible) {
// Launched activity is already visible. We cannot measure windows drawn delay.
- reset(true /* abort */, info);
+ reset(true /* abort */, info, "launched activity already visible");
return;
}
if (launchedActivity != null && info != null) {
// If we are already in an existing transition, only update the activity name, but not
// the other attributes.
+
+ // Coalesce multiple (trampoline) activities from a single sequence together.
info.launchedActivity = launchedActivity;
return;
}
@@ -377,7 +403,7 @@
if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
|| windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
// Failed to launch or it was not a process switch, so we don't care about the timing.
- reset(true /* abort */, info);
+ reset(true /* abort */, info, "failed to launch or not a process switch");
return;
} else if (otherWindowModesLaunching) {
// Don't log this windowing mode but continue with the other windowing modes.
@@ -386,6 +412,8 @@
if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched successful");
+ // A new launch sequence [with the windowingMode] has begun.
+ // Start tracking it.
final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
newInfo.launchedActivity = launchedActivity;
newInfo.currentTransitionProcessRunning = processRunning;
@@ -394,6 +422,7 @@
mLastWindowingModeTransitionInfo.put(windowingMode, newInfo);
mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
startTraces(newInfo);
+ launchObserverNotifyActivityLaunched(newInfo);
}
/**
@@ -407,7 +436,8 @@
/**
* Notifies the tracker that all windows of the app have been drawn.
*/
- WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(int windowingMode, long timestamp) {
+ WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(@WindowingMode int windowingMode,
+ long timestamp) {
if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
@@ -419,7 +449,7 @@
final WindowingModeTransitionInfoSnapshot infoSnapshot =
new WindowingModeTransitionInfoSnapshot(info);
if (allWindowsDrawn() && mLoggedTransitionStarting) {
- reset(false /* abort */, info);
+ reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn");
}
return infoSnapshot;
}
@@ -427,7 +457,7 @@
/**
* Notifies the tracker that the starting window was drawn.
*/
- void notifyStartingWindowDrawn(int windowingMode, long timestamp) {
+ void notifyStartingWindowDrawn(@WindowingMode int windowingMode, long timestamp) {
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
if (info == null || info.loggedStartingWindowDrawn) {
return;
@@ -444,22 +474,30 @@
*/
void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestamp) {
if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
+ // Ignore calls to this made after a reset and prior to notifyActivityLaunching.
+
+ // Ignore any subsequent notifyTransitionStarting until the next reset.
return;
}
if (DEBUG_METRICS) Slog.i(TAG, "notifyTransitionStarting");
mCurrentTransitionDelayMs = calculateDelay(timestamp);
mLoggedTransitionStarting = true;
+
+ WindowingModeTransitionInfo foundInfo = null;
for (int index = windowingModeToReason.size() - 1; index >= 0; index--) {
- final int windowingMode = windowingModeToReason.keyAt(index);
+ final @WindowingMode int windowingMode = windowingModeToReason.keyAt(index);
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
windowingMode);
if (info == null) {
continue;
}
info.reason = windowingModeToReason.valueAt(index);
+ foundInfo = info;
}
if (allWindowsDrawn()) {
- reset(false /* abort */, null /* WindowingModeTransitionInfo */);
+ // abort metrics collection if we cannot find a matching transition.
+ final boolean abortMetrics = foundInfo == null;
+ reset(abortMetrics, foundInfo, "notifyTransitionStarting - all windows drawn");
}
}
@@ -498,7 +536,7 @@
logAppTransitionCancel(info);
mWindowingModeTransitionInfo.remove(r.getWindowingMode());
if (mWindowingModeTransitionInfo.size() == 0) {
- reset(true /* abort */, info);
+ reset(true /* abort */, info, "notifyVisibilityChanged to invisible");
}
}
}
@@ -534,12 +572,25 @@
&& mWindowingModeTransitionInfo.size() > 0;
}
- private void reset(boolean abort, WindowingModeTransitionInfo info) {
- if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort);
+ private void reset(boolean abort, WindowingModeTransitionInfo info, String cause) {
+ if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort + ",cause=" + cause);
if (!abort && isAnyTransitionActive()) {
logAppTransitionMultiEvents();
}
stopLaunchTrace(info);
+
+ // Ignore reset-after reset.
+ if (isAnyTransitionActive()) {
+ // LaunchObserver callbacks.
+ if (abort) {
+ launchObserverNotifyActivityLaunchCancelled(info);
+ } else {
+ launchObserverNotifyActivityLaunchFinished(info);
+ }
+ } else {
+ launchObserverNotifyIntentFailed();
+ }
+
mCurrentTransitionStartTime = INVALID_START_TIME;
mCurrentTransitionDelayMs = INVALID_DELAY;
mLoggedTransitionStarting = false;
@@ -572,6 +623,13 @@
info.launchedActivity.packageName,
convertAppStartTransitionType(type),
info.launchedActivity.info.name);
+ if (DEBUG_METRICS) {
+ Slog.i(TAG, String.format("APP_START_CANCELED(%s, %s, %s, %s)",
+ info.launchedActivity.appInfo.uid,
+ info.launchedActivity.packageName,
+ convertAppStartTransitionType(type),
+ info.launchedActivity.info.name));
+ }
}
private void logAppTransitionMultiEvents() {
@@ -656,6 +714,17 @@
launchToken,
packageOptimizationInfo.getCompilationReason(),
packageOptimizationInfo.getCompilationFilter());
+
+ if (DEBUG_METRICS) {
+ Slog.i(TAG, String.format("APP_START_OCCURRED(%s, %s, %s, %s, %s)",
+ info.applicationInfo.uid,
+ info.packageName,
+ convertAppStartTransitionType(info.type),
+ info.launchedActivityName,
+ info.launchedActivityLaunchedFromPackage));
+ }
+
+
logAppStartMemoryStateCapture(info);
}
@@ -923,4 +992,76 @@
info.launchTraceActive = false;
}
}
+
+ /** Notify the {@link ActivityMetricsLaunchObserver} that a new launch sequence has begun. */
+ private void launchObserverNotifyIntentStarted(Intent intent) {
+ if (mLaunchObserver != null) {
+ // Beginning a launch is timing sensitive and so should be observed as soon as possible.
+ mLaunchObserver.onIntentStarted(intent);
+ }
+ }
+
+ /**
+ * Notify the {@link ActivityMetricsLaunchObserver} that the previous launch sequence has
+ * aborted due to intent failure (e.g. intent resolve failed or security error, etc) or
+ * intent being delivered to the top running activity.
+ */
+ private void launchObserverNotifyIntentFailed() {
+ if (mLaunchObserver != null) {
+ mLaunchObserver.onIntentFailed();
+ }
+ }
+
+ /**
+ * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence's activity
+ * has started.
+ */
+ private void launchObserverNotifyActivityLaunched(WindowingModeTransitionInfo info) {
+ @ActivityMetricsLaunchObserver.Temperature int temperature =
+ convertTransitionTypeToLaunchObserverTemperature(getTransitionType(info));
+
+ if (mLaunchObserver != null) {
+ // Beginning a launch is timing sensitive and so should be observed as soon as possible.
+ mLaunchObserver.onActivityLaunched(info.launchedActivity,
+ temperature);
+ }
+ }
+
+ /**
+ * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence is
+ * cancelled.
+ */
+ private void launchObserverNotifyActivityLaunchCancelled(WindowingModeTransitionInfo info) {
+ final ActivityRecord launchedActivity = info != null ? info.launchedActivity : null;
+
+ if (mLaunchObserver != null) {
+ mLaunchObserver.onActivityLaunchCancelled(launchedActivity);
+ }
+ }
+
+ /**
+ * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence's activity
+ * has fully finished (successfully).
+ */
+ private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info) {
+ final ActivityRecord launchedActivity = info.launchedActivity;
+
+ if (mLaunchObserver != null) {
+ mLaunchObserver.onActivityLaunchFinished(launchedActivity);
+ }
+ }
+
+ private static @ActivityMetricsLaunchObserver.Temperature int
+ convertTransitionTypeToLaunchObserverTemperature(int transitionType) {
+ switch (transitionType) {
+ case TYPE_TRANSITION_WARM_LAUNCH:
+ return ActivityMetricsLaunchObserver.TEMPERATURE_WARM;
+ case TYPE_TRANSITION_HOT_LAUNCH:
+ return ActivityMetricsLaunchObserver.TEMPERATURE_HOT;
+ case TYPE_TRANSITION_COLD_LAUNCH:
+ return ActivityMetricsLaunchObserver.TEMPERATURE_COLD;
+ default:
+ return -1;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a8b4a9d..1944184 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -46,6 +46,13 @@
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static com.android.server.am.ActivityStackProto.BOUNDS;
+import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
+import static com.android.server.am.ActivityStackProto.FULLSCREEN;
+import static com.android.server.am.ActivityStackProto.ID;
+import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityStackProto.TASKS;
import static com.android.server.wm.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
@@ -56,13 +63,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.am.ActivityStackProto.BOUNDS;
-import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
-import static com.android.server.am.ActivityStackProto.FULLSCREEN;
-import static com.android.server.am.ActivityStackProto.ID;
-import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
-import static com.android.server.am.ActivityStackProto.TASKS;
import static com.android.server.wm.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -513,14 +513,23 @@
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWindowingMode = getWindowingMode();
final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
- super.onConfigurationChanged(newParentConfig);
final ActivityDisplay display = getDisplay();
+
+ getBounds(mTmpRect2);
+ final boolean hasNewBounds = display != null && getWindowContainerController() != null
+ && getWindowContainerController().updateBoundsForConfigChange(
+ newParentConfig, getConfiguration(), mTmpRect2);
+
+ super.onConfigurationChanged(newParentConfig);
if (display == null) {
return;
}
if (prevWindowingMode != getWindowingMode()) {
display.onStackWindowingModeChanged(this);
}
+ if (hasNewBounds) {
+ resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
+ }
if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
// Since always on top is only on when the stack is freeform or pinned, the state
// can be toggled when the windowing mode changes. We must make sure the stack is
@@ -729,7 +738,7 @@
}
/** Adds the stack to specified display and calls WindowManager to do the same. */
- void reparent(ActivityDisplay activityDisplay, boolean onTop) {
+ void reparent(ActivityDisplay activityDisplay, boolean onTop, boolean displayRemoved) {
// TODO: We should probably resolve the windowing mode for the stack on the new display here
// so that it end up in a compatible mode in the new display. e.g. split-screen secondary.
removeFromDisplay();
@@ -738,6 +747,13 @@
mTmpRect2.setEmpty();
mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
+ if (!displayRemoved) {
+ postReparent();
+ }
+ }
+
+ /** Resume next focusable stack after reparenting to another display. */
+ void postReparent() {
adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
// Update visibility of activities before notifying WM. This way it won't try to resize
@@ -752,6 +768,12 @@
* @param bounds Updated bounds.
*/
private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) {
+ if (mDisplayId != activityDisplay.mDisplayId) {
+ // rotations are relative to the display, so pretend like our current rotation is
+ // the same as the new display so we don't try to rotate bounds.
+ getConfiguration().windowConfiguration.setRotation(
+ activityDisplay.getWindowConfiguration().getRotation());
+ }
mDisplayId = activityDisplay.mDisplayId;
setBounds(bounds);
onParentChanged();
@@ -810,10 +832,6 @@
outBounds.setEmpty();
}
- void getBoundsForNewConfiguration(Rect outBounds) {
- mWindowContainerController.getBoundsForNewConfiguration(outBounds);
- }
-
void positionChildWindowContainerAtTop(TaskRecord child) {
mWindowContainerController.positionChildAtTop(child.getWindowContainerController(),
true /* includingParents */);
@@ -1151,7 +1169,8 @@
}
final boolean isAttached() {
- return getParent() != null;
+ final ActivityDisplay display = getDisplay();
+ return display != null && !display.isRemoved();
}
/**
@@ -2679,136 +2698,129 @@
|| (lastFocusedStack.mLastPausedActivity != null
&& !lastFocusedStack.mLastPausedActivity.fullscreen));
- // The contained logic must be synchronized, since we are both changing the visibility
- // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will
- // ultimately cause the client code to schedule a layout. Since layouts retrieve the
- // current {@link Configuration}, we must ensure that the below code updates it before
- // the layout can occur.
- synchronized(mWindowManager.getWindowManagerLock()) {
- // This activity is now becoming visible.
- if (!next.visible || next.stopped || lastActivityTranslucent) {
+ // This activity is now becoming visible.
+ if (!next.visible || next.stopped || lastActivityTranslucent) {
+ next.setVisibility(true);
+ }
+
+ // schedule launch ticks to collect information about slow apps.
+ next.startLaunchTickingLocked();
+
+ ActivityRecord lastResumedActivity =
+ lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
+ final ActivityState lastState = next.getState();
+
+ mService.updateCpuStats();
+
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
+ + " (in existing)");
+
+ next.setState(RESUMED, "resumeTopActivityInnerLocked");
+
+ next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
+ true /* updateLru */, true /* activityChange */, true /* updateOomAdj */);
+ updateLRUListLocked(next);
+
+ // Have the window manager re-evaluate the orientation of
+ // the screen based on the new activity order.
+ boolean notUpdated = true;
+
+ if (isFocusedStackOnDisplay()) {
+ // We have special rotation behavior when here is some active activity that
+ // requests specific orientation or Keyguard is locked. Make sure all activity
+ // visibilities are set correctly as well as the transition is updated if needed
+ // to get the correct rotation behavior. Otherwise the following call to update
+ // the orientation may cause incorrect configurations delivered to client as a
+ // result of invisible window resize.
+ // TODO: Remove this once visibilities are set correctly immediately when
+ // starting an activity.
+ notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
+ true /* markFrozenIfConfigChanged */, false /* deferResume */);
+ }
+
+ if (notUpdated) {
+ // The configuration update wasn't able to keep the existing
+ // instance of the activity, and instead started a new one.
+ // We should be all done, but let's just make sure our activity
+ // is still at the top and schedule another run if something
+ // weird happened.
+ ActivityRecord nextNext = topRunningActivityLocked();
+ if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
+ "Activity config changed during resume: " + next
+ + ", new next: " + nextNext);
+ if (nextNext != next) {
+ // Do over!
+ mStackSupervisor.scheduleResumeTopActivities();
+ }
+ if (!next.visible || next.stopped) {
next.setVisibility(true);
}
+ next.completeResumeLocked();
+ if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+ return true;
+ }
- // schedule launch ticks to collect information about slow apps.
- next.startLaunchTickingLocked();
-
- ActivityRecord lastResumedActivity =
- lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
- final ActivityState lastState = next.getState();
-
- mService.updateCpuStats();
-
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
- + " (in existing)");
-
- next.setState(RESUMED, "resumeTopActivityInnerLocked");
-
- next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
- true /* updateLru */, true /* activityChange */, true /* updateOomAdj */);
- updateLRUListLocked(next);
-
- // Have the window manager re-evaluate the orientation of
- // the screen based on the new activity order.
- boolean notUpdated = true;
-
- if (isFocusedStackOnDisplay()) {
- // We have special rotation behavior when here is some active activity that
- // requests specific orientation or Keyguard is locked. Make sure all activity
- // visibilities are set correctly as well as the transition is updated if needed
- // to get the correct rotation behavior. Otherwise the following call to update
- // the orientation may cause incorrect configurations delivered to client as a
- // result of invisible window resize.
- // TODO: Remove this once visibilities are set correctly immediately when
- // starting an activity.
- notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
- true /* markFrozenIfConfigChanged */, false /* deferResume */);
+ try {
+ final ClientTransaction transaction =
+ ClientTransaction.obtain(next.app.getThread(), next.appToken);
+ // Deliver all pending results.
+ ArrayList<ResultInfo> a = next.results;
+ if (a != null) {
+ final int N = a.size();
+ if (!next.finishing && N > 0) {
+ if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
+ "Delivering results to " + next + ": " + a);
+ transaction.addCallback(ActivityResultItem.obtain(a));
+ }
}
- if (notUpdated) {
- // The configuration update wasn't able to keep the existing
- // instance of the activity, and instead started a new one.
- // We should be all done, but let's just make sure our activity
- // is still at the top and schedule another run if something
- // weird happened.
- ActivityRecord nextNext = topRunningActivityLocked();
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
- "Activity config changed during resume: " + next
- + ", new next: " + nextNext);
- if (nextNext != next) {
- // Do over!
- mStackSupervisor.scheduleResumeTopActivities();
- }
- if (!next.visible || next.stopped) {
- next.setVisibility(true);
- }
- next.completeResumeLocked();
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- return true;
+ if (next.newIntents != null) {
+ transaction.addCallback(NewIntentItem.obtain(next.newIntents,
+ false /* andPause */));
}
- try {
- final ClientTransaction transaction =
- ClientTransaction.obtain(next.app.getThread(), next.appToken);
- // Deliver all pending results.
- ArrayList<ResultInfo> a = next.results;
- if (a != null) {
- final int N = a.size();
- if (!next.finishing && N > 0) {
- if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
- "Delivering results to " + next + ": " + a);
- transaction.addCallback(ActivityResultItem.obtain(a));
- }
- }
+ // Well the app will no longer be stopped.
+ // Clear app token stopped state in window manager if needed.
+ next.notifyAppResumed(next.stopped);
- if (next.newIntents != null) {
- transaction.addCallback(NewIntentItem.obtain(next.newIntents,
- false /* andPause */));
- }
+ EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
+ System.identityHashCode(next), next.getTask().taskId,
+ next.shortComponentName);
- // Well the app will no longer be stopped.
- // Clear app token stopped state in window manager if needed.
- next.notifyAppResumed(next.stopped);
+ next.sleeping = false;
+ mService.getAppWarningsLocked().onResumeActivity(next);
+ next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
+ next.clearOptionsLocked();
+ transaction.setLifecycleStateRequest(
+ ResumeActivityItem.obtain(next.app.getReportedProcState(),
+ getDisplay().getWindowContainerController()
+ .isNextTransitionForward()));
+ mService.getLifecycleManager().scheduleTransaction(transaction);
- EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
- System.identityHashCode(next), next.getTask().taskId,
- next.shortComponentName);
+ if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
+ + next);
+ } catch (Exception e) {
+ // Whoops, need to restart this activity!
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
+ + lastState + ": " + next);
+ next.setState(lastState, "resumeTopActivityInnerLocked");
- next.sleeping = false;
- mService.getAppWarningsLocked().onResumeActivity(next);
- next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
- next.clearOptionsLocked();
- transaction.setLifecycleStateRequest(
- ResumeActivityItem.obtain(next.app.getReportedProcState(),
- getDisplay().getWindowContainerController()
- .isNextTransitionForward()));
- mService.getLifecycleManager().scheduleTransaction(transaction);
-
- if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
- + next);
- } catch (Exception e) {
- // Whoops, need to restart this activity!
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
- + lastState + ": " + next);
- next.setState(lastState, "resumeTopActivityInnerLocked");
-
- // lastResumedActivity being non-null implies there is a lastStack present.
- if (lastResumedActivity != null) {
- lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
- }
-
- Slog.i(TAG, "Restarting because process died: " + next);
- if (!next.hasBeenLaunched) {
- next.hasBeenLaunched = true;
- } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null
- && lastFocusedStack.isTopStackOnDisplay()) {
- next.showStartingWindow(null /* prev */, false /* newTask */,
- false /* taskSwitch */);
- }
- mStackSupervisor.startSpecificActivityLocked(next, true, false);
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- return true;
+ // lastResumedActivity being non-null implies there is a lastStack present.
+ if (lastResumedActivity != null) {
+ lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
}
+
+ Slog.i(TAG, "Restarting because process died: " + next);
+ if (!next.hasBeenLaunched) {
+ next.hasBeenLaunched = true;
+ } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null
+ && lastFocusedStack.isTopStackOnDisplay()) {
+ next.showStartingWindow(null /* prev */, false /* newTask */,
+ false /* taskSwitch */);
+ }
+ mStackSupervisor.startSpecificActivityLocked(next, true, false);
+ if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+ return true;
}
// From this point on, if something goes wrong there is no way
@@ -4841,35 +4853,33 @@
mTmpBounds.clear();
mTmpInsetBounds.clear();
- synchronized (mWindowManager.getWindowManagerLock()) {
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
- if (task.isResizeable()) {
- if (inFreeformWindowingMode()) {
- // TODO(b/71028874): Can be removed since each freeform task is its own
- // stack.
- // For freeform stack we don't adjust the size of the tasks to match that
- // of the stack, but we do try to make sure the tasks are still contained
- // with the bounds of the stack.
- if (task.getOverrideBounds() != null) {
- mTmpRect2.set(task.getOverrideBounds());
- fitWithinBounds(mTmpRect2, bounds);
- task.updateOverrideConfiguration(mTmpRect2);
- }
- } else {
- task.updateOverrideConfiguration(taskBounds, insetBounds);
+ for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
+ final TaskRecord task = mTaskHistory.get(i);
+ if (task.isResizeable()) {
+ if (inFreeformWindowingMode()) {
+ // TODO(b/71028874): Can be removed since each freeform task is its own
+ // stack.
+ // For freeform stack we don't adjust the size of the tasks to match that
+ // of the stack, but we do try to make sure the tasks are still contained
+ // with the bounds of the stack.
+ if (task.getOverrideBounds() != null) {
+ mTmpRect2.set(task.getOverrideBounds());
+ fitWithinBounds(mTmpRect2, bounds);
+ task.updateOverrideConfiguration(mTmpRect2);
}
- }
-
- mTmpBounds.put(task.taskId, task.getOverrideBounds());
- if (tempTaskInsetBounds != null) {
- mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
+ } else {
+ task.updateOverrideConfiguration(taskBounds, insetBounds);
}
}
- mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
- setBounds(bounds);
+ mTmpBounds.put(task.taskId, task.getOverrideBounds());
+ if (tempTaskInsetBounds != null) {
+ mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
+ }
}
+
+ mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
+ setBounds(bounds);
}
void onPipAnimationEndResize() {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 77b331e..6034f81 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -59,6 +59,13 @@
import static android.view.Display.TYPE_VIRTUAL;
import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
+import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
+import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
+import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
+import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
+import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
@@ -67,13 +74,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
-import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
-import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
-import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
-import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
-import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -789,7 +789,15 @@
return startHomeOnDisplay(mCurrentUser, myReason, displayId);
}
- boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId) {
+ /**
+ * Check if home activity start should be allowed on a display.
+ * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
+ * @param displayId The id of the target display.
+ * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
+ * @return {@code true} if allow to launch, {@code false} otherwise.
+ */
+ boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
+ boolean allowInstrumenting) {
if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mService.mTopAction == null) {
// We are running in factory test mode, but unable to find the factory test app, so
@@ -799,7 +807,7 @@
final WindowProcessController app =
mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
- if (app != null && app.isInstrumenting()) {
+ if (!allowInstrumenting && app != null && app.isInstrumenting()) {
// Don't do this if the home app is currently being instrumented.
return false;
}
@@ -1049,20 +1057,26 @@
boolean allResumedActivitiesIdle() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ // TODO(b/117135575): Check resumed activities on all visible stacks.
final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- // We cannot only check the top stack on each display since there might have
- // always-on-top stacks (e.g. pinned stack).
- final ActivityStack stack = display.getChildAt(stackNdx);
- if (stack.numActivities() == 0) {
- continue;
+ if (display.isSleeping()) {
+ // No resumed activities while display is sleeping.
+ continue;
+ }
+
+ // If the focused stack is not null or not empty, there should have some activities
+ // resuming or resumed. Make sure these activities are idle.
+ final ActivityStack stack = display.getFocusedStack();
+ if (stack == null || stack.numActivities() == 0) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity == null || !resumedActivity.idle) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ + stack.mStackId + " " + resumedActivity + " not idle");
}
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity != null && !resumedActivity.idle) {
- if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
- + stack.mStackId + " " + resumedActivity + " not idle");
- return false;
- }
+ return false;
}
}
// Send launch end powerhint when idle
@@ -1976,8 +1990,9 @@
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
- // Make sure we can finish booting when all resumed activities are idle.
- if ((!mService.isBooted() && allResumedActivitiesIdle()) || fromTimeout) {
+ // Check if able to finish booting when device is booting and all resumed activities
+ // are idle.
+ if ((mService.isBooting() && allResumedActivitiesIdle()) || fromTimeout) {
booting = checkFinishBootingLocked();
}
@@ -2050,7 +2065,7 @@
}
}
- mService.mAmInternal.trimApplications();
+ mService.mH.post(() -> mService.mAmInternal.trimApplications());
//dump();
//mWindowManager.dump();
@@ -2611,8 +2626,7 @@
}
ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
- getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
- return null;
+ return getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
}
void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
@@ -3172,7 +3186,7 @@
+ " to its current displayId=" + displayId);
}
- stack.reparent(activityDisplay, onTop);
+ stack.reparent(activityDisplay, onTop, false /* displayRemoved */);
// TODO(multi-display): resize stacks properly if moved from split-screen.
}
@@ -4136,7 +4150,12 @@
if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
synchronized (mService.mGlobalLock) {
getActivityDisplayOrCreateLocked(displayId);
- startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
+ // Do not start home before booting, or it may accidentally finish booting before it
+ // starts. Instead, we expect home activities to be launched when the system is ready
+ // (ActivityManagerService#systemReady).
+ if (mService.isBooted() || mService.isBooting()) {
+ startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
+ }
}
}
@@ -4234,7 +4253,7 @@
return false;
}
- if (!canStartHomeOnDisplay(aInfo, displayId)) {
+ if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) {
return false;
}
@@ -4562,14 +4581,14 @@
/**
* Begin deferring resume to avoid duplicate resumes in one pass.
*/
- private void beginDeferResume() {
+ void beginDeferResume() {
mDeferResumeCount++;
}
/**
* End deferring resume and determine if resume can be called.
*/
- private void endDeferResume() {
+ void endDeferResume() {
mDeferResumeCount--;
}
@@ -4745,7 +4764,7 @@
final ActivityRecord targetActivity = task.getTopActivity();
sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity);
- mActivityMetricsLogger.notifyActivityLaunching();
+ mActivityMetricsLogger.notifyActivityLaunching(task.intent);
try {
mService.moveTaskToFrontLocked(task.taskId, 0, options,
true /* fromRecents */);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e43a79a..83db8de 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -53,6 +53,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -72,7 +73,6 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
-import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
@@ -114,9 +114,9 @@
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.EventLogTags;
import com.android.server.am.PendingIntentRecord;
+import com.android.server.pm.InstantAppResolver;
import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.wm.LaunchParamsController.LaunchParams;
-import com.android.server.pm.InstantAppResolver;
import java.io.PrintWriter;
import java.text.DateFormat;
@@ -996,7 +996,7 @@
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
+ mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
boolean componentSpecified = intent.getComponent() != null;
final int realCallingPid = Binder.getCallingPid();
@@ -1284,8 +1284,8 @@
// Do not start home activity if it cannot be launched on preferred display. We are not
// doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might
// fallback to launch on other displays.
- if (r.isActivityTypeHome()
- && !mSupervisor.canStartHomeOnDisplay(r.info, mPreferredDisplayId)) {
+ if (r.isActivityTypeHome() && !mSupervisor.canStartHomeOnDisplay(r.info,
+ mPreferredDisplayId, true /* allowInstrumenting */)) {
Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
return START_CANCELED;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index dcc7bc5..d665592 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -22,6 +22,7 @@
import android.app.AppProtoEnums;
import android.app.IActivityManager;
import android.app.IApplicationThread;
+import android.app.ProfilerInfo;
import android.content.ComponentName;
import android.content.IIntentSender;
import android.content.Intent;
@@ -468,4 +469,8 @@
public abstract void clearLockedTasks(String reason);
public abstract void updateUserConfiguration();
public abstract boolean canShowErrorDialogs();
+
+ public abstract void setProfileApp(String profileApp);
+ public abstract void setProfileProc(WindowProcessController wpc);
+ public abstract void setProfilerInfo(ProfilerInfo profilerInfo);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3ede8bc8..f55bcce 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -56,7 +56,6 @@
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
@@ -114,17 +113,17 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
-import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
-import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
-import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
-import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
+import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
+import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import android.Manifest;
import android.annotation.NonNull;
@@ -190,7 +189,6 @@
import android.os.IBinder;
import android.os.IUserManager;
import android.os.LocaleList;
-import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
@@ -247,9 +245,11 @@
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
+import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
+import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
@@ -347,7 +347,7 @@
IntentFirewall mIntentFirewall;
/* Global service lock used by the package the owns this service. */
- Object mGlobalLock;
+ final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
ActivityStackSupervisor mStackSupervisor;
WindowManagerService mWindowManager;
private UserManagerService mUserManager;
@@ -466,6 +466,11 @@
String mTopAction = Intent.ACTION_MAIN;
String mTopData;
+ /** Profiling app information. */
+ String mProfileApp = null;
+ WindowProcessController mProfileProc = null;
+ ProfilerInfo mProfilerInfo = null;
+
/**
* Dump of the activity state at the time of the last ANR. Cleared after
* {@link WindowManagerService#LAST_ANR_LIFETIME_DURATION_MSECS}
@@ -652,8 +657,6 @@
ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
final boolean supportsMultiDisplay = mContext.getPackageManager()
.hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
- final boolean alwaysFinishActivities =
- Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
final boolean forceResizable = Settings.Global.getInt(
resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
@@ -716,11 +719,13 @@
}
}
- // TODO: Will be converted to WM lock once transition is complete.
- public void setActivityManagerService(Object globalLock, Looper looper,
- IntentFirewall intentFirewall, PendingIntentController intentController) {
- mGlobalLock = globalLock;
- mH = new H(looper);
+ public WindowManagerGlobalLock getGlobalLock() {
+ return mGlobalLock;
+ }
+
+ public void setActivityManagerService(IntentFirewall intentFirewall,
+ PendingIntentController intentController) {
+ mH = new H();
mUiHandler = new UiHandler();
mIntentFirewall = intentFirewall;
final File systemDir = SystemServiceManager.ensureSystemDir();
@@ -2885,7 +2890,7 @@
@Override
public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
- int secondaryDisplayShowing) {
+ int[] secondaryDisplaysShowing) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -2903,7 +2908,7 @@
}
try {
mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing,
- secondaryDisplayShowing);
+ secondaryDisplaysShowing);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -4873,21 +4878,6 @@
mH.sendMessage(msg);
}
}
-
- // Update the configuration with WM first and check if any of the stacks need to be resized
- // due to the configuration change. If so, resize the stacks now and do any relaunches if
- // necessary. This way we don't need to relaunch again afterwards in
- // ensureActivityConfiguration().
- if (mWindowManager != null) {
- final int[] resizedStacks =
- mWindowManager.setNewDisplayOverrideConfiguration(mTempConfig, displayId);
- if (resizedStacks != null) {
- for (int stackId : resizedStacks) {
- resizeStackWithBoundsFromWindowManager(stackId, deferResume);
- }
- }
- }
-
return changes;
}
@@ -5277,28 +5267,6 @@
return "focused app: " + packageName;
}
- /** Helper method that requests bounds from WM and applies them to stack. */
- private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
- final Rect newStackBounds = new Rect();
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
-
- // TODO(b/71548119): Revert CL introducing below once cause of mismatch is found.
- if (stack == null) {
- final StringWriter writer = new StringWriter();
- final PrintWriter printWriter = new PrintWriter(writer);
- mStackSupervisor.dumpDisplays(printWriter);
- printWriter.flush();
-
- Log.wtf(TAG, "stack not found:" + stackId + " displays:" + writer);
- }
-
- stack.getBoundsForNewConfiguration(newStackBounds);
- mStackSupervisor.resizeStackLocked(
- stack, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
- null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
- false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
- }
-
/** Applies latest configuration and/or visibility updates if needed. */
private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
boolean kept = true;
@@ -5487,8 +5455,8 @@
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_SUPERVISOR_STACK_MSG = 200;
- public H(Looper looper) {
- super(looper, null, true);
+ public H() {
+ super(DisplayThread.get().getLooper());
}
@Override
@@ -5506,7 +5474,7 @@
static final int DISMISS_DIALOG_UI_MSG = 1;
public UiHandler() {
- super(com.android.server.UiThread.get().getLooper(), null, true);
+ super(UiThread.get().getLooper(), null, true);
}
@Override
@@ -6296,8 +6264,11 @@
FLAG_ACTIVITY_TASK_ON_HOME);
ActivityOptions activityOptions = options != null
? new ActivityOptions(options) : ActivityOptions.makeBasic();
- activityOptions.setLaunchTaskId(
- mStackSupervisor.getDefaultDisplayHomeActivity().getTask().taskId);
+ final ActivityRecord homeActivity =
+ mStackSupervisor.getDefaultDisplayHomeActivity();
+ if (homeActivity != null) {
+ activityOptions.setLaunchTaskId(homeActivity.getTask().taskId);
+ }
mContext.startActivityAsUser(intent, activityOptions.toBundle(),
UserHandle.CURRENT);
} finally {
@@ -6762,5 +6733,26 @@
&& mAmInternal.getCurrentUser().isDemo());
}
}
+
+ @Override
+ public void setProfileApp(String profileApp) {
+ synchronized (mGlobalLock) {
+ mProfileApp = profileApp;
+ }
+ }
+
+ @Override
+ public void setProfileProc(WindowProcessController wpc) {
+ synchronized (mGlobalLock) {
+ mProfileProc = wpc;
+ }
+ }
+
+ @Override
+ public void setProfilerInfo(ProfilerInfo profilerInfo) {
+ synchronized (mGlobalLock) {
+ mProfilerInfo = profilerInfo;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 584c1e4..830c2e6 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -18,6 +18,7 @@
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_NONE;
import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
import static android.app.ActivityOptions.ANIM_SCALE_UP;
@@ -27,9 +28,9 @@
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static android.view.WindowManager.TRANSIT_UNSET;
+
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -862,6 +863,8 @@
displayContent.mAppTransition.overridePendingAppTransitionRemote(
pendingOptions.getRemoteAnimationAdapter());
break;
+ case ANIM_NONE:
+ break;
default:
Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
break;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 348b2af..e20793e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -157,8 +157,8 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
-import android.view.WindowManagerPolicyConstants.PointerEventListener;
import android.view.WindowManager;
+import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
@@ -1153,14 +1153,19 @@
}
/**
- * Update rotation of the display with an option to force the update.
+ * Update rotation of the DisplayContent with an option to force the update. This updates
+ * the container's perception of rotation and, depending on the top activities, will freeze
+ * the screen or start seamless rotation. The display itself gets rotated in
+ * {@link #applyRotationLocked} during {@link WindowManagerService#sendNewConfiguration}.
+ *
* @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
* orientation because we're waiting for some rotation to finish or display
* to unfreeze, which results in configuration of the previously visible
* activity being applied to a newly visible one. Forcing the rotation
* update allows to workaround this issue.
* @return {@code true} if the rotation has been changed. In this case YOU MUST CALL
- * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
+ * {@link WindowManagerService#sendNewConfiguration(int)} TO COMPLETE THE ROTATION AND
+ * UNFREEZE THE SCREEN.
*/
boolean updateRotationUnchecked(boolean forceUpdate) {
ScreenRotationAnimation screenRotationAnimation;
@@ -1258,7 +1263,7 @@
mService.mWaitingForConfig = true;
}
- setRotation(rotation);
+ mRotation = rotation;
mAltOrientation = altOrientation;
mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
@@ -1272,18 +1277,29 @@
if (!rotateSeamlessly) {
mService.startFreezingDisplayLocked(anim[0], anim[1], this);
// startFreezingDisplayLocked can reset the ScreenRotationAnimation.
- screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
- mDisplayId);
} else {
// The screen rotation animation uses a screenshot to freeze the screen
// while windows resize underneath.
// When we are rotating seamlessly, we allow the elements to transition
// to their rotated state independently and without a freeze required.
- screenRotationAnimation = null;
-
mService.startSeamlessRotation();
}
+ return true;
+ }
+
+ /**
+ * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked}
+ * (if it returned {@code true}) to actually finish the rotation.
+ *
+ * @param oldRotation the rotation we are coming from.
+ * @param rotation the rotation to apply.
+ */
+ void applyRotationLocked(final int oldRotation, final int rotation) {
+ mDisplayRotation.setRotation(rotation);
+ final boolean rotateSeamlessly = mService.isRotatingSeamlessly();
+ ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly
+ ? null : mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
// We need to update our screen size information to match the new rotation. If the rotation
// has actually changed then this method will return true and, according to the comment at
// the top of the method, the caller is obligated to call computeNewConfigurationLocked().
@@ -1344,8 +1360,6 @@
&& isDefaultDisplay) {
mService.mAccessibilityController.onRotationChangedLocked(this);
}
-
- return true;
}
void configureDisplayPolicy() {
@@ -1455,7 +1469,6 @@
mCompatDisplayMetrics);
}
- updateBounds();
return mDisplayInfo;
}
@@ -1489,11 +1502,14 @@
*/
void computeScreenConfiguration(Configuration config) {
final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode);
+ calculateBounds(displayInfo, mTmpBounds);
+ config.windowConfiguration.setBounds(mTmpBounds);
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
config.windowConfiguration.setWindowingMode(getWindowingMode());
+ config.windowConfiguration.setRotation(displayInfo.rotation);
final float density = mDisplayMetrics.density;
config.screenWidthDp =
@@ -1525,7 +1541,7 @@
config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw,
- dh, mDisplayId);
+ dh, displayInfo.displayCutout, mDisplayId);
config.densityDpi = displayInfo.logicalDensityDpi;
config.colorMode =
@@ -1602,7 +1618,7 @@
}
private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
- int displayId) {
+ DisplayCutout displayCutout, int displayId) {
mTmpDisplayMetrics.setTo(mDisplayMetrics);
final DisplayMetrics tmpDm = mTmpDisplayMetrics;
final int unrotDw, unrotDh;
@@ -1614,22 +1630,22 @@
unrotDh = dh;
}
int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
- displayId);
+ displayCutout, displayId);
sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
- displayId);
+ displayCutout, displayId);
sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
- displayId);
+ displayCutout, displayId);
sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
- displayId);
+ displayCutout, displayId);
return sw;
}
private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
- DisplayMetrics dm, int dw, int dh, int displayId) {
+ DisplayMetrics dm, int dw, int dh, DisplayCutout displayCutout, int displayId) {
dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
- displayId, mDisplayInfo.displayCutout);
+ displayId, displayCutout);
dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
- uiMode, displayId, mDisplayInfo.displayCutout);
+ uiMode, displayId, displayCutout);
float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
if (curSize == 0 || size < curSize) {
@@ -1667,24 +1683,24 @@
unrotDw);
int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
- displayId);
+ displayInfo.displayCutout, displayId);
sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
- displayId);
+ displayInfo.displayCutout, displayId);
sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
- displayId);
+ displayInfo.displayCutout, displayId);
sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
- displayId);
+ displayInfo.displayCutout, displayId);
outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
outConfig.screenLayout = sl;
}
private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
- int uiMode, int displayId) {
+ int uiMode, DisplayCutout displayCutout, int displayId) {
// Get the app screen size at this rotation.
int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId,
- mDisplayInfo.displayCutout);
+ displayCutout);
int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId,
- mDisplayInfo.displayCutout);
+ displayCutout);
// Compute the screen layout size class for this rotation.
int longSize = w;
@@ -1858,11 +1874,26 @@
public void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig);
+ // If there was no pinned stack, we still need to notify the controller of the display info
+ // update as a result of the config change.
+ if (mPinnedStackControllerLocked != null && !hasPinnedStack()) {
+ mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
+ }
+
// The display size information is heavily dependent on the resources in the current
// configuration, so we need to reconfigure it every time the configuration changes.
// See {@link #configureDisplayPolicy}...sigh...
mService.reconfigureDisplayLocked(this);
+ }
+
+ /**
+ * Updates the resources used by docked/pinned controllers. This needs to be called at the
+ * beginning of a configuration update cascade since the metrics from these resources are used
+ * for bounds calculations. Since ActivityDisplay initiates the configuration update, this
+ * should be called from there instead of DisplayContent's onConfigurationChanged.
+ */
+ void preOnConfigurationChanged() {
final DockedStackDividerController dividerController = getDockedDividerController();
if (dividerController != null) {
@@ -1876,26 +1907,6 @@
}
}
- /**
- * Callback used to trigger bounds update after configuration change and get ids of stacks whose
- * bounds were updated.
- */
- void updateStackBoundsAfterConfigChange(@NonNull List<TaskStack> changedStackList) {
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
- if (stack.updateBoundsAfterConfigChange()) {
- changedStackList.add(stack);
- }
- }
-
- // If there was no pinned stack, we still need to notify the controller of the display info
- // update as a result of the config change. We do this here to consolidate the flow between
- // changes when there is and is not a stack.
- if (!hasPinnedStack()) {
- mPinnedStackControllerLocked.onDisplayInfoChanged();
- }
- }
-
@Override
boolean fillsParent() {
return true;
@@ -2494,11 +2505,15 @@
void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
getBounds(mTmpRect, newRotation);
+ rotateBounds(mTmpRect, oldRotation, newRotation, bounds);
+ }
+ void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) {
// Compute a transform matrix to undo the coordinate space transformation,
// and present the window at the same physical position it previously occupied.
final int deltaRotation = deltaRotation(newRotation, oldRotation);
- createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
+ createRotationMatrix(
+ deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix);
mTmpRectF.set(bounds);
mTmpMatrix.mapRect(mTmpRectF);
@@ -3426,27 +3441,27 @@
}
private void updateBounds() {
- calculateBounds(mTmpBounds);
+ calculateBounds(mDisplayInfo, mTmpBounds);
setBounds(mTmpBounds);
}
// Determines the current display bounds based on the current state
- private void calculateBounds(Rect out) {
+ private void calculateBounds(DisplayInfo displayInfo, Rect out) {
// Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
- final int orientation = mDisplayInfo.rotation;
- boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+ final int rotation = displayInfo.rotation;
+ boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
- int width = mDisplayInfo.logicalWidth;
+ int width = displayInfo.logicalWidth;
int left = (physWidth - width) / 2;
- int height = mDisplayInfo.logicalHeight;
+ int height = displayInfo.logicalHeight;
int top = (physHeight - height) / 2;
out.set(left, top, left + width, top + height);
}
@Override
public void getBounds(Rect out) {
- calculateBounds(out);
+ calculateBounds(mDisplayInfo, out);
}
private void getBounds(Rect out, int orientation) {
@@ -4651,4 +4666,16 @@
pendingLayoutChanges |= changes;
}
+
+ /**
+ * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ */
+ boolean supportsSystemDecorations() {
+ // TODO(b/114338689): Read the setting from DisplaySettings.
+ return mDisplay.supportsSystemDecorations()
+ // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
+ // (b/114338689) whenever vr 2d display id is set.
+ || mDisplayId == mService.mVr2dDisplayId
+ || mService.mForceDesktopModeOnExternalDisplays;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 44956ab..624fbc7 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -185,15 +185,12 @@
}
// No record is present so use default windowing mode policy.
if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- if (displayId == Display.DEFAULT_DISPLAY) {
- windowingMode = (mService.mIsPc && mService.mSupportsFreeformWindowManagement)
- ? WindowConfiguration.WINDOWING_MODE_FREEFORM
- : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
- } else {
- windowingMode = mService.mSupportsFreeformWindowManagement
- ? WindowConfiguration.WINDOWING_MODE_FREEFORM
- : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
- }
+ final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
+ && displayId != Display.DEFAULT_DISPLAY;
+ windowingMode = mService.mSupportsFreeformWindowManagement
+ && (mService.mIsPc || forceDesktopMode)
+ ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+ : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
}
return windowingMode;
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index f772216..864f7e1 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -88,9 +88,34 @@
@Override
public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
- // TODO: The container receives override configuration changes through other means. enabling
- // callbacks through the controller causes layout issues. Investigate consolidating
- // override configuration propagation to just here.
+ synchronized (mGlobalLock) {
+ if (mContainer != null) {
+ mContainer.mService.setNewDisplayOverrideConfiguration(overrideConfiguration,
+ mContainer);
+ }
+ }
+ }
+
+ /**
+ * Updates the docked/pinned controller resources to the current system context.
+ */
+ public void preOnConfigurationChanged() {
+ synchronized (mGlobalLock) {
+ if (mContainer != null) {
+ mContainer.preOnConfigurationChanged();
+ }
+ }
+ }
+
+ /**
+ * @see DisplayContent#applyRotationLocked(int, int)
+ */
+ public void applyRotation(int oldRotation, int newRotation) {
+ synchronized (mGlobalLock) {
+ if (mContainer != null) {
+ mContainer.applyRotationLocked(oldRotation, newRotation);
+ }
+ }
}
public int getDisplayId() {
@@ -314,6 +339,17 @@
|| transit == TRANSIT_TASK_TO_FRONT;
}
+ /**
+ * Checks if system decorations should be shown on this display.
+ *
+ * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+ */
+ public boolean supportsSystemDecorations() {
+ synchronized (mGlobalLock) {
+ return mContainer.supportsSystemDecorations();
+ }
+ }
+
@Override
public String toString() {
return "{DisplayWindowController displayId=" + mDisplayId + "}";
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 985ce06..6daf2f5 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -171,7 +171,7 @@
final int orientation = mTmpRect2.width() <= mTmpRect2.height()
? ORIENTATION_PORTRAIT
: ORIENTATION_LANDSCAPE;
- final int dockSide = getDockSide(mTmpRect, mTmpRect2, orientation);
+ final int dockSide = getDockSide(mTmpRect, mTmpRect2, orientation, rotation);
final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
getContentWidth());
@@ -202,7 +202,7 @@
* @param orientation the origination of device
* @return current docked side
*/
- int getDockSide(Rect bounds, Rect displayRect, int orientation) {
+ int getDockSide(Rect bounds, Rect displayRect, int orientation, int rotation) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Portrait mode, docked either at the top or the bottom.
final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
@@ -211,7 +211,8 @@
} else if (diff < 0) {
return DOCKED_BOTTOM;
}
- return canPrimaryStackDockTo(DOCKED_TOP) ? DOCKED_TOP : DOCKED_BOTTOM;
+ return canPrimaryStackDockTo(DOCKED_TOP, displayRect, rotation)
+ ? DOCKED_TOP : DOCKED_BOTTOM;
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Landscape mode, docked either on the left or on the right.
final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
@@ -220,7 +221,8 @@
} else if (diff < 0) {
return DOCKED_RIGHT;
}
- return canPrimaryStackDockTo(DOCKED_LEFT) ? DOCKED_LEFT : DOCKED_RIGHT;
+ return canPrimaryStackDockTo(DOCKED_LEFT, displayRect, rotation)
+ ? DOCKED_LEFT : DOCKED_RIGHT;
}
return DOCKED_INVALID;
}
@@ -463,10 +465,9 @@
* @param dockSide the side to see if it is valid
* @return true if the side provided is valid
*/
- boolean canPrimaryStackDockTo(int dockSide) {
- final DisplayInfo di = mDisplayContent.getDisplayInfo();
- return mService.mPolicy.isDockSideAllowed(dockSide, mOriginalDockedSide, di.logicalWidth,
- di.logicalHeight, di.rotation);
+ boolean canPrimaryStackDockTo(int dockSide, Rect parentRect, int rotation) {
+ return mService.mPolicy.isDockSideAllowed(dockSide, mOriginalDockedSide,
+ parentRect.width(), parentRect.height(), rotation);
}
void notifyDockedStackExistsChanged(boolean exists) {
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 3560635..c91af73 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -18,7 +18,6 @@
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
@@ -30,13 +29,13 @@
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
-import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
+import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import android.os.IBinder;
import android.os.RemoteException;
@@ -50,6 +49,7 @@
import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import java.io.PrintWriter;
+import java.util.Arrays;
/**
* Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
@@ -67,10 +67,9 @@
private boolean mAodShowing;
private boolean mKeyguardGoingAway;
private boolean mDismissalRequested;
+ private int[] mSecondaryDisplayIdsShowing;
private int mBeforeUnoccludeTransit;
private int mVisibilityTransactionDepth;
- // TODO(b/111955725): Support multiple external displays
- private int mSecondaryDisplayShowing = INVALID_DISPLAY;
private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
private final ActivityTaskManagerService mService;
@@ -90,7 +89,9 @@
*/
boolean isKeyguardOrAodShowing(int displayId) {
return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
- && !isDisplayOccluded(displayId);
+ && (displayId == DEFAULT_DISPLAY
+ ? !isDisplayOccluded(DEFAULT_DISPLAY)
+ : isShowingOnSecondaryDisplay(displayId));
}
/**
@@ -98,7 +99,10 @@
* display, false otherwise
*/
boolean isKeyguardShowing(int displayId) {
- return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
+ return mKeyguardShowing && !mKeyguardGoingAway
+ && (displayId == DEFAULT_DISPLAY
+ ? !isDisplayOccluded(DEFAULT_DISPLAY)
+ : isShowingOnSecondaryDisplay(displayId));
}
/**
@@ -120,16 +124,17 @@
* Update the Keyguard showing state.
*/
void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
- int secondaryDisplayShowing) {
+ int[] secondaryDisplaysShowing) {
boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
// If keyguard is going away, but SystemUI aborted the transition, need to reset state.
showingChanged |= mKeyguardGoingAway && keyguardShowing;
- if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
+ if (!showingChanged && Arrays.equals(secondaryDisplaysShowing,
+ mSecondaryDisplayIdsShowing)) {
return;
}
mKeyguardShowing = keyguardShowing;
mAodShowing = aodShowing;
- mSecondaryDisplayShowing = secondaryDisplayShowing;
+ mSecondaryDisplayIdsShowing = secondaryDisplaysShowing;
mWindowManager.setAodShowing(aodShowing);
if (showingChanged) {
dismissDockedStackIfNeeded();
@@ -145,6 +150,14 @@
updateKeyguardSleepToken();
}
+ private boolean isShowingOnSecondaryDisplay(int displayId) {
+ if (mSecondaryDisplayIdsShowing == null) return false;
+ for (int showingId : mSecondaryDisplayIdsShowing) {
+ if (displayId == showingId) return true;
+ }
+ return false;
+ }
+
/**
* Called when Keyguard is going away.
*
@@ -386,16 +399,18 @@
}
private KeyguardDisplayState getDisplay(int displayId) {
- if (mDisplayStates.get(displayId) == null) {
- mDisplayStates.append(displayId,
- new KeyguardDisplayState(mService, displayId));
+ KeyguardDisplayState state = mDisplayStates.get(displayId);
+ if (state == null) {
+ state = new KeyguardDisplayState(mService, displayId);
+ mDisplayStates.append(displayId, state);
}
- return mDisplayStates.get(displayId);
+ return state;
}
void onDisplayRemoved(int displayId) {
- if (mDisplayStates.get(displayId) != null) {
- mDisplayStates.get(displayId).onRemoved();
+ final KeyguardDisplayState state = mDisplayStates.get(displayId);
+ if (state != null) {
+ state.onRemoved();
mDisplayStates.remove(displayId);
}
}
@@ -456,7 +471,8 @@
mOccluded |= controller.mWindowManager.isShowingDream();
}
- // TODO(b/113840485): Handle app transition for individual display.
+ // TODO(b/113840485): Handle app transition for individual display, and apply occluded
+ // state change to secondary displays.
// For now, only default display can change occluded.
if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
controller.handleOccludedChanged();
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 405aaab..d21f67d 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -314,8 +314,8 @@
* onTaskStackBoundsChanged() to be called. But we still should update our known display info
* with the new state so that we can update SystemUI.
*/
- synchronized void onDisplayInfoChanged() {
- mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
+ synchronized void onDisplayInfoChanged(DisplayInfo displayInfo) {
+ mDisplayInfo.copyFrom(displayInfo);
notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 7a1ebf2..067b01a 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -42,7 +42,6 @@
import android.util.Slog;
import android.view.IRecentsAnimationRunner;
-import com.android.server.wm.AssistDataReceiverProxy;
import com.android.server.am.AssistDataRequester;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
@@ -122,9 +121,9 @@
targetActivity);
}
- mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
+ mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
- mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true);
+ mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true));
mWindowManager.deferSurfaceLayout();
try {
@@ -234,7 +233,8 @@
mStackSupervisor.sendPowerHintForLaunchEndIfNeeded();
}
- mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false);
+ mService.mH.post(
+ () -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false));
mWindowManager.inSurfaceTransaction(() -> {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 67fe5c4..8c0c073 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -54,6 +54,7 @@
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
import android.annotation.CallSuper;
+import android.annotation.NonNull;
import android.content.res.Configuration;
import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
@@ -75,12 +76,10 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
-import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.List;
import java.util.function.Consumer;
/** Root {@link WindowContainer} for the device. */
@@ -115,9 +114,6 @@
boolean mOrientationChangeComplete = true;
boolean mWallpaperActionPending = false;
- private final ArrayList<TaskStack> mTmpStackList = new ArrayList();
- private final ArrayList<Integer> mTmpStackIds = new ArrayList<>();
-
final WallpaperController mWallpaperController;
private final Handler mHandler;
@@ -313,57 +309,33 @@
}
/**
- * Set new display override config and return array of ids of stacks that were changed during
- * update. If called for the default display, global configuration will also be updated. Stacks
- * that are marked for deferred removal are excluded from the returned array.
+ * Set new display override config. If called for the default display, global configuration
+ * will also be updated.
*/
- int[] setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId) {
- final DisplayContent displayContent = getDisplayContent(displayId);
- if (displayContent == null) {
- throw new IllegalArgumentException("Display not found for id: " + displayId);
- }
+ void setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration,
+ @NonNull DisplayContent displayContent) {
final Configuration currentConfig = displayContent.getOverrideConfiguration();
final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
if (!configChanged) {
- return null;
+ return;
}
displayContent.onOverrideConfigurationChanged(newConfiguration);
- mTmpStackList.clear();
- if (displayId == DEFAULT_DISPLAY) {
+ if (displayContent.getDisplayId() == DEFAULT_DISPLAY) {
// Override configuration of the default display duplicates global config. In this case
// we also want to update the global config.
- setGlobalConfigurationIfNeeded(newConfiguration, mTmpStackList);
- } else {
- updateStackBoundsAfterConfigChange(displayId, mTmpStackList);
+ setGlobalConfigurationIfNeeded(newConfiguration);
}
-
- mTmpStackIds.clear();
- final int stackCount = mTmpStackList.size();
-
- for (int i = 0; i < stackCount; ++i) {
- final TaskStack stack = mTmpStackList.get(i);
-
- // We only include stacks that are not marked for removal as they do not exist outside
- // of WindowManager at this point.
- if (!stack.mDeferRemoval) {
- mTmpStackIds.add(stack.mStackId);
- }
- }
-
- return mTmpStackIds.isEmpty() ? null : ArrayUtils.convertToIntArray(mTmpStackIds);
}
- private void setGlobalConfigurationIfNeeded(Configuration newConfiguration,
- List<TaskStack> changedStacks) {
+ private void setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
if (!configChanged) {
return;
}
onConfigurationChanged(newConfiguration);
- updateStackBoundsAfterConfigChange(changedStacks);
}
@Override
@@ -374,24 +346,6 @@
forAllDisplays(mDisplayContentConfigChangesConsumer);
}
- /**
- * Callback used to trigger bounds update after configuration change and get ids of stacks whose
- * bounds were updated.
- */
- private void updateStackBoundsAfterConfigChange(List<TaskStack> changedStacks) {
- final int numDisplays = mChildren.size();
- for (int i = 0; i < numDisplays; ++i) {
- final DisplayContent dc = mChildren.get(i);
- dc.updateStackBoundsAfterConfigChange(changedStacks);
- }
- }
-
- /** Same as {@link #updateStackBoundsAfterConfigChange()} but only for a specific display. */
- private void updateStackBoundsAfterConfigChange(int displayId, List<TaskStack> changedStacks) {
- final DisplayContent dc = getDisplayContent(displayId);
- dc.updateStackBoundsAfterConfigChange(changedStacks);
- }
-
private void prepareFreezingTaskBounds() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
mChildren.get(i).prepareFreezingTaskBounds();
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index c920b9e..d8e1ebf 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -245,12 +245,6 @@
}
}
- public void getBoundsForNewConfiguration(Rect outBounds) {
- synchronized (mGlobalLock) {
- mContainer.getBoundsForNewConfiguration(outBounds);
- }
- }
-
/**
* Adjusts the screen size in dp's for the {@param config} for the given params. The provided
* params represent the desired state of a configuration change. Since this utility is used
@@ -378,6 +372,14 @@
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
+ /** @see TaskStack.updateBoundsForConfigChange(Configuration, Configuration, Rect) */
+ public boolean updateBoundsForConfigChange(
+ Configuration parentConfig, Configuration prevConfig, Rect outBounds) {
+ synchronized (mGlobalLock) {
+ return mContainer.updateBoundsForConfigChange(parentConfig, prevConfig, outBounds);
+ }
+ }
+
@Override
public String toString() {
return "{StackWindowController stackId=" + mStackId + "}";
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3f394a2..30eca89 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -290,12 +290,7 @@
if (displayContent != null) {
rotation = displayContent.getDisplayInfo().rotation;
} else if (bounds == null) {
- // Can't set to fullscreen if we don't have a display to get bounds from...
- return BOUNDS_CHANGE_NONE;
- }
-
- if (equivalentOverrideBounds(bounds)) {
- return BOUNDS_CHANGE_NONE;
+ return super.setBounds(bounds);
}
final int boundsChange = super.setBounds(bounds);
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index d697f28..d4acb18 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -1960,7 +1960,7 @@
info.stackId = getStackId();
info.taskId = taskId;
info.isRunning = getTopActivity() != null;
- info.baseIntent = getBaseIntent();
+ info.baseIntent = new Intent(getBaseIntent());
info.baseActivity = reuseActivitiesReport.base != null
? reuseActivitiesReport.base.intent.getComponent()
: null;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 0d98b20..4dc2b8e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -23,6 +23,9 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -61,6 +64,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -143,10 +147,6 @@
private Rect mBoundsAnimationTarget = new Rect();
private Rect mBoundsAnimationSourceHintBounds = new Rect();
- // Temporary storage for the new bounds that should be used after the configuration change.
- // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
- private final Rect mBoundsAfterRotation = new Rect();
-
Rect mPreAnimationBounds = new Rect();
private Dimmer mDimmer = new Dimmer(this);
@@ -292,8 +292,9 @@
private int setBounds(Rect existing, Rect bounds) {
int rotation = Surface.ROTATION_0;
int density = DENSITY_DPI_UNDEFINED;
- if (mDisplayContent != null) {
- mDisplayContent.getBounds(mTmpRect);
+ WindowContainer parent = getParent();
+ if (parent != null) {
+ parent.getBounds(mTmpRect);
rotation = mDisplayContent.getDisplayInfo().rotation;
density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
}
@@ -443,20 +444,33 @@
// If the rotation or density didn't match, we'll update it in onConfigurationChanged.
}
- /** @return true if bounds were updated to some non-empty value. */
- boolean updateBoundsAfterConfigChange() {
- if (mDisplayContent == null) {
- // If the stack is already detached we're not updating anything,
- // as it's going away soon anyway.
- return false;
- }
-
- if (inPinnedWindowingMode()) {
- getAnimationOrCurrentBounds(mTmpRect2);
+ /**
+ * Updates the passed-in {@code inOutBounds} based on how it would change when this container's
+ * override configuration is applied to the specified {@code parentConfig} and
+ * {@code prevConfig}. This gets run *after* the override configuration is updated, so it's
+ * safe to rely on wm hierarchy state in here (though eventually this dependence should be
+ * removed).
+ *
+ * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
+ * update various controller state (pinned/docked).
+ *
+ * @param parentConfig a parent configuration to compute relative to.
+ * @param prevConfig the full configuration used to produce the incoming {@code inOutBounds}.
+ * @param inOutBounds the bounds to update (both input and output).
+ * @return true if bounds were updated to some non-empty value. */
+ boolean updateBoundsForConfigChange(
+ Configuration parentConfig, Configuration prevConfig, Rect inOutBounds) {
+ if (getOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
+ if ((mBoundsAnimatingRequested || mBoundsAnimating)
+ && !mBoundsAnimationTarget.isEmpty()) {
+ getFinalAnimationBounds(mTmpRect2);
+ } else {
+ mTmpRect2.set(prevConfig.windowConfiguration.getBounds());
+ }
boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
mTmpRect2, mTmpRect3);
if (updated) {
- mBoundsAfterRotation.set(mTmpRect3);
+ inOutBounds.set(mTmpRect3);
// Once we've set the bounds based on the rotation of the old bounds in the new
// orientation, clear the animation target bounds since they are obsolete, and
@@ -464,72 +478,75 @@
mBoundsAnimationTarget.setEmpty();
mBoundsAnimationSourceHintBounds.setEmpty();
mCancelCurrentBoundsAnimation = true;
- return true;
}
+ return updated;
}
- final int newRotation = getDisplayInfo().rotation;
- final int newDensity = getDisplayInfo().logicalDensityDpi;
+ final int newRotation = parentConfig.windowConfiguration.getRotation();
+ final int newDensity = parentConfig.densityDpi;
- if (mRotation == newRotation && mDensity == newDensity) {
- // Nothing to do here as we already update the state in updateDisplayInfo.
+ if (prevConfig.windowConfiguration.getRotation() == newRotation
+ && prevConfig.densityDpi == newDensity) {
return false;
}
if (matchParentBounds()) {
- // Update stack bounds again since rotation changed since updateDisplayInfo().
- setBounds(null);
- // Return false since we don't need the client to resize.
return false;
}
- mTmpRect2.set(getRawBounds());
- mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
- if (inSplitScreenPrimaryWindowingMode()) {
- repositionPrimarySplitScreenStackAfterRotation(mTmpRect2);
- snapDockedStackAfterRotation(mTmpRect2);
- final int newDockSide = getDockSide(mTmpRect2);
+ mDisplayContent.rotateBounds(parentConfig.windowConfiguration.getBounds(),
+ prevConfig.windowConfiguration.getRotation(), newRotation, inOutBounds);
+ if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ boolean primary = getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
+ final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
+ snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
+ if (primary) {
+ final int newDockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
- // Update the dock create mode and clear the dock create bounds, these
- // might change after a rotation and the original values will be invalid.
- mService.setDockedStackCreateStateLocked(
- (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
- ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
- : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
- null);
- mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+ // Update the dock create mode and clear the dock create bounds, these
+ // might change after a rotation and the original values will be invalid.
+ mService.setDockedStackCreateStateLocked(
+ (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+ ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
+ : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
+ null);
+ mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+ }
}
- mBoundsAfterRotation.set(mTmpRect2);
return true;
}
- void getBoundsForNewConfiguration(Rect outBounds) {
- outBounds.set(mBoundsAfterRotation);
- mBoundsAfterRotation.setEmpty();
- }
-
/**
* Some primary split screen sides are not allowed by the policy. This method queries the policy
* and moves the primary stack around if needed.
*
- * @param inOutBounds the bounds of the primary stack to adjust
+ * @param parentConfig the configuration of the stack's parent.
+ * @param primary true if adjusting the primary docked stack, false for secondary.
+ * @param inOutBounds the bounds of the stack to adjust.
*/
- private void repositionPrimarySplitScreenStackAfterRotation(Rect inOutBounds) {
- int dockSide = getDockSide(inOutBounds);
- if (mDisplayContent.getDockedDividerController().canPrimaryStackDockTo(dockSide)) {
+ void repositionSplitScreenStackAfterRotation(Configuration parentConfig, boolean primary,
+ Rect inOutBounds) {
+ final int dockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
+ final int otherDockSide = DockedDividerUtils.invertDockSide(dockSide);
+ final int primaryDockSide = primary ? dockSide : otherDockSide;
+ if (mDisplayContent.getDockedDividerController()
+ .canPrimaryStackDockTo(primaryDockSide,
+ parentConfig.windowConfiguration.getBounds(),
+ parentConfig.windowConfiguration.getRotation())) {
return;
}
- mDisplayContent.getBounds(mTmpRect);
- dockSide = DockedDividerUtils.invertDockSide(dockSide);
- switch (dockSide) {
+ final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
+ switch (otherDockSide) {
case DOCKED_LEFT:
int movement = inOutBounds.left;
inOutBounds.left -= movement;
inOutBounds.right -= movement;
break;
case DOCKED_RIGHT:
- movement = mTmpRect.right - inOutBounds.right;
+ movement = parentBounds.right - inOutBounds.right;
inOutBounds.left += movement;
inOutBounds.right += movement;
break;
@@ -539,7 +556,7 @@
inOutBounds.bottom -= movement;
break;
case DOCKED_BOTTOM:
- movement = mTmpRect.bottom - inOutBounds.bottom;
+ movement = parentBounds.bottom - inOutBounds.bottom;
inOutBounds.top += movement;
inOutBounds.bottom += movement;
break;
@@ -549,22 +566,22 @@
/**
* Snaps the bounds after rotation to the closest snap target for the docked stack.
*/
- private void snapDockedStackAfterRotation(Rect outBounds) {
+ void snapDockedStackAfterRotation(Configuration parentConfig, DisplayCutout displayCutout,
+ Rect outBounds) {
// Calculate the current position.
- final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
- final int dockSide = getDockSide(outBounds);
+ final int dockSide = getDockSide(parentConfig, outBounds);
final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
dockSide, dividerSize);
- final int displayWidth = displayInfo.logicalWidth;
- final int displayHeight = displayInfo.logicalHeight;
+ final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
+ final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
// Snap the position to a target.
- final int rotation = displayInfo.rotation;
- final int orientation = mDisplayContent.getConfiguration().orientation;
+ final int rotation = parentConfig.windowConfiguration.getRotation();
+ final int orientation = parentConfig.orientation;
mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight,
- displayInfo.displayCutout, outBounds);
+ displayCutout, outBounds);
final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
mService.mContext.getResources(), displayWidth, displayHeight,
dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
@@ -573,7 +590,7 @@
// Recalculate the bounds based on the position of the target.
DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
- outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
+ outBounds, displayWidth, displayHeight,
dividerSize);
}
@@ -1473,27 +1490,27 @@
* information which side of the screen was the dock anchored.
*/
int getDockSide() {
- return getDockSide(getRawBounds());
+ return getDockSide(mDisplayContent.getConfiguration(), getRawBounds());
}
int getDockSideForDisplay(DisplayContent dc) {
- return getDockSide(dc, getRawBounds());
+ return getDockSide(dc, dc.getConfiguration(), getRawBounds());
}
- private int getDockSide(Rect bounds) {
+ int getDockSide(Configuration parentConfig, Rect bounds) {
if (mDisplayContent == null) {
return DOCKED_INVALID;
}
- return getDockSide(mDisplayContent, bounds);
+ return getDockSide(mDisplayContent, parentConfig, bounds);
}
- private int getDockSide(DisplayContent dc, Rect bounds) {
+ private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) {
if (!inSplitScreenWindowingMode()) {
return DOCKED_INVALID;
}
- dc.getBounds(mTmpRect);
- final int orientation = dc.getConfiguration().orientation;
- return dc.getDockedDividerController().getDockSide(bounds, mTmpRect, orientation);
+ return dc.getDockedDividerController().getDockSide(bounds,
+ parentConfig.windowConfiguration.getBounds(),
+ parentConfig.orientation, parentConfig.windowConfiguration.getRotation());
}
boolean hasTaskForUser(int userId) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a641f75..e4444e2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -29,6 +29,7 @@
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -441,7 +442,7 @@
final WindowHashMap mWindowMap = new WindowHashMap();
/** Global service lock used by the package the owns this service. */
- WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
+ final WindowManagerGlobalLock mGlobalLock;
/**
* List of app window tokens that are waiting for replacing windows. If the
@@ -538,12 +539,21 @@
int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
Rect mDockedStackCreateBounds;
- boolean mForceResizableTasks = false;
- boolean mSupportsPictureInPicture = false;
- boolean mSupportsFreeformWindowManagement = false;
- boolean mIsPc = false;
+ boolean mForceResizableTasks;
+ boolean mSupportsPictureInPicture;
+ boolean mSupportsFreeformWindowManagement;
+ boolean mIsPc;
+ /**
+ * Flag that indicates that desktop mode is forced for public secondary screens.
+ *
+ * This includes several settings:
+ * - Set freeform windowing mode on external screen if it's supported and enabled.
+ * - Enable system decorations and IME on external screen.
+ * - TODO: Show mouse pointer on external screen.
+ */
+ boolean mForceDesktopModeOnExternalDisplays;
- boolean mDisableTransitionAnimation = false;
+ boolean mDisableTransitionAnimation;
int getDragLayerLocked() {
return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
@@ -855,9 +865,11 @@
}
public static WindowManagerService main(final Context context, final InputManagerService im,
- final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy) {
+ final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
+ final WindowManagerGlobalLock globalLock) {
DisplayThread.getHandler().runWithScissors(() ->
- sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy),
+ sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
+ globalLock),
0);
return sInstance;
}
@@ -879,8 +891,10 @@
}
private WindowManagerService(Context context, InputManagerService inputManager,
- boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy) {
+ boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
+ WindowManagerGlobalLock globalLock) {
installLock(this, INDEX_WINDOW);
+ mGlobalLock = globalLock;
mContext = context;
mAllowBootMessages = showBootMsgs;
mOnlyCore = onlyCore;
@@ -976,17 +990,21 @@
}
}, UserHandle.ALL, suspendPackagesFilter, null, null);
+ final ContentResolver resolver = context.getContentResolver();
// Get persisted window scale setting
- mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
+ mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
- mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
+ mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
Settings.Global.TRANSITION_ANIMATION_SCALE,
context.getResources().getFloat(
R.dimen.config_appTransitionAnimationDurationScaleDefault));
- setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
+ setAnimatorDurationScale(Settings.Global.getFloat(resolver,
Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
+ mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
+ DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
+
IntentFilter filter = new IntentFilter();
// Track changes to DevicePolicyManager state so we can enable/disable keyguard.
filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -2403,20 +2421,13 @@
return config;
}
- @Override
- public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+ void setNewDisplayOverrideConfiguration(Configuration overrideConfig, DisplayContent dc) {
+ if (mWaitingForConfig) {
+ mWaitingForConfig = false;
+ mLastFinishedFreezeSource = "new-config";
}
- synchronized (mGlobalLock) {
- if (mWaitingForConfig) {
- mWaitingForConfig = false;
- mLastFinishedFreezeSource = "new-config";
- }
-
- return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
- }
+ mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, dc);
}
// TODO(multi-display): remove when no default display use case.
@@ -2629,21 +2640,16 @@
/**
* Starts deferring layout passes. Useful when doing multiple changes but to optimize
* performance, only one layout pass should be done. This can be called multiple times, and
- * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
+ * layouting will be resumed once the last caller has called
+ * {@link #continueSurfaceLayout}.
*/
- public void deferSurfaceLayout() {
- synchronized (mGlobalLock) {
- mWindowPlacerLocked.deferLayout();
- }
+ void deferSurfaceLayout() {
+ mWindowPlacerLocked.deferLayout();
}
- /**
- * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
- */
- public void continueSurfaceLayout() {
- synchronized (mGlobalLock) {
- mWindowPlacerLocked.continueLayout();
- }
+ /** Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} */
+ void continueSurfaceLayout() {
+ mWindowPlacerLocked.continueLayout();
}
/**
@@ -6406,6 +6412,12 @@
}
}
+ void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
+ synchronized (mWindowMap) {
+ mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
+ }
+ }
+
public void setIsPc(boolean isPc) {
synchronized (mGlobalLock) {
mIsPc = isPc;
@@ -6584,10 +6596,10 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final DisplayContent dc = getDisplayContentOrCreate(displayId, null);
+ final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
if (dc == null) {
throw new IllegalArgumentException(
- "Trying to register a non existent display.");
+ "Trying to configure a non existent display.");
}
// We usually set the override info in DisplayManager so that we get consistent
// values when displays are changing. However, we don't do this for displays that
@@ -6902,7 +6914,7 @@
if (DEBUG_DISPLAY) {
Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
}
- synchronized (WindowManagerService.this) {
+ synchronized (mGlobalLock) {
mVr2dDisplayId = vr2dDisplayId;
}
}
@@ -7027,10 +7039,6 @@
* WARNING: This interrupts surface updates, be careful! Don't
* execute within the transaction for longer than you would
* execute on an animation thread.
- * WARNING: This holds the WindowManager lock, so if exec will acquire
- * the ActivityManager lock, you should hold it BEFORE calling this
- * otherwise there is a risk of deadlock if another thread holding the AM
- * lock waits on the WM lock.
* WARNING: This method contains locks known to the State of California
* to cause Deadlocks and other conditions.
*
@@ -7051,19 +7059,12 @@
* deferSurfaceLayout may be a little too broad, in particular the total
* enclosure of startActivityUnchecked which could run for quite some time.
*/
- public void inSurfaceTransaction(Runnable exec) {
- // We hold the WindowManger lock to ensure relayoutWindow
- // does not return while a Surface transaction is opening.
- // The client depends on us to have resized the surface
- // by that point (b/36462635)
-
- synchronized (mGlobalLock) {
- SurfaceControl.openTransaction();
- try {
- exec.run();
- } finally {
- SurfaceControl.closeTransaction();
- }
+ void inSurfaceTransaction(Runnable exec) {
+ SurfaceControl.openTransaction();
+ try {
+ exec.run();
+ } finally {
+ SurfaceControl.closeTransaction();
}
}
@@ -7139,6 +7140,10 @@
mRotatingSeamlessly = true;
}
+ boolean isRotatingSeamlessly() {
+ return mRotatingSeamlessly;
+ }
+
void finishSeamlessRotation() {
mRotatingSeamlessly = false;
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index bb17254..4c9788d 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -56,6 +56,7 @@
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.Watchdog;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -690,24 +691,52 @@
}
void addPackage(String pkg, long versionCode) {
- // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
- // using WM lock. Need to figure-out if it is okay to do this asynchronously.
if (mListener == null) return;
- mListener.addPackage(pkg, versionCode);
+ // Posting on handler so WM lock isn't held when we call into AM.
+ final Message m = PooledLambda.obtainMessage(
+ WindowProcessListener::addPackage, mListener, pkg, versionCode);
+ mAtm.mH.sendMessage(m);
}
ProfilerInfo onStartActivity(int topProcessState) {
- // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
- // using WM lock. Need to figure-out if it is okay to do this asynchronously.
- if (mListener == null) return null;
- return mListener.onStartActivity(topProcessState);
+ ProfilerInfo profilerInfo = null;
+ boolean setProfileProc = false;
+ if (mAtm.mProfileApp != null
+ && mAtm.mProfileApp.equals(mName)) {
+ if (mAtm.mProfileProc == null || mAtm.mProfileProc == this) {
+ setProfileProc = true;
+ final ProfilerInfo profilerInfoSvc = mAtm.mProfilerInfo;
+ if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
+ if (profilerInfoSvc.profileFd != null) {
+ try {
+ profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
+ } catch (IOException e) {
+ profilerInfoSvc.closeFd();
+ }
+ }
+
+ profilerInfo = new ProfilerInfo(profilerInfoSvc);
+ }
+ }
+ }
+
+
+ if (mListener != null) {
+ // Posting on handler so WM lock isn't held when we call into AM.
+ final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity,
+ mListener, topProcessState, setProfileProc);
+ mAtm.mH.sendMessage(m);
+ }
+
+ return profilerInfo;
}
public void appDied() {
- // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
- // using WM lock. Need to figure-out if it is okay to do this asynchronously.
if (mListener == null) return;
- mListener.appDied();
+ // Posting on handler so WM lock isn't held when we call into AM.
+ final Message m = PooledLambda.obtainMessage(
+ WindowProcessListener::appDied, mListener);
+ mAtm.mH.sendMessage(m);
}
void registerDisplayConfigurationListenerLocked(ActivityDisplay activityDisplay) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessListener.java b/services/core/java/com/android/server/wm/WindowProcessListener.java
index 7f20f4b..bce5e2d 100644
--- a/services/core/java/com/android/server/wm/WindowProcessListener.java
+++ b/services/core/java/com/android/server/wm/WindowProcessListener.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import android.app.ProfilerInfo;
import android.util.proto.ProtoOutputStream;
/**
@@ -58,7 +57,7 @@
void addPackage(String pkg, long versionCode);
/** Called when we are in the process on starting an activity. */
- ProfilerInfo onStartActivity(int topProcessState);
+ void onStartActivity(int topProcessState, boolean setProfileProc);
/** App died :(...oh well */
void appDied();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 54a140d..933eac6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -115,6 +115,7 @@
import com.android.server.policy.PhoneWindowManager;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
+import com.android.server.power.ThermalManagerService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
@@ -134,6 +135,7 @@
import com.android.server.vr.VrManagerService;
import com.android.server.webkit.WebViewUpdateService;
import com.android.server.wm.ActivityTaskManagerService;
+import com.android.server.wm.WindowManagerGlobalLock;
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
@@ -275,6 +277,7 @@
// TODO: remove all of these references by improving dependency resolution and boot phases
private PowerManagerService mPowerManagerService;
private ActivityManagerService mActivityManagerService;
+ private WindowManagerGlobalLock mWindowManagerGlobalLock;
private WebViewUpdateService mWebViewUpdateService;
private DisplayManagerService mDisplayManagerService;
private PackageManagerService mPackageManagerService;
@@ -597,6 +600,7 @@
mSystemServiceManager, atm);
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
+ mWindowManagerGlobalLock = atm.getGlobalLock();
traceEnd();
// Power manager needs to be started early because other services need it.
@@ -607,6 +611,10 @@
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
traceEnd();
+ traceBeginAndSlog("StartThermalManager");
+ mSystemServiceManager.startService(ThermalManagerService.class);
+ traceEnd();
+
// Now that the power manager has been started, let the activity manager
// initialize power management features.
traceBeginAndSlog("InitPowerManagement");
@@ -921,7 +929,7 @@
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
- new PhoneWindowManager());
+ new PhoneWindowManager(), mWindowManagerGlobalLock);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
@@ -1619,7 +1627,7 @@
if (hasFeatureFace || hasFeatureIris || hasFeatureFingerprint) {
// Start this service after all biometric services.
- traceBeginAndSlog("StartBiometricPromptService");
+ traceBeginAndSlog("StartBiometricService");
mSystemServiceManager.startService(BiometricService.class);
traceEnd();
}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 878179b..e2f8995 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -33,7 +33,8 @@
testables \
testng \
ub-uiautomator\
- platformprotosnano
+ platformprotosnano \
+ hamcrest-library
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index e53518c..69d8e25 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -28,8 +28,9 @@
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.os.storage.StorageManagerInternal;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 2b5b812..a847b6a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -38,12 +38,13 @@
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.security.KeyChain;
-import android.support.annotation.NonNull;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.IWindowManager;
+import androidx.annotation.NonNull;
+
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.net.NetworkPolicyManagerInternal;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 213961c..be00bb6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -30,11 +30,12 @@
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManagerInternal;
-import android.support.annotation.NonNull;
import android.test.mock.MockContext;
import android.util.ArrayMap;
import android.util.ExceptionUtils;
+import androidx.annotation.NonNull;
+
import com.android.internal.util.FunctionalUtils;
import org.junit.Assert;
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
index e62e07d..6b7634d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -29,6 +29,7 @@
import android.content.pm.PackageManagerInternal;
import android.os.Build;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -47,6 +48,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
+@Presubmit
public class JobSetTest {
private static final String TAG = JobSetTest.class.getSimpleName();
private static final int SECONDARY_USER_ID_1 = 12;
@@ -64,6 +66,7 @@
final PackageManagerInternal pm = mock(PackageManagerInternal.class);
when(pm.getPackageTargetSdkVersion(anyString()))
.thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, pm);
assumeFalse("Test cannot run in user " + mContext.getUserId(),
mContext.getUserId() == SECONDARY_USER_ID_1
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index ebac8fb..58c4bbf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -15,7 +15,10 @@
*/
package com.android.server.pm;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -461,6 +464,7 @@
pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
pkg.requestedPermissions.add("foo7");
+ pkg.implicitPermissions.add("foo25");
pkg.protectedBroadcasts = new ArrayList<>();
pkg.protectedBroadcasts.add("foo8");
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index 553d234a..c6be1c0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -16,6 +16,10 @@
package com.android.server.pm;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_PLAY_AUDIO;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -35,12 +39,14 @@
import android.content.pm.PackageManager;
import android.content.pm.SuspendDialogInfo;
import android.content.res.Resources;
+import android.media.AudioAttributes;
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
@@ -54,6 +60,8 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
@@ -550,6 +558,32 @@
assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
}
+ @Test
+ public void testAudioOpBlockedOnSuspend() throws Exception {
+ final IAppOpsService iAppOps = IAppOpsService.Stub.asInterface(
+ ServiceManager.getService(Context.APP_OPS_SERVICE));
+ final CountDownLatch latch = new CountDownLatch(1);
+ final IAppOpsCallback watcher = new IAppOpsCallback.Stub() {
+ @Override
+ public void opChanged(int op, int uid, String packageName) {
+ if (op == OP_PLAY_AUDIO && packageName.equals(TEST_APP_PACKAGE_NAME)) {
+ latch.countDown();
+ }
+ }
+ };
+ iAppOps.startWatchingMode(OP_PLAY_AUDIO, TEST_APP_PACKAGE_NAME, watcher);
+ final int testPackageUid = mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0);
+ int audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO,
+ AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME);
+ assertEquals("Audio muted for unsuspended package", MODE_ALLOWED, audioOpMode);
+ suspendTestPackage(null, null, null);
+ assertTrue("AppOpsWatcher did not callback", latch.await(5, TimeUnit.SECONDS));
+ audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO,
+ AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME);
+ assertEquals("Audio not muted for suspended package", MODE_IGNORED, audioOpMode);
+ iAppOps.stopWatchingMode(watcher);
+ }
+
@After
public void tearDown() throws IOException {
mAppCommsReceiver.unregister();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index bd42b73..dad7b93 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -68,6 +68,7 @@
private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
DelegateLastClassLoader.class.getName();
+ private static final String UNSUPPORTED_CLASS_LOADER_NAME = "unsupported.class_loader";
@Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Mock Installer mInstaller;
@@ -105,7 +106,7 @@
mDoesNotExist = new TestData("DOES.NOT.EXIST", isa, mUser1);
mBarUser0UnsupportedClassLoader = new TestData(bar, isa, mUser0,
- "unsupported.class_loader");
+ UNSUPPORTED_CLASS_LOADER_NAME);
mBarUser0DelegateLastClassLoader = new TestData(bar, isa, mUser0,
DELEGATE_LAST_CLASS_LOADER_NAME);
@@ -405,6 +406,24 @@
}
@Test
+ public void testNotifySupportedAndUnsupportedClassLoader() {
+ String classPath = String.join(File.pathSeparator, mBarUser0.getSecondaryDexPaths());
+ List<String> classLoaders =
+ Arrays.asList(PATH_CLASS_LOADER_NAME, UNSUPPORTED_CLASS_LOADER_NAME);
+ List<String> classPaths = Arrays.asList(classPath, classPath);
+ notifyDexLoad(mBarUser0, classLoaders, classPaths, mUser0);
+
+ assertNoUseInfo(mBarUser0);
+ }
+
+ @Test
+ public void testNotifyNullClassPath() {
+ notifyDexLoad(mBarUser0, null, mUser0);
+
+ assertNoUseInfo(mBarUser0);
+ }
+
+ @Test
public void testNotifyVariableClassLoader() {
// Record bar secondaries with the default PathClassLoader.
List<String> secondaries = mBarUser0.getSecondaryDexPaths();
@@ -499,14 +518,17 @@
// By default, assume a single class loader in the chain.
// This makes writing tests much easier.
List<String> classLoaders = Arrays.asList(testData.mClassLoader);
- List<String> classPaths = Arrays.asList(String.join(File.pathSeparator, dexPaths));
+ List<String> classPaths = (dexPaths == null)
+ ? Arrays.asList((String) null)
+ : Arrays.asList(String.join(File.pathSeparator, dexPaths));
notifyDexLoad(testData, classLoaders, classPaths, loaderUserId);
}
- private void notifyDexLoad(TestData testData, List<String> classLoader, List<String> classPaths,
- int loaderUserId) {
- mDexManager.notifyDexLoad(testData.mPackageInfo.applicationInfo, classLoader, classPaths,
- testData.mLoaderIsa, loaderUserId);
+ private void notifyDexLoad(TestData testData, List<String> classLoaders,
+ List<String> classPaths, int loaderUserId) {
+ // We call the internal function so any exceptions thrown cause test failures.
+ mDexManager.notifyDexLoadInternal(testData.mPackageInfo.applicationInfo, classLoaders,
+ classPaths, testData.mLoaderIsa, loaderUserId);
}
private PackageUseInfo getPackageUseInfo(TestData testData) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 77f517b..cd15a57 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -353,6 +353,18 @@
}
@Test
+ public void testProcessContextForDexLoadNoClassPath() {
+ List<String> classLoaders = Arrays.asList(
+ DELEGATE_LAST_CLASS_LOADER_NAME,
+ PATH_CLASS_LOADER_NAME);
+ List<String> classPaths = Arrays.asList(
+ String.join(File.pathSeparator, "foo.dex", "bar.dex"),
+ null);
+ String[] context = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
+ assertNull(context);
+ }
+
+ @Test
public void testProcessContextForDexLoadIllegalCallEmptyList() {
boolean gotException = false;
try {
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index caaa0bb..41d5691 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -129,6 +129,7 @@
static class MyInjector extends AppStandbyController.Injector {
long mElapsedRealtime;
+ boolean mIsAppIdleEnabled = true;
boolean mIsCharging;
List<String> mPowerSaveWhitelistExceptIdle = new ArrayList<>();
boolean mDisplayOn;
@@ -160,7 +161,7 @@
@Override
boolean isAppIdleEnabled() {
- return true;
+ return mIsAppIdleEnabled;
}
@Override
@@ -277,6 +278,13 @@
}
}
+ private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
+ mInjector.mIsAppIdleEnabled = enabled;
+ if (controller != null) {
+ controller.setAppIdleEnabled(enabled);
+ }
+ }
+
private AppStandbyController setupController() throws Exception {
mInjector.mElapsedRealtime = 0;
setupPm(mInjector.getContext().getPackageManager());
@@ -346,7 +354,7 @@
public void onParoleStateChanged(boolean isParoleOn) {
synchronized (this) {
// Only record information if it is being looked for
- if (mLatch.getCount() > 0) {
+ if (mLatch != null && mLatch.getCount() > 0) {
mOnParole = isParoleOn;
mLastParoleChangeTime = getCurrentTime();
mLatch.countDown();
@@ -407,6 +415,74 @@
marginOfError);
}
+ @Test
+ public void testEnabledState() throws Exception {
+ TestParoleListener paroleListener = new TestParoleListener();
+ mController.addListener(paroleListener);
+ long lastUpdateTime;
+
+ // Test that listeners are notified if enabled changes when the device is not in parole.
+ setChargingState(mController, false);
+
+ // Start off not enabled. Device is effectively on permanent parole.
+ setAppIdleEnabled(mController, false);
+
+ // Enable controller
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, true);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertFalse(paroleListener.mOnParole);
+ lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, true);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertFalse(paroleListener.mOnParole);
+ // Make sure AppStandbyController doesn't notify listeners when there's no change.
+ assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+ // Disable controller
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, false);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertTrue(paroleListener.mOnParole);
+ lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, false);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertTrue(paroleListener.mOnParole);
+ // Make sure AppStandbyController doesn't notify listeners when there's no change.
+ assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+
+ // Test that listeners aren't notified if enabled status changes when the device is already
+ // in parole.
+
+ // A device is in parole whenever it's charging.
+ setChargingState(mController, true);
+
+ // Start off not enabled.
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, false);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertTrue(paroleListener.mOnParole);
+ lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+ // Test that toggling doesn't notify the listener.
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, true);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertTrue(paroleListener.mOnParole);
+ assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+ paroleListener.rearmLatch();
+ setAppIdleEnabled(mController, false);
+ paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+ assertTrue(paroleListener.mOnParole);
+ assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+ }
+
private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
mInjector.mElapsedRealtime = elapsedTime;
controller.checkIdleStates(USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index a8e1ed4..552390d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -190,7 +190,11 @@
private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
+ int oldRotation = mDisplayContent.getRotation();
mWm.updateRotation(false, false);
+ // Must manually apply here since ATM doesn't know about the display during this test
+ // (meaning it can't perform the normal sendNewConfiguration flow).
+ mDisplayContent.applyRotationLocked(oldRotation, mDisplayContent.getRotation());
// Prevent the next rotation from being deferred by animation.
mWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index dd374e9..f4da4b3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -230,7 +230,6 @@
*/
@Test
public void testDisplayOverrideConfigUpdate() {
- final int displayId = mDisplayContent.getDisplayId();
final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
// Create new, slightly changed override configuration and apply it to the display.
@@ -238,7 +237,7 @@
newOverrideConfig.densityDpi += 120;
newOverrideConfig.fontScale += 0.3;
- mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
+ mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
// Check that override config is applied.
assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
@@ -249,14 +248,15 @@
*/
@Test
public void testDefaultDisplayOverrideConfigUpdate() {
- final Configuration currentConfig = mDisplayContent.getConfiguration();
+ DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
+ final Configuration currentConfig = defaultDisplay.getConfiguration();
// Create new, slightly changed override configuration and apply it to the display.
final Configuration newOverrideConfig = new Configuration(currentConfig);
newOverrideConfig.densityDpi += 120;
newOverrideConfig.fontScale += 0.3;
- mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
+ mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
// Check that global configuration is updated, as we've updated default display's config.
Configuration globalConfig = mWm.mRoot.getConfiguration();
@@ -264,7 +264,7 @@
assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
// Return back to original values.
- mWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
+ mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
globalConfig = mWm.mRoot.getConfiguration();
assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
index f0c49c8..5808bc9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
@@ -64,6 +64,7 @@
mWm.setSupportsFreeformWindowManagement(false);
mWm.setIsPc(false);
+ mWm.setForceDesktopModeOnExternalDisplays(false);
mTarget = new DisplaySettings(mWm, TEST_FOLDER);
@@ -78,7 +79,7 @@
}
@Test
- public void testPrimaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+ public void testPrimaryDisplayDefaultToFullscreen_NoFreeformSupport() {
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
@@ -86,7 +87,7 @@
}
@Test
- public void testPrimaryDisplayDefaultToFullscreenWithFreeformSupportNonPc() {
+ public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_NoDesktopMode() {
mWm.setSupportsFreeformWindowManagement(true);
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -96,7 +97,18 @@
}
@Test
- public void testPrimaryDisplayDefaultToFreeformWithFreeformIsPc() {
+ public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_HasDesktopMode() {
+ mWm.setSupportsFreeformWindowManagement(true);
+ mWm.setForceDesktopModeOnExternalDisplays(true);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+ mPrimaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testPrimaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
mWm.setSupportsFreeformWindowManagement(true);
mWm.setIsPc(true);
@@ -107,7 +119,7 @@
}
@Test
- public void testSecondaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+ public void testSecondaryDisplayDefaultToFullscreen_NoFreeformSupport() {
mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
@@ -115,17 +127,28 @@
}
@Test
- public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportNonPc() {
+ public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_NoDesktopMode() {
mWm.setSupportsFreeformWindowManagement(true);
mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+ mSecondaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_HasDesktopMode() {
+ mWm.setSupportsFreeformWindowManagement(true);
+ mWm.setForceDesktopModeOnExternalDisplays(true);
+
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
mSecondaryDisplay.getWindowingMode());
}
@Test
- public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportIsPc() {
+ public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
mWm.setSupportsFreeformWindowManagement(true);
mWm.setIsPc(true);
diff --git a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
deleted file mode 100644
index 62a617d..0000000
--- a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Tests for the {@link RootWindowContainer} class.
- *
- * Build/Install/Run:
- * atest FrameworksServicesTests:RootWindowContainerTests
- */
-@SmallTest
-@Presubmit
-public class RootWindowContainerTests extends WindowTestsBase {
- @Test
- public void testSetDisplayOverrideConfigurationIfNeeded() {
- synchronized (mWm.mGlobalLock) {
- // Add first stack we expect to be updated with configuration change.
- final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
- stack.getOverrideConfiguration().windowConfiguration.setBounds(new Rect(0, 0, 5, 5));
-
- // Add second task that will be set for deferred removal that should not be returned
- // with the configuration change.
- final TaskStack deferredDeletedStack = createTaskStackOnDisplay(mDisplayContent);
- deferredDeletedStack.getOverrideConfiguration().windowConfiguration.setBounds(
- new Rect(0, 0, 5, 5));
- deferredDeletedStack.mDeferRemoval = true;
-
- final Configuration override = new Configuration(
- mDisplayContent.getOverrideConfiguration());
- override.windowConfiguration.setBounds(new Rect(0, 0, 10, 10));
-
- // Set display override.
- final int[] results = mWm.mRoot.setDisplayOverrideConfigurationIfNeeded(override,
- mDisplayContent.getDisplayId());
-
- // Ensure only first stack is returned.
- assertEquals(1, results.length);
- assertEquals(stack.mStackId, results[0]);
- }
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
index 4369c96..3643457 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -22,6 +22,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOW_CONFIG_ALWAYS_ON_TOP;
import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION;
import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
@@ -33,6 +34,7 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
+import android.view.Surface;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
@@ -66,11 +68,13 @@
final WindowConfiguration winConfig2 = config2.windowConfiguration;
final Configuration config3 = new Configuration();
final WindowConfiguration winConfig3 = config3.windowConfiguration;
+ final Configuration config4 = new Configuration();
+ final WindowConfiguration winConfig4 = config4.windowConfiguration;
winConfig1.setAppBounds(0, 1, 1, 0);
winConfig2.setAppBounds(1, 2, 2, 1);
winConfig3.setAppBounds(winConfig1.getAppBounds());
-
+ winConfig4.setRotation(Surface.ROTATION_90);
assertEquals(CONFIG_WINDOW_CONFIGURATION, config1.diff(config2));
assertEquals(0, config1.diffPublicOnly(config2));
@@ -86,6 +90,9 @@
| WINDOW_CONFIG_ALWAYS_ON_TOP,
winConfig1.diff(winConfig2, false /* compareUndefined */));
+ assertEquals(WINDOW_CONFIG_ROTATION,
+ winConfig1.diff(winConfig4, false /* compareUndefined */));
+
assertEquals(0, config1.diff(config3));
assertEquals(0, config1.diffPublicOnly(config3));
assertEquals(0, winConfig1.diff(winConfig3, false /* compareUndefined */));
@@ -123,11 +130,18 @@
winConfig2.setAppBounds(0, 2, 3, 4);
assertNotEquals(config1.compareTo(config2), 0);
assertNotEquals(winConfig1.compareTo(winConfig2), 0);
+ winConfig2.setAppBounds(winConfig1.getAppBounds());
// No bounds
assertEquals(config1.compareTo(blankConfig), -1);
assertEquals(winConfig1.compareTo(blankWinConfig), -1);
+ // Different rotation
+ winConfig2.setRotation(Surface.ROTATION_180);
+ assertNotEquals(config1.compareTo(config2), 0);
+ assertNotEquals(winConfig1.compareTo(winConfig2), 0);
+ winConfig2.setRotation(winConfig1.getRotation());
+
assertEquals(blankConfig.compareTo(config1), 1);
assertEquals(blankWinConfig.compareTo(winConfig1), 1);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
index 4e75ec9..9a13efb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -124,9 +124,10 @@
doReturn(input[1]).when(ims).monitorInput(anyString(), anyInt());
}
- mService = WindowManagerService.main(context, ims, false,
- false, mPolicy = new TestWindowManagerPolicy(
- WindowManagerServiceRule.this::getWindowManagerService));
+ mService = WindowManagerService.main(context, ims, false, false,
+ mPolicy = new TestWindowManagerPolicy(
+ WindowManagerServiceRule.this::getWindowManagerService),
+ new WindowManagerGlobalLock());
mService.mTransactionFactory = () -> {
final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
mSurfaceTransactions.add(new WeakReference<>(transaction));
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 9e12f02..b318b91 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -53,14 +53,6 @@
public class WindowTestUtils {
private static int sNextTaskId = 0;
- /** Retrieves an instance of a mock {@link WindowManagerService}. */
- static WindowManagerService getMockWindowManagerService() {
- final WindowManagerService service = mock(WindowManagerService.class);
- final WindowManagerGlobalLock lock = new WindowManagerGlobalLock();
- doReturn(lock).when(service).getWindowManagerLock();
- return service;
- }
-
/** An extension of {@link DisplayContent} to gain package scoped access. */
public static class TestDisplayContent extends DisplayContent {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 59eab3f..9da204f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -417,6 +417,7 @@
verifyLights();
assertTrue(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -429,6 +430,7 @@
verifyNeverVibrate();
verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -439,6 +441,7 @@
verifyBeep();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -449,6 +452,7 @@
verifyNeverBeep();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -461,6 +465,7 @@
verifyNeverBeep();
verifyNeverVibrate();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -473,6 +478,7 @@
verifyNeverBeep();
verifyNeverVibrate();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -489,6 +495,7 @@
verifyBeepLooped();
verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -517,6 +524,7 @@
verifyNeverStopAudio();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -530,7 +538,9 @@
verifyNeverStopAudio();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
/**
@@ -567,6 +577,7 @@
mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
verifyNeverStopAudio();
assertTrue(other.isInterruptive());
+ assertTrue(other.getAudiblyAlerted());
}
@Test
@@ -592,12 +603,14 @@
// set up internal state
mService.buzzBeepBlinkLocked(r);
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
Mockito.reset(mRingtonePlayer);
// quiet update should stop making noise
mService.buzzBeepBlinkLocked(s);
verifyStopAudio();
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -609,12 +622,14 @@
// set up internal state
mService.buzzBeepBlinkLocked(r);
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
Mockito.reset(mRingtonePlayer);
// stop making noise - this is a weird corner case, but quiet should override once
mService.buzzBeepBlinkLocked(s);
verifyStopAudio();
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -631,6 +646,7 @@
verify(mService, times(1)).playInCallNotification();
verifyNeverBeep(); // doesn't play normal beep
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -650,6 +666,7 @@
eq(effect), anyString(),
(AudioAttributes) anyObject());
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -667,6 +684,7 @@
verifyNeverVibrate();
verifyBeepLooped();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -686,6 +704,7 @@
verify(mRingtonePlayer, never()).playAsync
(anyObject(), anyObject(), anyBoolean(), anyObject());
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -702,6 +721,7 @@
verifyDelayedVibrateLooped();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -713,6 +733,7 @@
verifyNeverBeep();
verifyVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -722,6 +743,7 @@
mService.buzzBeepBlinkLocked(r);
verifyVibrateLooped();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -737,6 +759,7 @@
mService.buzzBeepBlinkLocked(r);
verifyVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -747,6 +770,7 @@
verifyNeverBeep();
assertFalse(child.isInterruptive());
+ assertFalse(child.getAudiblyAlerted());
}
@Test
@@ -759,6 +783,7 @@
verifyBeepLooped();
// summaries are never interruptive for notification counts
assertFalse(summary.isInterruptive());
+ assertTrue(summary.getAudiblyAlerted());
}
@Test
@@ -769,6 +794,7 @@
verifyBeepLooped();
assertTrue(nonGroup.isInterruptive());
+ assertTrue(nonGroup.getAudiblyAlerted());
}
@Test
@@ -780,6 +806,7 @@
verifyNeverBeep();
assertFalse(summary.isInterruptive());
+ assertFalse(summary.getAudiblyAlerted());
}
@Test
@@ -790,6 +817,7 @@
verifyBeepLooped();
assertTrue(child.isInterruptive());
+ assertTrue(child.getAudiblyAlerted());
}
@Test
@@ -800,6 +828,7 @@
verifyBeepLooped();
assertTrue(nonGroup.isInterruptive());
+ assertTrue(nonGroup.getAudiblyAlerted());
}
@Test
@@ -810,6 +839,7 @@
verifyBeepLooped();
assertTrue(group.isInterruptive());
+ assertTrue(group.getAudiblyAlerted());
}
@Test
@@ -822,11 +852,13 @@
mService.buzzBeepBlinkLocked(r);
Mockito.reset(mVibrator);
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
// update should not beep
mService.buzzBeepBlinkLocked(s);
verifyNeverVibrate();
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -839,6 +871,7 @@
verifyNeverStopVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
}
@Test
@@ -852,7 +885,9 @@
verifyNeverStopVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -871,8 +906,11 @@
mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
verifyNeverStopVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
assertTrue(other.isInterruptive());
+ assertTrue(other.getAudiblyAlerted());
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -888,6 +926,7 @@
mService.buzzBeepBlinkLocked(other);
verifyNeverStopVibrate();
assertFalse(other.isInterruptive());
+ assertFalse(other.getAudiblyAlerted());
}
@Test
@@ -904,7 +943,9 @@
mService.buzzBeepBlinkLocked(s);
verifyStopVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -921,7 +962,9 @@
mService.buzzBeepBlinkLocked(s);
verifyStopVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -939,7 +982,9 @@
mService.buzzBeepBlinkLocked(s);
verifyStopVibrate();
assertTrue(r.isInterruptive());
+ assertTrue(r.getAudiblyAlerted());
assertFalse(s.isInterruptive());
+ assertFalse(s.getAudiblyAlerted());
}
@Test
@@ -957,6 +1002,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -968,6 +1014,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1010,6 +1057,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverBeep();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1043,6 +1091,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1052,6 +1101,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1060,6 +1110,7 @@
mService.buzzBeepBlinkLocked(r);
verifyLights();
assertTrue(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
r = getLightsOnceNotification();
r.isUpdate = true;
@@ -1067,6 +1118,7 @@
// checks that lights happened once, i.e. this new call didn't trigger them again
verifyLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1076,6 +1128,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1084,6 +1137,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1093,6 +1147,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1102,6 +1157,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1111,6 +1167,7 @@
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
assertFalse(r.isInterruptive());
+ assertFalse(r.getAudiblyAlerted());
}
@Test
@@ -1121,6 +1178,7 @@
verifyNeverLights();
assertFalse(child.isInterruptive());
+ assertFalse(child.getAudiblyAlerted());
}
@Test
@@ -1133,6 +1191,7 @@
verifyLights();
// summaries should never count for interruptiveness counts
assertFalse(summary.isInterruptive());
+ assertFalse(summary.getAudiblyAlerted());
}
@Test
@@ -1143,6 +1202,7 @@
verifyLights();
assertTrue(nonGroup.isInterruptive());
+ assertFalse(nonGroup.getAudiblyAlerted());
}
@Test
@@ -1154,6 +1214,7 @@
verifyNeverLights();
assertFalse(summary.isInterruptive());
+ assertFalse(summary.getAudiblyAlerted());
}
@Test
@@ -1164,6 +1225,7 @@
verifyLights();
assertTrue(child.isInterruptive());
+ assertFalse(child.getAudiblyAlerted());
}
@Test
@@ -1174,6 +1236,7 @@
verifyLights();
assertTrue(nonGroup.isInterruptive());
+ assertFalse(nonGroup.getAudiblyAlerted());
}
@Test
@@ -1184,6 +1247,7 @@
verifyLights();
assertTrue(group.isInterruptive());
+ assertFalse(group.getAudiblyAlerted());
}
static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index f255d49..bcba15d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -38,12 +38,10 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.Parcel;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.SnoozeCriterion;
-import android.service.notification.StatusBarNotification;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
@@ -94,6 +92,7 @@
assertEquals(getShowBadge(i), ranking.canShowBadge());
assertEquals(getUserSentiment(i), ranking.getUserSentiment());
assertEquals(getHidden(i), ranking.isSuspended());
+ assertEquals(audiblyAlerted(i), ranking.audiblyAlerted());
assertActionsEqual(getSmartActions(key, i), ranking.getSmartActions());
assertEquals(getSmartReplies(key, i), ranking.getSmartReplies());
}
@@ -114,6 +113,8 @@
Bundle mHidden = new Bundle();
Bundle smartActions = new Bundle();
Bundle smartReplies = new Bundle();
+ Bundle audiblyAlerted = new Bundle();
+ Bundle noisy = new Bundle();
for (int i = 0; i < mKeys.length; i++) {
String key = mKeys[i];
@@ -133,12 +134,14 @@
mHidden.putBoolean(key, getHidden(i));
smartActions.putParcelableArrayList(key, getSmartActions(key, i));
smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
+ audiblyAlerted.putBoolean(key, audiblyAlerted(i));
+ noisy.putBoolean(key, getNoisy(i));
}
NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
interceptedKeys.toArray(new String[0]), visibilityOverrides,
suppressedVisualEffects, importance, explanation, overrideGroupKeys,
channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
- smartActions, smartReplies);
+ smartActions, smartReplies, audiblyAlerted, noisy);
return update;
}
@@ -190,6 +193,14 @@
return index % 2 == 0;
}
+ private boolean audiblyAlerted(int index) {
+ return index < 2;
+ }
+
+ private boolean getNoisy(int index) {
+ return index < 1;
+ }
+
private ArrayList<String> getPeople(String key, int index) {
ArrayList<String> people = new ArrayList<>();
for (int i = 0; i < index; i++) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 1b59e75..9b41fdd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -801,4 +801,16 @@
assertEquals(1.0f, record.getContactAffinity());
assertEquals(IMPORTANCE_LOW, record.getImportance());
}
+
+ @Test
+ public void testSetAudiblyAlerted() {
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, groupId /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+ record.setAudiblyAlerted(true);
+
+ assertTrue(record.getAudiblyAlerted());
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index ae0e35b..32f389a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -31,9 +31,11 @@
import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.media.AudioAttributes;
import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenModeConfig;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -43,7 +45,6 @@
import com.android.server.UiServiceTestCase;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -70,11 +71,11 @@
private NotificationRecord getNotificationRecord(NotificationChannel c) {
StatusBarNotification sbn = mock(StatusBarNotification.class);
- when(sbn.getNotification()).thenReturn(mock(Notification.class));
+ Notification notification = mock(Notification.class);
+ when(sbn.getNotification()).thenReturn(notification);
return new NotificationRecord(mContext, sbn, c);
}
- @Ignore
@Test
public void testIsMessage() {
NotificationRecord r = getNotificationRecord();
@@ -86,7 +87,6 @@
assertFalse(mZenModeFiltering.isMessage(r));
}
- @Ignore
@Test
public void testIsAlarm() {
NotificationChannel c = mock(NotificationChannel.class);
@@ -101,7 +101,6 @@
assertTrue(mZenModeFiltering.isAlarm(r));
}
- @Ignore
@Test
public void testIsAlarm_wrongCategory() {
NotificationRecord r = getNotificationRecord();
@@ -109,7 +108,6 @@
assertFalse(mZenModeFiltering.isAlarm(r));
}
- @Ignore
@Test
public void testIsAlarm_wrongUsage() {
NotificationChannel c = mock(NotificationChannel.class);
@@ -120,7 +118,6 @@
assertFalse(mZenModeFiltering.isAlarm(r));
}
- @Ignore
@Test
public void testSuppressDNDInfo_yes_VisEffectsAllowed() {
NotificationRecord r = getNotificationRecord();
@@ -132,7 +129,6 @@
assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
}
- @Ignore
@Test
public void testSuppressDNDInfo_yes_WrongId() {
NotificationRecord r = getNotificationRecord();
@@ -143,7 +139,6 @@
assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
}
- @Ignore
@Test
public void testSuppressDNDInfo_yes_WrongPackage() {
NotificationRecord r = getNotificationRecord();
@@ -154,7 +149,6 @@
assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
}
- @Ignore
@Test
public void testSuppressDNDInfo_no() {
NotificationRecord r = getNotificationRecord();
@@ -167,7 +161,6 @@
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
}
- @Ignore
@Test
public void testSuppressAnything_yes_ZenModeOff() {
NotificationRecord r = getNotificationRecord();
@@ -177,7 +170,6 @@
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, policy, r));
}
- @Ignore
@Test
public void testSuppressAnything_bypass_ZenModeOn() {
NotificationRecord r = getNotificationRecord();
diff --git a/services/tests/wmtests/Android.mk b/services/tests/wmtests/Android.mk
index dd656c30..9655b3d 100644
--- a/services/tests/wmtests/Android.mk
+++ b/services/tests/wmtests/Android.mk
@@ -23,6 +23,7 @@
truth-prebuilt \
testables \
ub-uiautomator \
+ hamcrest-library
LOCAL_JAVA_LIBRARIES := \
android.test.mock \
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index d3f1a0a..7a9c8dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -27,7 +28,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.platform.test.annotations.Presubmit;
@@ -120,6 +126,39 @@
assertTrue(stack2.isFocusedStackOnDisplay());
}
+ /**
+ * Verifies {@link ActivityDisplay#remove} should not resume home stack on the removing display.
+ */
+ @Test
+ public void testNotResumeHomeStackOnRemovingDisplay() {
+ // Create a display which supports system decoration and allows reparenting stacks to
+ // another display when the display is removed.
+ final ActivityDisplay display = spy(createNewActivityDisplay());
+ doReturn(false).when(display).shouldDestroyContentOnRemove();
+ doReturn(true).when(display).supportsSystemDecorations();
+ mSupervisor.addChild(display, ActivityDisplay.POSITION_TOP);
+
+ // Put home stack on the display.
+ final ActivityStack homeStack = display.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(homeStack).build();
+ new ActivityBuilder(mService).setTask(task).build();
+ display.removeChild(homeStack);
+ final ActivityStack spiedHomeStack = spy(homeStack);
+ display.addChild(spiedHomeStack, ActivityDisplay.POSITION_TOP);
+ reset(spiedHomeStack);
+
+ // Put a finishing standard activity which will be reparented.
+ final ActivityStack stack = createFullscreenStackWithSimpleActivityAt(display);
+ stack.topRunningActivityLocked().makeFinishingLocked();
+
+ display.remove();
+
+ // The removed display should have no focused stack and its home stack should never resume.
+ assertNull(display.getFocusedStack());
+ verify(spiedHomeStack, never()).resumeTopActivityUncheckedLocked(any(), any());
+ }
+
private ActivityStack createFullscreenStackWithSimpleActivityAt(ActivityDisplay display) {
final ActivityStack fullscreenStack = display.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
new file mode 100644
index 0000000..215c51d
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityManager.START_SUCCESS;
+import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.content.Intent;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.util.SparseIntArray;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link ActivityMetricsLaunchObserver} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:ActivityMetricsLaunchObserverTests
+ */
+@SmallTest
+@Presubmit
+@FlakyTest(detail="promote once confirmed non-flaky")
+public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
+ private ActivityMetricsLogger mActivityMetricsLogger;
+ private ActivityMetricsLaunchObserver mLaunchObserver;
+
+ private TestActivityStack mStack;
+ private TaskRecord mTask;
+ private ActivityRecord mActivityRecord;
+ private ActivityRecord mActivityRecordTrampoline;
+
+ @Before
+ public void setUpAMLO() throws Exception {
+ setupActivityTaskManagerService();
+
+ mActivityMetricsLogger =
+ new ActivityMetricsLogger(mSupervisor, mService.mContext, mService.mH.getLooper());
+
+ mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
+
+ // TODO: Use ActivityMetricsLaunchObserverRegistry .
+ java.lang.reflect.Field f =
+ mActivityMetricsLogger.getClass().getDeclaredField("mLaunchObserver");
+ f.setAccessible(true);
+ f.set(mActivityMetricsLogger, mLaunchObserver);
+
+ // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
+ // This seems to be the easiest way to create an ActivityRecord.
+ mStack = mSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
+ mActivityRecord = new ActivityBuilder(mService).setTask(mTask).build();
+ mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
+ }
+
+ @Test
+ public void testOnIntentStarted() throws Exception {
+ Intent intent = new Intent("action 1");
+
+ mActivityMetricsLogger.notifyActivityLaunching(intent);
+
+ verify(mLaunchObserver).onIntentStarted(eq(intent));
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnIntentFailed() throws Exception {
+ testOnIntentStarted();
+
+ ActivityRecord activityRecord = null;
+
+ // Bringing an intent that's already running 'to front' is not considered
+ // as an ACTIVITY_LAUNCHED state transition.
+ mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
+ activityRecord);
+
+ verify(mLaunchObserver).onIntentFailed();
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnActivityLaunched() throws Exception {
+ testOnIntentStarted();
+
+ mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
+ mActivityRecord);
+
+ verify(mLaunchObserver).onActivityLaunched(eq(mActivityRecord), anyInt());
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnActivityLaunchFinished() throws Exception {
+ testOnActivityLaunched();
+
+ mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+ SystemClock.uptimeMillis());
+
+ mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecord.getWindowingMode(),
+ SystemClock.uptimeMillis());
+
+ verify(mLaunchObserver).onActivityLaunchFinished(eq(mActivityRecord));
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnActivityLaunchCancelled() throws Exception {
+ testOnActivityLaunched();
+
+ mActivityRecord.nowVisible = true;
+
+ // Cannot time already-visible activities.
+ mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mActivityRecord);
+
+ verify(mLaunchObserver).onActivityLaunchCancelled(eq(mActivityRecord));
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnActivityLaunchedTrampoline() throws Exception {
+ testOnIntentStarted();
+
+ mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
+ mActivityRecord);
+
+ verify(mLaunchObserver).onActivityLaunched(eq(mActivityRecord), anyInt());
+
+ // A second, distinct, activity launch is coalesced into the the current app launch sequence
+ mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
+ mActivityRecordTrampoline);
+
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnActivityLaunchFinishedTrampoline() throws Exception {
+ testOnActivityLaunchedTrampoline();
+
+ mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+ SystemClock.uptimeMillis());
+
+ mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecordTrampoline.getWindowingMode(),
+ SystemClock.uptimeMillis());
+
+ verify(mLaunchObserver).onActivityLaunchFinished(eq(mActivityRecordTrampoline));
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+
+ @Test
+ public void testOnActivityLaunchCancelledTrampoline() throws Exception {
+ testOnActivityLaunchedTrampoline();
+
+ mActivityRecordTrampoline.nowVisible = true;
+
+ // Cannot time already-visible activities.
+ mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
+ mActivityRecordTrampoline);
+
+ verify(mLaunchObserver).onActivityLaunchCancelled(eq(mActivityRecordTrampoline));
+ verifyNoMoreInteractions(mLaunchObserver);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index a794d6d..f692a57 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -25,12 +25,12 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
-
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -54,6 +54,8 @@
import android.app.ActivityOptions;
import android.app.WaitResult;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -436,7 +438,7 @@
* Tests that home activities can be started on the displays that supports system decorations.
*/
@Test
- public void testStartHomeOnAllDisplays() throws Exception {
+ public void testStartHomeOnAllDisplays() {
// Create secondary displays.
final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
mSupervisor.addChild(secondDisplay, POSITION_TOP);
@@ -450,7 +452,7 @@
.create(any(), anyInt(), any(), any(), any(), any());
doReturn(true).when(mService.mStackSupervisor)
.ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
- doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt());
+ doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt(), anyBoolean());
mSupervisor.startHomeOnAllDisplays(0, "testStartHome");
@@ -458,4 +460,49 @@
assertNotNull(secondDisplay.getTopStack());
assertTrue(secondDisplay.getTopStack().isActivityTypeHome());
}
+
+ /**
+ * Tests that home activities won't be started before booting when display added.
+ */
+ @Test
+ public void testNotStartHomeBeforeBoot() {
+ final int displayId = 1;
+ final boolean isBooting = mService.mAmInternal.isBooting();
+ final boolean isBooted = mService.mAmInternal.isBooted();
+ try {
+ mService.mAmInternal.setBooting(false);
+ mService.mAmInternal.setBooted(false);
+ mSupervisor.onDisplayAdded(displayId);
+ verify(mSupervisor, never()).startHomeOnDisplay(anyInt(), any(), anyInt());
+ } finally {
+ mService.mAmInternal.setBooting(isBooting);
+ mService.mAmInternal.setBooted(isBooted);
+ }
+ }
+
+ /**
+ * Tests whether home can be started if being instrumented.
+ */
+ @Test
+ public void testCanStartHomeWhenInstrumented() {
+ final ActivityInfo info = new ActivityInfo();
+ info.applicationInfo = new ApplicationInfo();
+ final WindowProcessController app = mock(WindowProcessController.class);
+ doReturn(app).when(mService).getProcessController(any(), anyInt());
+
+ // Can not start home if we don't want to start home while home is being instrumented.
+ doReturn(true).when(app).isInstrumenting();
+ assertFalse(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ false /* allowInstrumenting*/));
+
+ // Can start home for other cases.
+ assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ true /* allowInstrumenting*/));
+
+ doReturn(false).when(app).isInstrumenting();
+ assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ false /* allowInstrumenting*/));
+ assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ true /* allowInstrumenting*/));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 974e285..62767e3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -457,7 +457,7 @@
final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
- final TestActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
homeStack.setIsTranslucent(false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 9d28c57..c35e4d6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -153,8 +153,7 @@
void setupActivityManagerService(
TestActivityManagerService am, TestActivityTaskManagerService atm) {
- atm.setActivityManagerService(am, am.mHandlerThread.getLooper(), am.mIntentFirewall,
- am.mPendingIntentController);
+ atm.setActivityManagerService(am.mIntentFirewall, am.mPendingIntentController);
atm.mAmInternal = am.getLocalService();
am.mAtmInternal = atm.getLocalService();
// Makes sure the supervisor is using with the spy object.
@@ -629,7 +628,7 @@
}
private static WindowManagerService prepareMockWindowManager() {
- final WindowManagerService service = WindowTestUtils.getMockWindowManagerService();
+ final WindowManagerService service = mock(WindowManagerService.class);
doAnswer((InvocationOnMock invocationOnMock) -> {
final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 4455630..72d7c90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -19,9 +19,12 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import android.app.ActivityManager;
@@ -92,6 +95,18 @@
assertNotNull(TaskRecord.getTaskRecordFactory());
}
+ /** Ensure we have no chance to modify the original intent. */
+ @Test
+ public void testCopyBaseIntentForTaskInfo() {
+ final TaskRecord task = createTaskRecord(1);
+ task.lastTaskDescription = new ActivityManager.TaskDescription();
+ final ActivityManager.RecentTaskInfo info = new ActivityManager.RecentTaskInfo();
+ task.fillTaskInfo(info, new TaskRecord.TaskActivitiesReport());
+
+ // The intent of info should be a copy so assert that they are different instances.
+ assertThat(info.baseIntent, not(sameInstance(task.getBaseIntent())));
+ }
+
@Test
public void testCreateTestRecordUsingCustomizedFactory() throws Exception {
TestTaskRecordFactory factory = new TestTaskRecordFactory();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 115bcb1..3b4ab38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -38,15 +38,6 @@
* to WindowManager related test functionality.
*/
public class WindowTestUtils {
- private static int sNextTaskId = 0;
-
- /** Retrieves an instance of a mock {@link WindowManagerService}. */
- static WindowManagerService getMockWindowManagerService() {
- final WindowManagerService service = mock(WindowManagerService.class);
- final WindowManagerGlobalLock lock = new WindowManagerGlobalLock();
- doReturn(lock).when(service).getWindowManagerLock();
- return service;
- }
/** An extension of {@link DisplayContent} to gain package scoped access. */
public static class TestDisplayContent extends DisplayContent {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 6a74564..4f573a4 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -30,18 +30,19 @@
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_NOTIFICATION_SEEN;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED_PRIV;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYNC_ADAPTER;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_UPDATE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
-import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED;
-import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED_PRIV;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
@@ -340,14 +341,21 @@
}
void setAppIdleEnabled(boolean enabled) {
- mAppIdleEnabled = enabled;
+ synchronized (mAppIdleLock) {
+ if (mAppIdleEnabled != enabled) {
+ final boolean oldParoleState = isParoledOrCharging();
+ mAppIdleEnabled = enabled;
+ if (isParoledOrCharging() != oldParoleState) {
+ postParoleStateChanged();
+ }
+ }
+ }
}
public void onBootPhase(int phase) {
mInjector.onBootPhase(phase);
if (phase == PHASE_SYSTEM_SERVICES_READY) {
Slog.d(TAG, "Setting app idle enabled state");
- setAppIdleEnabled(mInjector.isAppIdleEnabled());
// Observe changes to the threshold
SettingsObserver settingsObserver = new SettingsObserver(mHandler);
settingsObserver.registerObserver();
@@ -1842,8 +1850,6 @@
mContext.getContentResolver(),
Global.APP_IDLE_CONSTANTS));
}
- // Check if app_idle_enabled has changed
- setAppIdleEnabled(mInjector.isAppIdleEnabled());
// Look at global settings for this.
// TODO: Maybe apply different thresholds for different users.
@@ -1915,6 +1921,10 @@
(KEY_STABLE_CHARGING_THRESHOLD,
COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD);
}
+
+ // Check if app_idle_enabled has changed. Do this after getting the rest of the settings
+ // in case we need to change something based on the new values.
+ setAppIdleEnabled(mInjector.isAppIdleEnabled());
}
long[] parseLongArray(String values, long[] defaults) {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 27b8cdf..60cb08f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -153,6 +153,7 @@
private static final int MSG_SET_FUNCTIONS_TIMEOUT = 15;
private static final int MSG_GET_CURRENT_USB_FUNCTIONS = 16;
private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17;
+ private static final int MSG_GADGET_HAL_REGISTERED = 18;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -1708,10 +1709,16 @@
protected static final String CTL_STOP = "ctl.stop";
/**
- * Adb natvie daemon
+ * Adb native daemon.
*/
protected static final String ADBD = "adbd";
+ /**
+ * Gadget HAL fully qualified instance name for registering for ServiceNotification.
+ */
+ protected static final String GADGET_HAL_FQ_NAME =
+ "android.hardware.usb.gadget@1.0::IUsbGadget";
+
protected boolean mCurrentUsbFunctionsRequested;
UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager,
@@ -1721,8 +1728,7 @@
ServiceNotification serviceNotification = new ServiceNotification();
boolean ret = IServiceManager.getService()
- .registerForNotifications("android.hardware.usb.gadget@1.0::IUsbGadget",
- "", serviceNotification);
+ .registerForNotifications(GADGET_HAL_FQ_NAME, "", serviceNotification);
if (!ret) {
Slog.e(TAG, "Failed to register usb gadget service start notification");
return;
@@ -1764,20 +1770,12 @@
@Override
public void onRegistration(String fqName, String name, boolean preexisting) {
Slog.i(TAG, "Usb gadget hal service started " + fqName + " " + name);
- synchronized (mGadgetProxyLock) {
- try {
- mGadgetProxy = IUsbGadget.getService();
- mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
- USB_GADGET_HAL_DEATH_COOKIE);
- if (!mCurrentFunctionsApplied && !mCurrentUsbFunctionsRequested) {
- setEnabledFunctions(mCurrentFunctions, false);
- }
- } catch (NoSuchElementException e) {
- Slog.e(TAG, "Usb gadget hal not found", e);
- } catch (RemoteException e) {
- Slog.e(TAG, "Usb Gadget hal not responding", e);
- }
+ if (!fqName.equals(GADGET_HAL_FQ_NAME)) {
+ Slog.e(TAG, "fqName does not match");
+ return;
}
+
+ sendMessage(MSG_GADGET_HAL_REGISTERED, preexisting);
}
}
@@ -1815,6 +1813,23 @@
setEnabledFunctions(UsbManager.FUNCTION_NONE, !isAdbEnabled());
}
break;
+ case MSG_GADGET_HAL_REGISTERED:
+ boolean preexisting = msg.arg1 == 1;
+ synchronized (mGadgetProxyLock) {
+ try {
+ mGadgetProxy = IUsbGadget.getService();
+ mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
+ USB_GADGET_HAL_DEATH_COOKIE);
+ if (!mCurrentFunctionsApplied && !preexisting) {
+ setEnabledFunctions(mCurrentFunctions, false);
+ }
+ } catch (NoSuchElementException e) {
+ Slog.e(TAG, "Usb gadget hal not found", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Usb Gadget hal not responding", e);
+ }
+ }
+ break;
default:
super.handleMessage(msg);
}
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index 0121d30..84add88 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -40,7 +40,6 @@
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
-import android.os.Binder;
import android.os.UserHandle;
import android.service.usb.UsbAccessoryAttachedActivities;
import android.service.usb.UsbDeviceAttachedActivities;
@@ -190,9 +189,8 @@
@Nullable UsbAccessory accessory,
boolean canBeDefault,
String packageName,
- PendingIntent pi) {
- final int uid = Binder.getCallingUid();
-
+ PendingIntent pi,
+ int uid) {
// compare uid with packageName to foil apps pretending to be someone else
try {
ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0);
@@ -235,7 +233,8 @@
}
}
- requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi);
+ requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi,
+ uid);
}
public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi,
@@ -253,8 +252,8 @@
return;
}
- requestPermissionDialog(null, accessory,
- canBeDefault(accessory, packageName), packageName, pi);
+ requestPermissionDialog(null, accessory, canBeDefault(accessory, packageName), packageName,
+ pi, uid);
}
public void grantDevicePermission(UsbDevice device, int uid) {
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index 3681529..0c40a6b 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -16,10 +16,15 @@
cc_defaults {
name: "viewcompiler_defaults",
+ header_libs: [
+ "libbase_headers",
+ ],
shared_libs: [
+ "libbase",
"libdexfile",
"slicer",
],
+ cppflags: ["-std=c++17"],
}
cc_library_host_static {
@@ -30,9 +35,6 @@
"java_lang_builder.cc",
"util.cc",
],
- static_libs: [
- "libbase",
- ],
}
cc_binary_host {
@@ -42,7 +44,6 @@
"main.cc",
],
static_libs: [
- "libbase",
"libtinyxml2",
"libgflags",
"libviewcompiler",
@@ -59,4 +60,24 @@
static_libs: [
"libviewcompiler",
],
+ test_suites: ["general-tests"],
+}
+
+cc_binary_host {
+ name: "dex_testcase_generator",
+ defaults: ["viewcompiler_defaults"],
+ srcs: ["dex_testcase_generator.cc"],
+ static_libs: [
+ "libviewcompiler",
+ ],
+}
+
+genrule {
+ name: "generate_dex_testcases",
+ tools: [":dex_testcase_generator"],
+ cmd: "$(location :dex_testcase_generator) $(genDir)",
+ out: [
+ "simple.dex",
+ "trivial.dex",
+ ],
}
diff --git a/startop/view_compiler/README.md b/startop/view_compiler/README.md
index 5659501..f8da02b 100644
--- a/startop/view_compiler/README.md
+++ b/startop/view_compiler/README.md
@@ -23,3 +23,31 @@
application.
* This only works for apps that do not use a custom layout inflater.
* Other limitations yet to be discovered.
+
+## DexBuilder Tests
+
+The DexBuilder has several low-level end to end tests to verify generated DEX
+code validates, runs, and has the correct behavior. There are, unfortunately, a
+number of pieces that must be added to generate new tests. Here are the
+components:
+
+* `dex_testcase_generator` - Written in C++ using `DexBuilder`. This runs as a
+ build step produce the DEX files that will be tested on device. See the
+ `genrule` named `generate_dex_testcases` in `Android.bp`. These files are then
+ copied over to the device by TradeFed when running tests.
+* `DexBuilderTest` - This is a Java Language test harness that loads the
+ generated DEX files and exercises methods in the file.
+
+To add a new DEX file test, follow these steps:
+1. Modify `dex_testcase_generator` to produce the DEX file.
+2. Add the filename to the `out` list of the `generate_dex_testcases` rule in
+ `Android.bp`.
+3. Add a new `push` option to `AndroidTest.xml` to copy the DEX file to the
+ device.
+4. Modify `DexBuilderTest.java` to load and exercise the new test.
+
+In each case, you should be able to cargo-cult the existing test cases.
+
+In general, you can probably get by without adding a new generated DEX file, and
+instead add more methods to the files that are already generated. In this case,
+you can skip all of steps 2 and 3 above, and simplify steps 1 and 4.
diff --git a/startop/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
index cc4b17a..5d675b7 100644
--- a/startop/view_compiler/TEST_MAPPING
+++ b/startop/view_compiler/TEST_MAPPING
@@ -1,7 +1,7 @@
{
"presubmit": [
{
- "name": "view-compiler-tests"
+ "name": "dex-builder-test"
}
]
}
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 7a9f41f..13e7f73 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -22,14 +22,16 @@
#include <fstream>
#include <memory>
+#define DCHECK_NOT_NULL(p) DCHECK((p) != nullptr)
+
namespace startop {
namespace dex {
using std::shared_ptr;
using std::string;
-using art::Instruction;
using ::dex::kAccPublic;
+using Op = Instruction::Op;
const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; };
const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; };
@@ -43,6 +45,20 @@
} // namespace
+std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {
+ switch (opcode) {
+ case Instruction::Op::kReturn:
+ out << "kReturn";
+ return out;
+ case Instruction::Op::kMove:
+ out << "kMove";
+ return out;
+ case Instruction::Op::kInvokeVirtual:
+ out << "kInvokeVirtual";
+ return out;
+ }
+}
+
void* TrackingAllocator::Allocate(size_t size) {
std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size);
void* raw_buffer = buffer.get();
@@ -56,7 +72,7 @@
//
// package dextest;
// public class DexTest {
-// public static int foo() { return 5; }
+// public static int foo(String s) { return s.length(); }
// }
void WriteTestDexFile(const string& filename) {
DexBuilder dex_file;
@@ -64,11 +80,17 @@
ClassBuilder cbuilder{dex_file.MakeClass("dextest.DexTest")};
cbuilder.set_source_file("dextest.java");
- MethodBuilder method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int()})};
+ TypeDescriptor string_type = TypeDescriptor::FromClassname("java.lang.String");
- MethodBuilder::Register r = method.MakeRegister();
- method.BuildConst4(r, 5);
- method.BuildReturn(r);
+ MethodBuilder method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int(), string_type})};
+
+ Value result = method.MakeRegister();
+
+ MethodDeclData string_length =
+ dex_file.GetOrDeclareMethod(string_type, "length", Prototype{TypeDescriptor::Int()});
+
+ method.AddInstruction(Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+ method.BuildReturn(result);
method.Encode();
@@ -78,6 +100,10 @@
out_file.write(image.ptr<const char>(), image.size());
}
+TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) {
+ return TypeDescriptor{art::DotToDescriptor(name.c_str())};
+}
+
DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} {
dex_file_->magic = slicer::MemView{kDexFileMagic, sizeof(kDexFileMagic)};
}
@@ -119,10 +145,9 @@
class_def->type = type_def;
class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object"));
class_def->access_flags = kAccPublic;
- return ClassBuilder{this, class_def};
+ return ClassBuilder{this, name, class_def};
}
-// TODO(eholk): we probably want GetOrAddString() also
ir::Type* DexBuilder::GetOrAddType(const std::string& descriptor) {
if (types_by_descriptor_.find(descriptor) != types_by_descriptor_.end()) {
return types_by_descriptor_[descriptor];
@@ -158,16 +183,11 @@
return shorty;
}
-ClassBuilder::ClassBuilder(DexBuilder* parent, ir::Class* class_def)
- : parent_(parent), class_(class_def) {}
+ClassBuilder::ClassBuilder(DexBuilder* parent, const std::string& name, ir::Class* class_def)
+ : parent_(parent), type_descriptor_{TypeDescriptor::FromClassname(name)}, class_(class_def) {}
MethodBuilder ClassBuilder::CreateMethod(const std::string& name, Prototype prototype) {
- ir::String* dex_name{parent_->GetOrAddString(name)};
-
- auto* decl = parent_->Alloc<ir::MethodDecl>();
- decl->name = dex_name;
- decl->parent = class_->type;
- decl->prototype = prototype.Encode(parent_);
+ ir::MethodDecl* decl = parent_->GetOrDeclareMethod(type_descriptor_, name, prototype).decl;
return MethodBuilder{parent_, class_, decl};
}
@@ -187,8 +207,13 @@
method->access_flags = kAccPublic | ::dex::kAccStatic;
auto* code = dex_->Alloc<ir::Code>();
- code->registers = num_registers_;
- // TODO: support ins and outs
+ DCHECK_NOT_NULL(decl_->prototype);
+ size_t const num_args =
+ decl_->prototype->param_types != nullptr ? decl_->prototype->param_types->types.size() : 0;
+ code->registers = num_registers_ + num_args;
+ code->ins_count = num_args;
+ code->outs_count = decl_->prototype->return_type == dex_->GetOrAddType("V") ? 0 : 1;
+ EncodeInstructions();
code->instructions = slicer::ArrayView<const ::dex::u2>(buffer_.data(), buffer_.size());
method->code = code;
@@ -197,17 +222,135 @@
return method;
}
-MethodBuilder::Register MethodBuilder::MakeRegister() { return num_registers_++; }
+Value MethodBuilder::MakeRegister() { return Value::Local(num_registers_++); }
-void MethodBuilder::BuildReturn() { buffer_.push_back(Instruction::RETURN_VOID); }
+void MethodBuilder::AddInstruction(Instruction instruction) {
+ instructions_.push_back(instruction);
+}
-void MethodBuilder::BuildReturn(Register src) { buffer_.push_back(Instruction::RETURN | src << 8); }
+void MethodBuilder::BuildReturn() { AddInstruction(Instruction::OpNoArgs(Op::kReturn)); }
-void MethodBuilder::BuildConst4(Register target, int value) {
+void MethodBuilder::BuildReturn(Value src) {
+ AddInstruction(Instruction::OpWithArgs(Op::kReturn, /*destination=*/{}, src));
+}
+
+void MethodBuilder::BuildConst4(Value target, int value) {
DCHECK_LT(value, 16);
- // TODO: support more registers
- DCHECK_LT(target, 16);
- buffer_.push_back(Instruction::CONST_4 | (value << 12) | (target << 8));
+ AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
+}
+
+void MethodBuilder::EncodeInstructions() {
+ buffer_.clear();
+ for (const auto& instruction : instructions_) {
+ EncodeInstruction(instruction);
+ }
+}
+
+void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
+ switch (instruction.opcode()) {
+ case Instruction::Op::kReturn:
+ return EncodeReturn(instruction);
+ case Instruction::Op::kMove:
+ return EncodeMove(instruction);
+ case Instruction::Op::kInvokeVirtual:
+ return EncodeInvokeVirtual(instruction);
+ }
+}
+
+void MethodBuilder::EncodeReturn(const Instruction& instruction) {
+ DCHECK_EQ(Instruction::Op::kReturn, instruction.opcode());
+ DCHECK(!instruction.dest().has_value());
+ if (instruction.args().size() == 0) {
+ buffer_.push_back(art::Instruction::RETURN_VOID);
+ } else {
+ DCHECK(instruction.args().size() == 1);
+ size_t source = RegisterValue(instruction.args()[0]);
+ buffer_.push_back(art::Instruction::RETURN | source << 8);
+ }
+}
+
+void MethodBuilder::EncodeMove(const Instruction& instruction) {
+ DCHECK_EQ(Instruction::Op::kMove, instruction.opcode());
+ DCHECK(instruction.dest().has_value());
+ DCHECK(instruction.dest()->is_register() || instruction.dest()->is_parameter());
+ DCHECK_EQ(1, instruction.args().size());
+
+ const Value& source = instruction.args()[0];
+
+ if (source.is_immediate()) {
+ // TODO: support more registers
+ DCHECK_LT(RegisterValue(*instruction.dest()), 16);
+ DCHECK_LT(source.value(), 16);
+ buffer_.push_back(art::Instruction::CONST_4 | (source.value() << 12) |
+ (RegisterValue(*instruction.dest()) << 8));
+ } else {
+ UNIMPLEMENTED(FATAL);
+ }
+}
+
+void MethodBuilder::EncodeInvokeVirtual(const Instruction& instruction) {
+ DCHECK_EQ(Instruction::Op::kInvokeVirtual, instruction.opcode());
+
+ // TODO: support more than one argument (i.e. the this argument) and change this to DCHECK_GE
+ DCHECK_EQ(1, instruction.args().size());
+
+ const Value& this_arg = instruction.args()[0];
+
+ size_t real_reg = RegisterValue(this_arg) & 0xf;
+ buffer_.push_back(1 << 12 | art::Instruction::INVOKE_VIRTUAL);
+ buffer_.push_back(instruction.method_id());
+ buffer_.push_back(real_reg);
+
+ if (instruction.dest().has_value()) {
+ real_reg = RegisterValue(*instruction.dest());
+ buffer_.push_back(real_reg << 8 | art::Instruction::MOVE_RESULT);
+ }
+}
+
+size_t MethodBuilder::RegisterValue(Value value) const {
+ if (value.is_register()) {
+ return value.value();
+ } else if (value.is_parameter()) {
+ return value.value() + num_registers_;
+ }
+ DCHECK(false && "Must be either a parameter or a register");
+ return 0;
+}
+
+const MethodDeclData& DexBuilder::GetOrDeclareMethod(TypeDescriptor type, const std::string& name,
+ Prototype prototype) {
+ MethodDeclData& entry = method_id_map_[{type, name, prototype}];
+
+ if (entry.decl == nullptr) {
+ // This method has not already been declared, so declare it.
+ ir::MethodDecl* decl = dex_file_->Alloc<ir::MethodDecl>();
+ // The method id is the last added method.
+ size_t id = dex_file_->methods.size() - 1;
+
+ ir::String* dex_name{GetOrAddString(name)};
+ decl->name = dex_name;
+ decl->parent = GetOrAddType(type.descriptor());
+ decl->prototype = GetOrEncodeProto(prototype);
+
+ // update the index -> ir node map (see tools/dexter/slicer/dex_ir_builder.cc)
+ auto new_index = dex_file_->methods_indexes.AllocateIndex();
+ auto& ir_node = dex_file_->methods_map[new_index];
+ SLICER_CHECK(ir_node == nullptr);
+ ir_node = decl;
+ decl->orig_index = new_index;
+
+ entry = {id, decl};
+ }
+
+ return entry;
+}
+
+ir::Proto* DexBuilder::GetOrEncodeProto(Prototype prototype) {
+ ir::Proto*& ir_proto = proto_map_[prototype];
+ if (ir_proto == nullptr) {
+ ir_proto = prototype.Encode(this);
+ }
+ return ir_proto;
}
} // namespace dex
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index d280abc..e46655e 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -17,7 +17,9 @@
#define DEX_BUILDER_H_
#include <map>
+#include <optional>
#include <string>
+#include <unordered_map>
#include <vector>
#include "slicer/dex_ir.h"
@@ -45,7 +47,7 @@
virtual void Free(void* ptr);
private:
- std::map<void*, std::unique_ptr<uint8_t[]>> allocations_;
+ std::unordered_map<void*, std::unique_ptr<uint8_t[]>> allocations_;
};
// Represents a DEX type descriptor.
@@ -57,11 +59,17 @@
static const TypeDescriptor Int();
static const TypeDescriptor Void();
+ // Creates a type descriptor from a fully-qualified class name. For example, it turns the class
+ // name java.lang.Object into the descriptor Ljava/lang/Object.
+ static TypeDescriptor FromClassname(const std::string& name);
+
// Return the full descriptor, such as I or Ljava/lang/Object
const std::string& descriptor() const { return descriptor_; }
// Return the shorty descriptor, such as I or L
std::string short_descriptor() const { return descriptor().substr(0, 1); }
+ bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; }
+
private:
TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
@@ -82,11 +90,98 @@
// Get the shorty descriptor, such as VII for (Int, Int) -> Void
std::string Shorty() const;
+ bool operator<(const Prototype& rhs) const {
+ return std::make_tuple(return_type_, param_types_) <
+ std::make_tuple(rhs.return_type_, rhs.param_types_);
+ }
+
private:
const TypeDescriptor return_type_;
const std::vector<TypeDescriptor> param_types_;
};
+// Represents a DEX register or constant. We separate regular registers and parameters
+// because we will not know the real parameter id until after all instructions
+// have been generated.
+class Value {
+ public:
+ static constexpr Value Local(size_t id) { return Value{id, Kind::kLocalRegister}; }
+ static constexpr Value Parameter(size_t id) { return Value{id, Kind::kParameter}; }
+ static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; }
+
+ bool is_register() const { return kind_ == Kind::kLocalRegister; }
+ bool is_parameter() const { return kind_ == Kind::kParameter; }
+ bool is_immediate() const { return kind_ == Kind::kImmediate; }
+
+ size_t value() const { return value_; }
+
+ private:
+ enum class Kind { kLocalRegister, kParameter, kImmediate };
+
+ const size_t value_;
+ const Kind kind_;
+
+ constexpr Value(size_t value, Kind kind) : value_{value}, kind_{kind} {}
+};
+
+// A virtual instruction. We convert these to real instructions in MethodBuilder::Encode.
+// Virtual instructions are needed to keep track of information that is not known until all of the
+// code is generated. This information includes things like how many local registers are created and
+// branch target locations.
+class Instruction {
+ public:
+ // The operation performed by this instruction. These are virtual instructions that do not
+ // correspond exactly to DEX instructions.
+ enum class Op { kReturn, kMove, kInvokeVirtual };
+
+ ////////////////////////
+ // Named Constructors //
+ ////////////////////////
+
+ // For instructions with no return value and no arguments.
+ static inline Instruction OpNoArgs(Op opcode) {
+ return Instruction{opcode, /*method_id*/ 0, /*dest*/ {}};
+ }
+ // For most instructions, which take some number of arguments and have an optional return value.
+ template <typename... T>
+ static inline Instruction OpWithArgs(Op opcode, std::optional<const Value> dest, T... args) {
+ return Instruction{opcode, /*method_id*/ 0, dest, args...};
+ }
+ // For method calls.
+ template <typename... T>
+ static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest,
+ Value this_arg, T... args) {
+ return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...};
+ }
+
+ ///////////////
+ // Accessors //
+ ///////////////
+
+ Op opcode() const { return opcode_; }
+ size_t method_id() const { return method_id_; }
+ const std::optional<const Value>& dest() const { return dest_; }
+ const std::vector<const Value>& args() const { return args_; }
+
+ private:
+ inline Instruction(Op opcode, size_t method_id, std::optional<const Value> dest)
+ : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{} {}
+
+ template <typename... T>
+ inline constexpr Instruction(Op opcode, size_t method_id, std::optional<const Value> dest,
+ T... args)
+ : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{args...} {}
+
+ const Op opcode_;
+ // The index of the method to invoke, for kInvokeVirtual and similar opcodes.
+ const size_t method_id_{0};
+ const std::optional<const Value> dest_;
+ const std::vector<const Value> args_;
+};
+
+// Needed for CHECK_EQ, DCHECK_EQ, etc.
+std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode);
+
// Tools to help build methods and their bodies.
class MethodBuilder {
public:
@@ -95,42 +190,53 @@
// Encode the method into DEX format.
ir::EncodedMethod* Encode();
- // Registers are just represented by their number.
- using Register = size_t;
-
// Create a new register to be used to storing values. Note that these are not SSA registers, like
// might be expected in similar code generators. This does no liveness tracking or anything, so
// it's up to the caller to reuse registers as appropriate.
- Register MakeRegister();
+ Value MakeRegister();
/////////////////////////////////
// Instruction builder methods //
/////////////////////////////////
+ void AddInstruction(Instruction instruction);
+
// return-void
void BuildReturn();
- void BuildReturn(Register src);
+ void BuildReturn(Value src);
// const/4
- void BuildConst4(Register target, int value);
+ void BuildConst4(Value target, int value);
// TODO: add builders for more instructions
private:
+ void EncodeInstructions();
+ void EncodeInstruction(const Instruction& instruction);
+ void EncodeReturn(const Instruction& instruction);
+ void EncodeMove(const Instruction& instruction);
+ void EncodeInvokeVirtual(const Instruction& instruction);
+
+ // Converts a register or parameter to its DEX register number.
+ size_t RegisterValue(Value value) const;
+
DexBuilder* dex_;
ir::Class* class_;
ir::MethodDecl* decl_;
- // A buffer to hold instructions we are generating.
+ // A list of the instructions we will eventually encode.
+ std::vector<Instruction> instructions_;
+
+ // A buffer to hold instructions that have been encoded.
std::vector<::dex::u2> buffer_;
// How many registers we've allocated
- size_t num_registers_;
+ size_t num_registers_{0};
};
// A helper to build class definitions.
class ClassBuilder {
public:
- ClassBuilder(DexBuilder* parent, ir::Class* class_def);
+ ClassBuilder(DexBuilder* parent, const std::string& name, ir::Class* class_def);
void set_source_file(const std::string& source);
@@ -139,8 +245,15 @@
MethodBuilder CreateMethod(const std::string& name, Prototype prototype);
private:
- DexBuilder* parent_;
- ir::Class* class_;
+ DexBuilder* const parent_;
+ const TypeDescriptor type_descriptor_;
+ ir::Class* const class_;
+};
+
+// Keeps track of information needed to manipulate or call a method.
+struct MethodDeclData {
+ size_t id;
+ ir::MethodDecl* decl;
};
// Builds Dex files from scratch.
@@ -163,10 +276,19 @@
ClassBuilder MakeClass(const std::string& name);
// Add a type for the given descriptor, or return the existing one if it already exists.
- // See the TypeDescriptor class for help generating these.
+ // See the TypeDescriptor class for help generating these. GetOrAddType can be used to declare
+ // imported classes.
ir::Type* GetOrAddType(const std::string& descriptor);
+ // Returns the method id for the method, creating it if it has not been created yet.
+ const MethodDeclData& GetOrDeclareMethod(TypeDescriptor type, const std::string& name,
+ Prototype prototype);
+
private:
+ // Looks up the ir::Proto* corresponding to this given prototype, or creates one if it does not
+ // exist.
+ ir::Proto* GetOrEncodeProto(Prototype prototype);
+
std::shared_ptr<ir::DexFile> dex_file_;
// allocator_ is needed to be able to encode the image.
@@ -177,10 +299,29 @@
std::vector<std::unique_ptr<uint8_t[]>> string_data_;
// Keep track of what types we've defined so we can look them up later.
- std::map<std::string, ir::Type*> types_by_descriptor_;
+ std::unordered_map<std::string, ir::Type*> types_by_descriptor_;
+
+ struct MethodDescriptor {
+ TypeDescriptor type;
+ std::string name;
+ Prototype prototype;
+
+ inline bool operator<(const MethodDescriptor& rhs) const {
+ return std::make_tuple(type, name, prototype) <
+ std::make_tuple(rhs.type, rhs.name, rhs.prototype);
+ }
+ };
+
+ // Maps method declarations to their method index. This is needed to encode references to them.
+ // When we go to actually write the DEX file, slicer will re-assign these after correctly sorting
+ // the methods list.
+ std::map<MethodDescriptor, MethodDeclData> method_id_map_;
// Keep track of what strings we've defined so we can look them up later.
- std::map<std::string, ir::String*> strings_;
+ std::unordered_map<std::string, ir::String*> strings_;
+
+ // Keep track of already-encoded protos.
+ std::map<Prototype, ir::Proto*> proto_map_;
};
} // namespace dex
diff --git a/startop/view_compiler/dex_builder_test.cc b/startop/view_compiler/dex_builder_test.cc
index 0d8b854..61c86b4 100644
--- a/startop/view_compiler/dex_builder_test.cc
+++ b/startop/view_compiler/dex_builder_test.cc
@@ -40,6 +40,12 @@
return loaded_dex_file != nullptr;
}
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+// public static void foo() {}
+// }
TEST(DexBuilderTest, VerifyDexWithClassMethod) {
DexBuilder dex_file;
@@ -67,6 +73,12 @@
EXPECT_FALSE(EncodeAndVerify(&dex_file));
}
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+// public static int foo() { return 5; }
+// }
TEST(DexBuilderTest, VerifyDexReturn5) {
DexBuilder dex_file;
@@ -80,3 +92,51 @@
EXPECT_TRUE(EncodeAndVerify(&dex_file));
}
+
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+// public static int foo(int x) { return x; }
+// }
+TEST(DexBuilderTest, VerifyDexReturnIntParam) {
+ DexBuilder dex_file;
+
+ auto cbuilder{dex_file.MakeClass("dextest.DexTest")};
+
+ auto method{
+ cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+ method.BuildReturn(Value::Parameter(0));
+ method.Encode();
+
+ EXPECT_TRUE(EncodeAndVerify(&dex_file));
+}
+
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+// public static int foo(String s) { return s.length(); }
+// }
+TEST(DexBuilderTest, VerifyDexCallStringLength) {
+ DexBuilder dex_file;
+
+ auto cbuilder{dex_file.MakeClass("dextest.DexTest")};
+
+ MethodBuilder method{cbuilder.CreateMethod(
+ "foo", Prototype{TypeDescriptor::Int(), TypeDescriptor::FromClassname("java.lang.String")})};
+
+ Value result = method.MakeRegister();
+
+ MethodDeclData string_length =
+ dex_file.GetOrDeclareMethod(TypeDescriptor::FromClassname("java.lang.String"),
+ "length",
+ Prototype{TypeDescriptor::Int()});
+
+ method.AddInstruction(Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+ method.BuildReturn(result);
+
+ method.Encode();
+
+ EXPECT_TRUE(EncodeAndVerify(&dex_file));
+}
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
new file mode 100644
index 0000000..4449ea0
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2018 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.
+//
+
+android_test {
+ name: "dex-builder-test",
+ srcs: ["src/android/startop/test/DexBuilderTest.java"],
+ sdk_version: "current",
+ data: [":generate_dex_testcases"],
+ static_libs: [
+ "android-support-test",
+ "guava",
+ ],
+ manifest: "AndroidManifest.xml",
+ test_config: "AndroidTest.xml",
+ test_suites: ["general-tests"],
+}
diff --git a/startop/view_compiler/dex_builder_test/AndroidManifest.xml b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
new file mode 100644
index 0000000..6ac5fc5
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.startop.test" >
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.startop.test"
+ android:label="DexBuilder Tests"/>
+
+</manifest>
diff --git a/startop/view_compiler/dex_builder_test/AndroidTest.xml b/startop/view_compiler/dex_builder_test/AndroidTest.xml
new file mode 100644
index 0000000..6f90cf3
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Runs DexBuilder Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="dex-builder-test.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="trivial.dex->/data/local/tmp/dex-builder-test/trivial.dex" />
+ <option name="push" value="simple.dex->/data/local/tmp/dex-builder-test/simple.dex" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.startop.test" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
new file mode 100644
index 0000000..87b2578
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.startop.test;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import com.google.common.io.ByteStreams;
+import dalvik.system.InMemoryDexClassLoader;
+import dalvik.system.PathClassLoader;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+public class DexBuilderTest {
+ static ClassLoader loadDexFile(String filename) throws Exception {
+ return new PathClassLoader("/data/local/tmp/dex-builder-test/" + filename,
+ ClassLoader.getSystemClassLoader());
+ }
+
+ public void hello() {}
+
+ @Test
+ public void loadTrivialDex() throws Exception {
+ ClassLoader loader = loadDexFile("trivial.dex");
+ loader.loadClass("android.startop.test.testcases.Trivial");
+ }
+
+ @Test
+ public void return5() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("return5");
+ Assert.assertEquals(5, method.invoke(null));
+ }
+
+ @Test
+ public void returnParam() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnParam", int.class);
+ Assert.assertEquals(5, method.invoke(null, 5));
+ Assert.assertEquals(42, method.invoke(null, 42));
+ }
+
+ @Test
+ public void returnStringLength() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnStringLength", String.class);
+ Assert.assertEquals(13, method.invoke(null, "Hello, World!"));
+ }
+}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
new file mode 100644
index 0000000..898817b
--- /dev/null
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 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 "android-base/logging.h"
+#include "dex_builder.h"
+
+#include <fstream>
+#include <string>
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+
+using namespace startop::dex;
+using namespace std;
+
+void GenerateTrivialDexFile(const string& outdir) {
+ DexBuilder dex_file;
+
+ ClassBuilder cbuilder{dex_file.MakeClass("android.startop.test.testcases.Trivial")};
+ cbuilder.set_source_file("dex_testcase_generator.cc#GenerateTrivialDexFile");
+
+ slicer::MemView image{dex_file.CreateImage()};
+ std::ofstream out_file(outdir + "/trivial.dex");
+ out_file.write(image.ptr<const char>(), image.size());
+}
+
+// Generates test cases that test around 1 instruction.
+void GenerateSimpleTestCases(const string& outdir) {
+ DexBuilder dex_file;
+
+ ClassBuilder cbuilder{dex_file.MakeClass("android.startop.test.testcases.SimpleTests")};
+ cbuilder.set_source_file("dex_testcase_generator.cc#GenerateSimpleTestCases");
+
+ // int return5() { return 5; }
+ auto return5{cbuilder.CreateMethod("return5", Prototype{TypeDescriptor::Int()})};
+ Value r{return5.MakeRegister()};
+ return5.BuildConst4(r, 5);
+ return5.BuildReturn(r);
+ return5.Encode();
+
+ // // int returnParam(int x) { return x; }
+ auto returnParam{cbuilder.CreateMethod("returnParam",
+ Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+ returnParam.BuildReturn(Value::Parameter(0));
+ returnParam.Encode();
+
+ // int returnStringLength(String x) { return x.length(); }
+ auto string_type{TypeDescriptor::FromClassname("java.lang.String")};
+ MethodDeclData string_length{
+ dex_file.GetOrDeclareMethod(string_type, "length", Prototype{TypeDescriptor::Int()})};
+
+ auto returnStringLength{
+ cbuilder.CreateMethod("returnStringLength", Prototype{TypeDescriptor::Int(), string_type})};
+ Value result = returnStringLength.MakeRegister();
+ returnStringLength.AddInstruction(
+ Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+ returnStringLength.BuildReturn(result);
+ returnStringLength.Encode();
+
+ slicer::MemView image{dex_file.CreateImage()};
+ std::ofstream out_file(outdir + "/simple.dex");
+ out_file.write(image.ptr<const char>(), image.size());
+}
+
+int main(int argc, char** argv) {
+ CHECK_EQ(argc, 2);
+
+ string outdir = argv[1];
+
+ GenerateTrivialDexFile(outdir);
+ GenerateSimpleTestCases(outdir);
+}
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index f62b170..7db6940 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.app.Service;
+import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
@@ -229,7 +230,8 @@
callDetails.getTelecomCallId(),
response.getRejectCall(),
!response.getSkipCallLog(),
- !response.getSkipNotification());
+ !response.getSkipNotification(),
+ new ComponentName(getPackageName(), getClass().getName()));
} else {
mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
}
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 2bda648..1342038 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -180,7 +180,7 @@
}
}
- private final List<Event> mEvents = new LinkedList<>();
+ private final List<Event> mEvents = Collections.synchronizedList(new LinkedList<>());
private final Loggable mRecordEntry;
public EventRecord(Loggable recordEntry) {
@@ -197,7 +197,7 @@
}
public List<Event> getEvents() {
- return mEvents;
+ return new LinkedList<>(mEvents);
}
public List<EventTiming> extractEventTimings() {
@@ -207,21 +207,24 @@
LinkedList<EventTiming> result = new LinkedList<>();
Map<String, PendingResponse> pendingResponses = new HashMap<>();
- for (Event event : mEvents) {
- if (requestResponsePairs.containsKey(event.eventId)) {
- // This event expects a response, so add that expected response to the maps
- // of pending events.
- for (EventManager.TimedEventPair p : requestResponsePairs.get(event.eventId)) {
- pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
- event.time, p.mTimeoutMillis, p.mName));
+ synchronized (mEvents) {
+ for (Event event : mEvents) {
+ if (requestResponsePairs.containsKey(event.eventId)) {
+ // This event expects a response, so add that expected response to the maps
+ // of pending events.
+ for (EventManager.TimedEventPair p : requestResponsePairs.get(
+ event.eventId)) {
+ pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
+ event.time, p.mTimeoutMillis, p.mName));
+ }
}
- }
- PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
- if (pendingResponse != null) {
- long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
- if (elapsedTime < pendingResponse.timeoutMillis) {
- result.add(new EventTiming(pendingResponse.name, elapsedTime));
+ PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
+ if (pendingResponse != null) {
+ long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
+ if (elapsedTime < pendingResponse.timeoutMillis) {
+ result.add(new EventTiming(pendingResponse.name, elapsedTime));
+ }
}
}
}
@@ -233,7 +236,8 @@
pw.print(mRecordEntry.getDescription());
pw.increaseIndent();
- for (Event event : mEvents) {
+ // Iterate over copy of events so that this doesn't hold the lock for too long.
+ for (Event event : getEvents()) {
pw.print(event.timestampString);
pw.print(" - ");
pw.print(event.eventId);
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
index 2e0af27..d255ed1 100644
--- a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
@@ -16,6 +16,8 @@
package com.android.internal.telecom;
+import android.content.ComponentName;
+
/**
* Internal remote callback interface for call screening services.
*
@@ -30,5 +32,6 @@
String callId,
boolean shouldReject,
boolean shouldAddToCallLog,
- boolean shouldShowNotification);
+ boolean shouldShowNotification,
+ in ComponentName componentName);
}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index d7024cf..61d60e3 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2756,6 +2756,13 @@
"content://telephony/carriers/enforce_managed");
/**
+ * The {@code content://} style URL to be called from Telephony to query current APNs.
+ * @hide
+ */
+ public static final Uri SIM_APN_LIST = Uri.parse(
+ "content://telephony/carriers/sim_apn_list");
+
+ /**
* The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
* @hide
*/
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 99de4ca..fbc54ae6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1079,24 +1079,44 @@
"wfc_operator_error_codes_string_array";
/**
- * Indexes of SPN format strings in wfcSpnFormats and wfcDataSpnFormats.
+ * Indexes of SPN format strings in wfcSpnFormats.
*
* <p>Available options are:
* <ul>
- * <li> 0: %s</li>
- * <li> 1: %s Wi-Fi Calling</li>
- * <li> 2: WLAN Call</li>
- * <li> 3: %s WLAN Call</li>
- * <li> 4: %s Wi-Fi</li>
- * <li> 5: WiFi Calling | %s</li>
- * <li> 6: %s VoWifi</li>
+ * <li> 0: %s</li>
+ * <li> 1: %s Wi-Fi Calling</li>
+ * <li> 2: WLAN Call</li>
+ * <li> 3: %s WLAN Call</li>
+ * <li> 4: %s Wi-Fi</li>
+ * <li> 5: WiFi Calling | %s</li>
+ * <li> 6: %s VoWifi</li>
+ * <li> 7: Wi-Fi Calling</li>
+ * <li> 8: Wi-Fi</li>
+ * <li> 9: WiFi Calling</li>
+ * <li> 10: VoWifi</li>
* @hide
*/
public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
- /** @hide */
+
+ /**
+ * Indexes of data SPN format strings in wfcSpnFormats.
+ *
+ * @see KEY_WFC_SPN_FORMAT_IDX_INT for available options.
+ * @hide
+ */
public static final String KEY_WFC_DATA_SPN_FORMAT_IDX_INT = "wfc_data_spn_format_idx_int";
/**
+ * Indexes of SPN format strings in wfcSpnFormats used during flight mode.
+ *
+ * Set to -1 to use the value from KEY_WFC_SPN_FORMAT_IDX_INT also in this case.
+ * @see KEY_WFC_SPN_FORMAT_IDX_INT for other available options.
+ * @hide
+ */
+ public static final String KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT =
+ "wfc_flight_mode_spn_format_idx_int";
+
+ /**
* Use root locale when reading wfcSpnFormats.
*
* If true, then the root locale will always be used when reading wfcSpnFormats. This means the
@@ -1257,20 +1277,11 @@
public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
/**
- * Package name of the carrier settings activity.
- * @see {@link #KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING}.
+ * Flatten {@link android.content.ComponentName} of the carrier's settings activity.
* @hide
*/
- public static final String KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING =
- "carrier_settings_activity_package_name_string";
-
- /**
- * Class name of the carrier settings activity.
- * @see {@link #KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING}.
- * @hide
- */
- public static final String KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING =
- "carrier_settings_activity_class_name_string";
+ public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING =
+ "carrier_settings_activity_component_name_string";
// These variables are used by the MMS service and exposed through another API,
// SmsManager. The variable names and string values are copied from there.
@@ -2465,6 +2476,7 @@
sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null);
sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0);
sDefaults.putInt(KEY_WFC_DATA_SPN_FORMAT_IDX_INT, 0);
+ sDefaults.putInt(KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT, -1);
sDefaults.putBoolean(KEY_WFC_SPN_USE_ROOT_LOCALE, false);
sDefaults.putString(KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING, "");
sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
@@ -2615,8 +2627,7 @@
sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_WORLD_MODE_ENABLED_BOOL, false);
- sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING, "");
- sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING, "");
+ sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING, "");
sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
sDefaults.putIntArray(KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY,
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 76a0026..6958d22 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -190,6 +190,7 @@
case CellInfo.TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
case CellInfo.TYPE_TDSCDMA:
return CellIdentityTdscdma.createFromParcelBody(in);
+ case CellInfo.TYPE_NR: return CellIdentityNr.createFromParcelBody(in);
default: throw new IllegalArgumentException("Bad Cell identity Parcel");
}
}
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
new file mode 100644
index 0000000..6b1b84c
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
+
+import java.util.Objects;
+
+/**
+ * Information to represent a unique 5G NR cell.
+ */
+public final class CellIdentityNr extends CellIdentity {
+ private static final String TAG = "CellIdentityNr";
+
+ private final int mNrArfcn;
+ private final int mPci;
+ private final int mTac;
+
+ /**
+ *
+ * @param pci Physical Cell Id in range [0, 1007].
+ * @param tac 16-bit Tracking Area Code.
+ * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
+ * @param mccStr 3-digit Mobile Country Code in string format.
+ * @param mncStr 2 or 3-digit Mobile Network Code in string format.
+ * @param alphal long alpha Operator Name String or Enhanced Operator Name String.
+ * @param alphas short alpha Operator Name String or Enhanced Operator Name String.
+ *
+ * @hide
+ */
+ public CellIdentityNr(int pci, int tac, int nrArfcn, String mccStr, String mncStr,
+ String alphal, String alphas) {
+ super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas);
+ mPci = pci;
+ mTac = tac;
+ mNrArfcn = nrArfcn;
+ }
+
+ /**
+ * @return a CellLocation object for this CellIdentity.
+ * @hide
+ */
+ @Override
+ public CellLocation asCellLocation() {
+ return new GsmCellLocation();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), mPci, mTac, mNrArfcn);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof CellIdentityNr)) {
+ return false;
+ }
+
+ CellIdentityNr o = (CellIdentityNr) other;
+ return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn;
+ }
+
+ /**
+ * Get the Absolute Radio Frequency Channel Number.
+ * @return Integer value in range [0, 3279165] or {@link CellInfo#UNAVAILABLE} if unknown.
+ */
+ @Override
+ public int getChannelNumber() {
+ return mNrArfcn;
+ }
+
+ /**
+ * Get the physical cell id.
+ * @return Integer value in range [0, 1007] or {@link CellInfo#UNAVAILABLE} if unknown.
+ */
+ public int getPci() {
+ return mPci;
+ }
+
+ /**
+ * Get the tracking area code.
+ * @return a 16 bit integer or {@link CellInfo#UNAVAILABLE} if unknown.
+ */
+ public int getTac() {
+ return mTac;
+ }
+
+ /**
+ * @return Mobile Country Code in string format, or {@code null} if unknown.
+ */
+ public String getMccString() {
+ return mMccStr;
+ }
+
+ /**
+ * @return Mobile Network Code in string fomrat, or {@code null} if unknown.
+ */
+ public String getMncString() {
+ return mMncStr;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(TAG + ":{")
+ .append(" mPci = ").append(mPci)
+ .append(" mTac = ").append(mTac)
+ .append(" mNrArfcn = ").append(mNrArfcn)
+ .append(" mMcc = ").append(mMccStr)
+ .append(" mMnc = ").append(mMncStr)
+ .append(" mAlphaLong = ").append(mAlphaLong)
+ .append(" mAlphaShort = ").append(mAlphaShort)
+ .append(" }")
+ .toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int type) {
+ super.writeToParcel(dest, CellInfo.TYPE_NR);
+ dest.writeInt(mPci);
+ dest.writeInt(mTac);
+ dest.writeInt(mNrArfcn);
+ }
+
+ /** Construct from Parcel, type has already been processed */
+ private CellIdentityNr(Parcel in) {
+ super(TAG, CellInfo.TYPE_NR, in);
+ mPci = in.readInt();
+ mTac = in.readInt();
+ mNrArfcn = in.readInt();
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<CellIdentityNr> CREATOR =
+ new Creator<CellIdentityNr>() {
+ @Override
+ public CellIdentityNr createFromParcel(Parcel in) {
+ // Skip the type info.
+ in.readInt();
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public CellIdentityNr[] newArray(int size) {
+ return new CellIdentityNr[size];
+ }
+ };
+
+ /** @hide */
+ protected static CellIdentityNr createFromParcelBody(Parcel in) {
+ return new CellIdentityNr(in);
+ }
+}
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 1c63e82..d0b26876 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -42,38 +42,51 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+ @IntDef(prefix = "TYPE_",
+ value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA, TYPE_NR})
public @interface Type {}
+
/**
* Unknown cell identity type
* @hide
*/
- public static final int TYPE_UNKNOWN = 0;
+ public static final int TYPE_UNKNOWN = 0;
+
/**
* GSM cell identity type
* @hide
*/
- public static final int TYPE_GSM = 1;
+ public static final int TYPE_GSM = 1;
+
/**
* CDMA cell identity type
* @hide
*/
- public static final int TYPE_CDMA = 2;
+ public static final int TYPE_CDMA = 2;
+
/**
* LTE cell identity type
* @hide
*/
- public static final int TYPE_LTE = 3;
+ public static final int TYPE_LTE = 3;
+
/**
* WCDMA cell identity type
* @hide
*/
- public static final int TYPE_WCDMA = 4;
+ public static final int TYPE_WCDMA = 4;
+
/**
* TD-SCDMA cell identity type
* @hide
*/
- public static final int TYPE_TDSCDMA = 5;
+ public static final int TYPE_TDSCDMA = 5;
+
+ /**
+ * 5G cell identity type
+ * @hide
+ */
+ public static final int TYPE_NR = 6;
// Type to distinguish where time stamp gets recorded.
@@ -277,6 +290,7 @@
case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
case TYPE_WCDMA: return CellInfoWcdma.createFromParcelBody(in);
case TYPE_TDSCDMA: return CellInfoTdscdma.createFromParcelBody(in);
+ case TYPE_NR: return CellInfoNr.createFromParcelBody(in);
default: throw new RuntimeException("Bad CellInfo Parcel");
}
}
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
new file mode 100644
index 0000000..11857a6
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+
+import java.util.Objects;
+
+/**
+ * A {@link CellInfo} representing an 5G NR cell that provides identity and measurement info.
+ */
+public final class CellInfoNr extends CellInfo {
+ private static final String TAG = "CellInfoNr";
+
+ private final CellIdentityNr mCellIdentity;
+ private final CellSignalStrengthNr mCellSignalStrength;
+
+ private CellInfoNr(Parcel in) {
+ super(in);
+ mCellIdentity = CellIdentityNr.CREATOR.createFromParcel(in);
+ mCellSignalStrength = CellSignalStrengthNr.CREATOR.createFromParcel(in);
+ }
+
+ @Override
+ public CellIdentity getCellIdentity() {
+ return mCellIdentity;
+ }
+
+ @Override
+ public CellSignalStrength getCellSignalStrength() {
+ return mCellSignalStrength;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), mCellIdentity, mCellSignalStrength);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof CellInfoNr)) {
+ return false;
+ }
+
+ CellInfoNr o = (CellInfoNr) other;
+ return super.equals(o) && mCellIdentity.equals(o.mCellIdentity)
+ && mCellSignalStrength.equals(o.mCellSignalStrength);
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append(TAG + ":{")
+ .append(" " + super.toString())
+ .append(" " + mCellIdentity)
+ .append(" " + mCellSignalStrength)
+ .append(" }")
+ .toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags, TYPE_NR);
+ mCellIdentity.writeToParcel(dest, flags);
+ mCellSignalStrength.writeToParcel(dest, flags);
+ }
+
+ public static final Creator<CellInfoNr> CREATOR = new Creator<CellInfoNr>() {
+ @Override
+ public CellInfoNr createFromParcel(Parcel in) {
+ // Skip the type info.
+ in.readInt();
+ return new CellInfoNr(in);
+ }
+
+ @Override
+ public CellInfoNr[] newArray(int size) {
+ return new CellInfoNr[size];
+ }
+ };
+
+ /** @hide */
+ protected static CellInfoNr createFromParcelBody(Parcel in) {
+ return new CellInfoNr(in);
+ }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index d6856b3..2ff75e6 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -19,7 +19,6 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
new file mode 100644
index 0000000..8079242
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * 5G NR signal strength related information.
+ */
+public final class CellSignalStrengthNr extends CellSignalStrength implements Parcelable {
+ /**
+ * The value is used to indicate that the asu level is unknown.
+ * Reference: 3GPP TS 27.007 section 8.69.
+ * @hide
+ */
+ public static final int UNKNOWN_ASU_LEVEL = 99;
+
+ private static final String TAG = "CellSignalStrengthNr";
+
+ /**
+ * These threshold values are copied from LTE.
+ * TODO: make it configurable via CarrierConfig.
+ */
+ private static final int SIGNAL_GREAT_THRESHOLD = -95;
+ private static final int SIGNAL_GOOD_THRESHOLD = -105;
+ private static final int SIGNAL_MODERATE_THRESHOLD = -115;
+
+ private int mCsiRsrp;
+ private int mCsiRsrq;
+ private int mCsiSinr;
+ private int mSsRsrp;
+ private int mSsRsrq;
+ private int mSsSinr;
+
+ /**
+ * @param csiRsrp CSI reference signal received power.
+ * @param csiRsrq CSI reference signal received quality.
+ * @param csiSinr CSI signal-to-noise and interference ratio.
+ * @param ssRsrp SS reference signal received power.
+ * @param ssRsrq SS reference signal received quality.
+ * @param ssSinr SS signal-to-noise and interference ratio.
+ * @hide
+ */
+ public CellSignalStrengthNr(
+ int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr) {
+ mCsiRsrp = csiRsrp;
+ mCsiRsrq = csiRsrq;
+ mCsiSinr = csiSinr;
+ mSsRsrp = ssRsrp;
+ mSsRsrq = ssRsrq;
+ mSsSinr = ssSinr;
+ }
+
+ /**
+ * Reference: 3GPP TS 38.215.
+ * Range: -140 dBm to -44 dBm.
+ * @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
+ * value.
+ */
+ public int getSsRsrp() {
+ return mSsRsrp;
+ }
+
+ /**
+ * Reference: 3GPP TS 38.215.
+ * Range: -20 dB to -3 dB.
+ * @return SS reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported
+ * value.
+ */
+ public int getSsRsrq() {
+ return mSsRsrq;
+ }
+
+ /**
+ * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1
+ * Range: -23 dB to 40 dB
+ * @return SS signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means
+ * unreported value.
+ */
+ public int getSsSinr() {
+ return mSsSinr;
+ }
+
+ /**
+ * Reference: 3GPP TS 38.215.
+ * Range: -140 dBm to -44 dBm.
+ * @return CSI reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
+ * value.
+ */
+ public int getCsiRsrp() {
+ return mCsiRsrp;
+ }
+
+ /**
+ * Reference: 3GPP TS 38.215.
+ * Range: -20 dB to -3 dB.
+ * @return CSI reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported
+ * value.
+ */
+ public int getCsiRsrq() {
+ return mCsiRsrq;
+ }
+
+ /**
+ * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1
+ * Range: -23 dB to 23 dB
+ * @return CSI signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means
+ * unreported value.
+ */
+ public int getCsiSinr() {
+ return mCsiSinr;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mCsiRsrp);
+ dest.writeInt(mCsiRsrq);
+ dest.writeInt(mCsiSinr);
+ dest.writeInt(mSsRsrp);
+ dest.writeInt(mSsRsrq);
+ dest.writeInt(mSsSinr);
+ }
+
+ private CellSignalStrengthNr(Parcel in) {
+ mCsiRsrp = in.readInt();
+ mCsiRsrq = in.readInt();
+ mCsiSinr = in.readInt();
+ mSsRsrp = in.readInt();
+ mSsRsrq = in.readInt();
+ mSsSinr = in.readInt();
+ }
+
+ /** @hide */
+ @Override
+ public void setDefaultValues() {
+ mCsiRsrp = CellInfo.UNAVAILABLE;
+ mCsiRsrq = CellInfo.UNAVAILABLE;
+ mCsiSinr = CellInfo.UNAVAILABLE;
+ mSsRsrp = CellInfo.UNAVAILABLE;
+ mSsRsrq = CellInfo.UNAVAILABLE;
+ mSsSinr = CellInfo.UNAVAILABLE;
+ }
+
+ @Override
+ public int getLevel() {
+ if (mCsiRsrp == CellInfo.UNAVAILABLE) {
+ return SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ } else if (mCsiRsrp >= SIGNAL_GREAT_THRESHOLD) {
+ return SIGNAL_STRENGTH_GREAT;
+ } else if (mCsiRsrp >= SIGNAL_GOOD_THRESHOLD) {
+ return SIGNAL_STRENGTH_GOOD;
+ } else if (mCsiRsrp >= SIGNAL_MODERATE_THRESHOLD) {
+ return SIGNAL_STRENGTH_MODERATE;
+ } else {
+ return SIGNAL_STRENGTH_POOR;
+ }
+ }
+
+ /**
+ * Calculates the NR signal as an asu value between 0..97, 99 is unknown.
+ * Asu is calculated based on 3GPP RSRP, refer to 3GPP TS 27.007 section 8.69.
+ * @return an integer represent the asu level of the signal strength.
+ */
+ @Override
+ public int getAsuLevel() {
+ int asuLevel;
+ int nrDbm = getDbm();
+ if (nrDbm == CellInfo.UNAVAILABLE) {
+ asuLevel = UNKNOWN_ASU_LEVEL;
+ } else if (nrDbm <= -140) {
+ asuLevel = 0;
+ } else if (nrDbm >= -43) {
+ asuLevel = 97;
+ } else {
+ asuLevel = nrDbm + 140;
+ }
+ return asuLevel;
+ }
+
+ @Override
+ public int getDbm() {
+ return mCsiRsrp;
+ }
+
+ /** @hide */
+ @Override
+ public CellSignalStrength copy() {
+ return new CellSignalStrengthNr(
+ mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof CellSignalStrengthNr) {
+ CellSignalStrengthNr o = (CellSignalStrengthNr) obj;
+ return mCsiRsrp == o.mCsiRsrp && mCsiRsrq == o.mCsiRsrq && mCsiSinr == o.mCsiSinr
+ && mSsRsrp == o.mSsRsrp && mSsRsrq == o.mSsRsrq && mSsSinr == o.mSsSinr;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append(TAG + ":{")
+ .append(" csiRsrp = " + mCsiRsrp)
+ .append(" csiRsrq = " + mCsiRsrq)
+ .append(" csiSinr = " + mCsiSinr)
+ .append(" ssRsrp = " + mSsRsrp)
+ .append(" ssRsrq = " + mSsRsrq)
+ .append(" ssSinr = " + mSsSinr)
+ .append(" }")
+ .toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Parcelable.Creator<CellSignalStrengthNr> CREATOR =
+ new Parcelable.Creator<CellSignalStrengthNr>() {
+ @Override
+ public CellSignalStrengthNr createFromParcel(Parcel in) {
+ return new CellSignalStrengthNr(in);
+ }
+
+ @Override
+ public CellSignalStrengthNr[] newArray(int size) {
+ return new CellSignalStrengthNr[size];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index d7169b2..c6887ab 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -342,6 +342,12 @@
*/
public static final int TOO_MANY_ONGOING_CALLS = 75;
+ /**
+ * Indicates that a new outgoing call cannot be placed because OTASP provisioning is currently
+ * in process.
+ */
+ public static final int OTASP_PROVISIONING_IN_PROCESS = 76;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Update toString() with the newly added disconnect type.
@@ -505,6 +511,8 @@
return "CALLING_DISABLED";
case TOO_MANY_ONGOING_CALLS:
return "TOO_MANY_ONGOING_CALLS";
+ case OTASP_PROVISIONING_IN_PROCESS:
+ return "OTASP_PROVISIONING_IN_PROCESS";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0ba18ee..31770ec 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -51,6 +51,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.euicc.EuiccManager;
+import android.telephony.ims.ImsMmTelManager;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -134,7 +135,7 @@
* A content {@link Uri} used to receive updates on wfc enabled user setting.
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * subscription wfc enabled {@link SubscriptionManager#WFC_IMS_ENABLED}
+ * subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()}
* while your app is running. You can also use a {@link JobService} to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
* Note, however, that using a {@link JobService} does not guarantee timely delivery of
@@ -147,10 +148,28 @@
public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
/**
- * A content {@link Uri} used to receive updates on enhanced 4g user setting.
+ * A content {@link Uri} used to receive updates on advanced calling user setting.
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * subscription enhanced 4G enabled {@link SubscriptionManager#ENHANCED_4G_MODE_ENABLED}
+ * subscription advanced calling enabled
+ * {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running.
+ * You can also use a {@link JobService} to ensure your app is notified of changes to the
+ * {@link Uri} even when it is not running.
+ * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ * To be notified of changes to a specific subId, append subId to the URI
+ * {@link Uri#withAppendedPath(Uri, String)}.
+ * @hide
+ */
+ @SystemApi
+ public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+ CONTENT_URI, "advanced_calling");
+
+ /**
+ * A content {@link Uri} used to receive updates on wfc mode setting.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()}
* while your app is running. You can also use a {@link JobService} to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
* Note, however, that using a {@link JobService} does not guarantee timely delivery of
@@ -160,9 +179,59 @@
* @hide
*/
@SystemApi
- public static final Uri ENHANCED_4G_ENABLED_CONTENT_URI = Uri.withAppendedPath(
- CONTENT_URI, "enhanced_4g");
+ public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
+ /**
+ * A content {@link Uri} used to receive updates on wfc roaming mode setting.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()}
+ * while your app is running. You can also use a {@link JobService} to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ * To be notified of changes to a specific subId, append subId to the URI
+ * {@link Uri#withAppendedPath(Uri, String)}.
+ * @hide
+ */
+ @SystemApi
+ public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
+ CONTENT_URI, "wfc_roaming_mode");
+
+ /**
+ * A content {@link Uri} used to receive updates on vt(video telephony over IMS) enabled
+ * setting.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()}
+ * while your app is running. You can also use a {@link JobService} to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ * To be notified of changes to a specific subId, append subId to the URI
+ * {@link Uri#withAppendedPath(Uri, String)}.
+ * @hide
+ */
+ @SystemApi
+ public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+ CONTENT_URI, "vt_enabled");
+
+ /**
+ * A content {@link Uri} used to receive updates on wfc roaming enabled setting.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()}
+ * while your app is running. You can also use a {@link JobService} to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ * To be notified of changes to a specific subId, append subId to the URI
+ * {@link Uri#withAppendedPath(Uri, String)}.
+ * @hide
+ */
+ @SystemApi
+ public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+ CONTENT_URI, "wfc_roaming_enabled");
/**
* TelephonyProvider unique key column name is the subscription id.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8a77f14..8414ed3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1285,9 +1285,10 @@
* Returns the unique device ID, for example, the IMEI for GSM and the MEID
* or ESN for CDMA phones. Return null if device ID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
- * that owns a managed profile on the device; for more details see <a
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
@@ -1295,7 +1296,7 @@
* MEID for CDMA.
*/
@Deprecated
- @SuppressAutoDoc // No support for device / profile owner.
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getDeviceId() {
try {
@@ -1314,9 +1315,10 @@
* Returns the unique device ID of a subscription, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
- * that owns a managed profile on the device; for more details see <a
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
@@ -1326,7 +1328,7 @@
* MEID for CDMA.
*/
@Deprecated
- @SuppressAutoDoc // No support for device / profile owner.
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getDeviceId(int slotIndex) {
// FIXME this assumes phoneId == slotIndex
@@ -1346,13 +1348,14 @@
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
- * that owns a managed profile on the device; for more details see <a
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*/
- @SuppressAutoDoc // No support for device / profile owner.
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getImei() {
return getImei(getSlotIndex());
@@ -1362,15 +1365,16 @@
* Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
* available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
- * that owns a managed profile on the device; for more details see <a
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
* @param slotIndex of which IMEI is returned
*/
- @SuppressAutoDoc // No support for device / profile owner.
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getImei(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -1415,13 +1419,14 @@
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
- * that owns a managed profile on the device; for more details see <a
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*/
- @SuppressAutoDoc // No support for device / profile owner.
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getMeid() {
return getMeid(getSlotIndex());
@@ -1430,15 +1435,16 @@
/**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
- * that owns a managed profile on the device; for more details see <a
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
* @param slotIndex of which MEID is returned
*/
- @SuppressAutoDoc // No support for device / profile owner.
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getMeid(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -2936,7 +2942,7 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*/
- @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getSimSerialNumber() {
return getSimSerialNumber(getSubId());
@@ -3098,7 +3104,7 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*/
- @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getSubscriberId() {
return getSubscriberId(getSubId());
@@ -8286,6 +8292,28 @@
}
/**
+ * Returns MNO carrier id of the current subscription’s MCCMNC.
+ * <p>MNO carrier id can be solely identified by subscription mccmnc. This is mainly used
+ * for MNO fallback when exact carrier id {@link #getSimCarrierId()}
+ * configurations are not found.
+ *
+ * @return MNO carrier id of the current subscription. Return the value same as carrier id
+ * {@link #getSimCarrierId()}, if MNO carrier id cannot be identified.
+ * @hide
+ */
+ public int getSimMNOCarrierId() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getSubscriptionMNOCarrierId(getSubId());
+ }
+ } catch (RemoteException ex) {
+ // This could happen if binder process crashes.
+ }
+ return UNKNOWN_CARRIER_ID;
+ }
+
+ /**
* Return the application ID for the uicc application type like {@link #APPTYPE_CSIM}.
* All uicc applications are uniquely identified by application ID. See ETSI 102.221 and 101.220
* <p>Requires Permission:
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 1141177..3b1ef3f 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -15,6 +15,7 @@
*/
package android.telephony.euicc;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -50,7 +51,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import android.annotation.CallbackExecutor;
import java.util.concurrent.Executor;
/**
@@ -119,6 +119,9 @@
/** Result code when the eUICC card with the given card Id is not found. */
public static final int RESULT_EUICC_NOT_FOUND = -2;
+ /** Result code indicating the caller is not the active LPA. */
+ public static final int RESULT_CALLER_NOT_ALLOWED = -3;
+
/**
* Callback to receive the result of an eUICC card API.
*
@@ -152,7 +155,7 @@
* Requests all the profiles on eUicc.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and all the profiles.
*/
public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
@@ -176,7 +179,7 @@
*
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and profile.
*/
public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -201,7 +204,7 @@
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
* @param refresh Whether sending the REFRESH command to modem.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void disableProfile(String cardId, String iccid, boolean refresh,
@@ -227,7 +230,7 @@
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile to switch to.
* @param refresh Whether sending the REFRESH command to modem.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and the EuiccProfileInfo enabled.
*/
public void switchToProfile(String cardId, String iccid, boolean refresh,
@@ -252,7 +255,7 @@
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
* @param nickname The nickname of the profile.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void setNickname(String cardId, String iccid, String nickname,
@@ -276,7 +279,7 @@
*
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -301,7 +304,7 @@
* @param cardId The Id of the eUICC.
* @param options Bits of the options of resetting which parts of the eUICC memory. See
* EuiccCard for details.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void resetMemory(String cardId, @ResetOption int options,
@@ -324,7 +327,7 @@
* Requests the default SM-DP+ address from eUICC.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and the default SM-DP+ address.
*/
public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
@@ -347,7 +350,7 @@
* Requests the SM-DS address from eUICC.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and the SM-DS address.
*/
public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
@@ -371,7 +374,7 @@
*
* @param cardId The Id of the eUICC.
* @param defaultSmdpAddress The default SM-DP+ address to set.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
@@ -395,7 +398,7 @@
* Requests Rules Authorisation Table.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the rule authorisation table.
*/
public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
@@ -418,7 +421,7 @@
* Requests the eUICC challenge for new profile downloading.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the challenge.
*/
public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
@@ -441,7 +444,7 @@
* Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the info1.
*/
public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
@@ -464,7 +467,7 @@
* Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the info2.
*/
public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
@@ -497,7 +500,7 @@
* GSMA RSP v2.0+.
* @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
* SM-DP+ server.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and a byte array which represents a
* {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
*/
@@ -537,7 +540,7 @@
* SM-DP+ server.
* @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
* by SM-DP+ server.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and a byte array which represents a
* {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
*/
@@ -569,7 +572,7 @@
*
* @param cardId The Id of the eUICC.
* @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and a byte array which represents a
* {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
*/
@@ -598,7 +601,7 @@
* @param cardId The Id of the eUICC.
* @param transactionId the transaction ID returned by SM-DP+ server.
* @param reason the cancel reason.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and an byte[] which represents a
* {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
*/
@@ -627,7 +630,7 @@
*
* @param cardId The Id of the eUICC.
* @param events bits of the event types ({@link EuiccNotification.Event}) to list.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the list of notifications.
*/
public void listNotifications(String cardId, @EuiccNotification.Event int events,
@@ -651,7 +654,7 @@
*
* @param cardId The Id of the eUICC.
* @param events bits of the event types ({@link EuiccNotification.Event}) to list.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the list of notifications.
*/
public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
@@ -675,7 +678,7 @@
*
* @param cardId The Id of the eUICC.
* @param seqNumber the sequence number of the notification.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the notification.
*/
public void retrieveNotification(String cardId, int seqNumber,
@@ -699,7 +702,7 @@
*
* @param cardId The Id of the eUICC.
* @param seqNumber the sequence number of the notification.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code.
*/
public void removeNotificationFromList(String cardId, int seqNumber,
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 89ef339..f73036e 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -16,17 +16,20 @@
package android.telephony.ims;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.PersistableBundle;
import android.telecom.VideoProfile;
import android.util.Log;
import com.android.internal.telephony.PhoneConstants;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Parcelable object to handle IMS call profile.
* It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
@@ -206,17 +209,36 @@
public static final int DIALSTRING_USSD = 2;
/**
- * Values for causes that restrict call types
+ * Call is not restricted on peer side and High Definition media is supported
*/
- // Default cause not restricted at peer and HD is supported
public static final int CALL_RESTRICT_CAUSE_NONE = 0;
- // Service not supported by RAT at peer
+
+ /**
+ * High Definition media is not supported on the peer side due to the Radio Access Technology
+ * (RAT) it is are connected to.
+ */
public static final int CALL_RESTRICT_CAUSE_RAT = 1;
- // Service Disabled at peer
+
+ /**
+ * The service has been disabled on the peer side.
+ */
public static final int CALL_RESTRICT_CAUSE_DISABLED = 2;
- // HD is not supported
+
+ /**
+ * High definition media is not currently supported.
+ */
public static final int CALL_RESTRICT_CAUSE_HD = 3;
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "CALL_RESTRICT_CAUSE_", value = {
+ CALL_RESTRICT_CAUSE_NONE,
+ CALL_RESTRICT_CAUSE_RAT,
+ CALL_RESTRICT_CAUSE_DISABLED,
+ CALL_RESTRICT_CAUSE_HD
+ })
+ public @interface CallRestrictCause {}
+
/**
* String extra properties
* oi : Originating identity (number), MT only
@@ -270,7 +292,7 @@
public int mCallType;
/** @hide */
@UnsupportedAppUsage
- public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
+ public @CallRestrictCause int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
/**
* Extras associated with this {@link ImsCallProfile}.
@@ -285,7 +307,7 @@
* <li>{@code long[]}</li>
* <li>{@code double[]}</li>
* <li>{@code String[]}</li>
- * <li>{@link PersistableBundle}</li>
+ * <li>{@link android.os.PersistableBundle}</li>
* <li>{@link Boolean} (and boolean)</li>
* <li>{@code boolean[]}</li>
* <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li>
@@ -426,6 +448,14 @@
}
}
+ /**
+ * Set the call restrict cause, which provides the reason why a call has been restricted from
+ * using High Definition media.
+ */
+ public void setCallRestrictCause(@CallRestrictCause int cause) {
+ mRestrictCause = cause;
+ }
+
public void updateCallType(ImsCallProfile profile) {
mCallType = profile.mCallType;
}
@@ -494,7 +524,11 @@
return mCallType;
}
- public int getRestrictCause() {
+ /**
+ * @return The call restrict cause, which provides the reason why a call has been restricted
+ * from using High Definition media.
+ */
+ public @CallRestrictCause int getRestrictCause() {
return mRestrictCause;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b20b164..682141f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1311,6 +1311,18 @@
String getSubscriptionCarrierName(int subId);
/**
+ * Returns MNO carrier id of the current subscription’s MCCMNC.
+ * <p>MNO carrier id can be solely identified by subscription mccmnc. This is mainly used
+ * for MNO fallback when exact carrier id {@link #getSimCarrierId()}
+ * configurations are not found.
+ *
+ * @return MNO carrier id of the current subscription. Return the value same as carrier id
+ * {@link #getSimCarrierId()}, if MNO carrier id cannot be identified.
+ * @hide
+ */
+ int getSubscriptionMNOCarrierId(int subId);
+
+ /**
* Action set from carrier signalling broadcast receivers to enable/disable metered apns
* Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
* @param subId the subscription ID that this action applies to.
diff --git a/telephony/java/com/android/internal/telephony/NetworkScanResult.java b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
index 95f39d7..d07d77c 100644
--- a/telephony/java/com/android/internal/telephony/NetworkScanResult.java
+++ b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
@@ -19,6 +19,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.CellInfo;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -106,6 +107,17 @@
}
@Override
+ public String toString() {
+ return new StringBuilder()
+ .append("{")
+ .append("scanStatus=" + scanStatus)
+ .append(", scanError=" + scanError)
+ .append(", networkInfos=" + networkInfos)
+ .append("}")
+ .toString();
+ }
+
+ @Override
public int hashCode () {
return ((scanStatus * 31)
+ (scanError * 23)
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index eb6be65..553e3fb 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -188,6 +188,13 @@
if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
return true;
}
+ // Calling packages with carrier privileges will also have access to device identifiers, but
+ // this may be removed in a future release.
+ if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(
+ TELEPHONY_SUPPLIER, subId, uid)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
// else the calling package is not authorized to access the device identifiers; call
// a central method to report the failure based on the target SDK and if the calling package
// has the READ_PHONE_STATE permission or carrier privileges that were previously required
@@ -279,44 +286,51 @@
int uid, String callingPackage, String message) {
Log.wtf(LOG_TAG,
"reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
- // if the device identifier check is relaxed then revert to the READ_PHONE_STATE permission
- // check that was previously required to access device identifiers.
- boolean relaxDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 0;
- if (relaxDeviceIdentifierCheck) {
- return checkReadPhoneState(context, subId, pid, uid, callingPackage, message);
- } else {
+ // If the device identifier check is enabled then enforce the new access requirements for
+ // both 1P and 3P apps.
+ boolean enableDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 1;
+ // Check if the application is a 3P app; if so then a separate setting is required to relax
+ // the check to begin flagging problems with 3P apps early.
+ boolean relax3PDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED, 0) == 1;
+ boolean is3PApp = true;
+ ApplicationInfo callingPackageInfo = null;
+ try {
+ callingPackageInfo = context.getPackageManager().getApplicationInfo(callingPackage, 0);
+ if (callingPackageInfo.isSystemApp()) {
+ is3PApp = false;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // If the application info for the calling package could not be found then assume the
+ // calling app is a 3P app to detect any issues with the check
+ }
+ if (enableDeviceIdentifierCheck || (is3PApp && !relax3PDeviceIdentifierCheck)) {
boolean targetQBehaviorDisabled = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED, 0) == 0;
if (callingPackage != null) {
- try {
- // if the target SDK is pre-Q or the target Q behavior is disabled then check if
- // the calling package would have previously had access to device identifiers.
- ApplicationInfo callingPackageInfo =
- context.getPackageManager().getApplicationInfo(
- callingPackage, 0);
- if (callingPackageInfo != null && (
- callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q
- || targetQBehaviorDisabled)) {
- if (context.checkPermission(
- android.Manifest.permission.READ_PHONE_STATE,
- pid,
- uid) == PackageManager.PERMISSION_GRANTED) {
- return false;
- }
- if (SubscriptionManager.isValidSubscriptionId(subId)
- && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return false;
- }
+ // if the target SDK is pre-Q or the target Q behavior is disabled then check if
+ // the calling package would have previously had access to device identifiers.
+ if (callingPackageInfo != null && (
+ callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q
+ || targetQBehaviorDisabled)) {
+ if (context.checkPermission(
+ android.Manifest.permission.READ_PHONE_STATE,
+ pid,
+ uid) == PackageManager.PERMISSION_GRANTED) {
+ return false;
}
- } catch (PackageManager.NameNotFoundException e) {
- // If the application info for the calling package could not be found then
- // default to throwing the SecurityException.
+ if (SubscriptionManager.isValidSubscriptionId(subId)
+ && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return false;
+ }
}
}
throw new SecurityException(message + ": The user " + uid
+ " does not meet the requirements to access device identifiers.");
+ } else {
+ return checkReadPhoneState(context, subId, pid, uid, callingPackage, message);
}
}
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index dfe31bd..bf42412 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -31,6 +31,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkInfo;
+import android.net.NetworkMisc;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.test.TestLooper;
@@ -55,6 +56,7 @@
static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
@Mock ConnectivityService mConnectivity;
+ @Mock NetworkMisc mMisc;
@Mock INetworkManagementService mNms;
@Mock InterfaceConfiguration mConfig;
@Mock NetworkAgentInfo mNai;
@@ -78,6 +80,7 @@
mNai.networkInfo = new NetworkInfo(null);
mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI);
when(mNai.connService()).thenReturn(mConnectivity);
+ when(mNai.netMisc()).thenReturn(mMisc);
when(mNai.handler()).thenReturn(mHandler);
when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig);
@@ -103,9 +106,16 @@
mNai.networkInfo.setType(type);
for (NetworkInfo.DetailedState state : supportedDetailedStates) {
mNai.networkInfo.setDetailedState(state, "reason", "extraInfo");
- assertTrue(
- String.format("requiresClat expected for type=%d state=%s", type, state),
- Nat464Xlat.requiresClat(mNai));
+ String msg = String.format("requiresClat expected for type=%d state=%s",
+ type, state);
+
+ mMisc.skip464xlat = true;
+ String errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
+ assertFalse(errorMsg, Nat464Xlat.requiresClat(mNai));
+
+ mMisc.skip464xlat = false;
+ errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
+ assertTrue(errorMsg, Nat464Xlat.requiresClat(mNai));
}
}
}
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index f12756a..af7123b 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -30,7 +30,9 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -63,24 +65,13 @@
@Mock private PackageManager mPackageManager;
private PermissionMonitor mPermissionMonitor;
- private int mMockFirstSdkInt;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(MOCK_PACKAGE_NAMES);
- // Try to use spy() here for stubbing getDeviceFirstSdkInt value but the spies are loaded
- // by a custom class loader that's different from the loader used for loading the real
- // thing. That means those two classes are not in the same package, so a package private
- // method is not accessible. Hence, using override method to control FIRST_SDK_INT value
- // instead of spy function for testing.
- mPermissionMonitor = new PermissionMonitor(mContext, null) {
- @Override
- int getDeviceFirstSdkInt() {
- return mMockFirstSdkInt;
- }
- };
+ mPermissionMonitor = spy(new PermissionMonitor(mContext, null));
}
private boolean hasBgPermission(String partition, int targetSdkVersion, int uid,
@@ -166,13 +157,13 @@
@Test
public void testHasUseBackgroundNetworksPermissionSystemUid() throws Exception {
- mMockFirstSdkInt = VERSION_P;
+ doReturn(VERSION_P).when(mPermissionMonitor).getDeviceFirstSdkInt();
assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CHANGE_WIFI_STATE));
assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID,
CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- mMockFirstSdkInt = VERSION_Q;
+ doReturn(VERSION_Q).when(mPermissionMonitor).getDeviceFirstSdkInt();
assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CHANGE_WIFI_STATE));
assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID,
diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp
index 4be6534..0a9e964 100644
--- a/tests/utils/testutils/Android.bp
+++ b/tests/utils/testutils/Android.bp
@@ -19,7 +19,7 @@
srcs: ["java/**/*.java"],
- static_libs: ["android-support-test"],
+ static_libs: ["junit"],
libs: [
"android.test.runner",
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 414758e..2e717ff 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -248,6 +248,7 @@
if (!split_entry->id) {
split_entry->id = entry->id;
split_entry->visibility = entry->visibility;
+ split_entry->overlayable_declarations = entry->overlayable_declarations;
}
// Copy the selected values into the new Split Entry.
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 3a4e88b..9b9247d 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -86,9 +86,9 @@
public static final int PROTOCOL_WPA = 1;
/**
* @hide
- * Security protocol type: WPA version 2, also called RSN.
+ * Security protocol type: RSN, for WPA version 2, and version 3.
*/
- public static final int PROTOCOL_WPA2 = 2;
+ public static final int PROTOCOL_RSN = 2;
/**
* @hide
* Security protocol type:
@@ -138,7 +138,21 @@
* Used for Hotspot 2.0.
*/
public static final int KEY_MGMT_OSEN = 7;
-
+ /**
+ * @hide
+ * Security key management scheme: SAE.
+ */
+ public static final int KEY_MGMT_SAE = 8;
+ /**
+ * @hide
+ * Security key management scheme: OWE.
+ */
+ public static final int KEY_MGMT_OWE = 9;
+ /**
+ * @hide
+ * Security key management scheme: SUITE_B_192.
+ */
+ public static final int KEY_MGMT_EAP_SUITE_B_192 = 10;
/**
* @hide
* No cipher suite.
@@ -159,6 +173,11 @@
* Cipher suite: CCMP
*/
public static final int CIPHER_CCMP = 3;
+ /**
+ * @hide
+ * Cipher suite: GCMP
+ */
+ public static final int CIPHER_GCMP_256 = 4;
/**
* The detected signal level in dBm, also known as the RSSI.
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 0574716..8fc9b97 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -23,6 +23,7 @@
import android.net.IpConfiguration;
import android.net.IpConfiguration.ProxySettings;
import android.net.MacAddress;
+import android.net.NetworkSpecifier;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
import android.net.Uri;
@@ -129,10 +130,26 @@
*/
public static final int FT_EAP = 7;
+ /**
+ * Simultaneous Authentication of Equals
+ */
+ public static final int SAE = 8;
+
+ /**
+ * Opportunististic Wireless Encryption
+ */
+ public static final int OWE = 9;
+
+ /**
+ * SUITE_B_192 192 bit level
+ */
+ public static final int SUITE_B_192 = 10;
+
public static final String varName = "key_mgmt";
public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
- "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
+ "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
+ "SAE", "OWE", "SUITE_B_192"};
}
/**
@@ -146,7 +163,7 @@
* is discouraged. WPA-2 (RSN) should be used instead. */
@Deprecated
public static final int WPA = 0;
- /** WPA2/IEEE 802.11i */
+ /** RSN WPA2/WPA3/IEEE 802.11i */
public static final int RSN = 1;
/** HS2.0 r2 OSEN
* @hide
@@ -194,10 +211,14 @@
public static final int TKIP = 1;
/** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
public static final int CCMP = 2;
+ /**
+ * AES in Galois/Counter Mode
+ */
+ public static final int GCMP_256 = 3;
public static final String varName = "pairwise";
- public static final String[] strings = { "NONE", "TKIP", "CCMP" };
+ public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" };
}
/**
@@ -207,6 +228,7 @@
* TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
* WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
* WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
+ * GCMP_256 = AES in Galois/Counter Mode
* </pre>
*/
public static class GroupCipher {
@@ -230,12 +252,64 @@
* @hide
*/
public static final int GTK_NOT_USED = 4;
+ /**
+ * AES in Galois/Counter Mode
+ */
+ public static final int GCMP_256 = 5;
public static final String varName = "group";
public static final String[] strings =
{ /* deprecated */ "WEP40", /* deprecated */ "WEP104",
- "TKIP", "CCMP", "GTK_NOT_USED" };
+ "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" };
+ }
+
+ /**
+ * Recognized group management ciphers.
+ * <pre>
+ * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits
+ * BIP_GMAC_128 = Galois Message Authentication Code 128 bits
+ * BIP_GMAC_256 = Galois Message Authentication Code 256 bits
+ * </pre>
+ */
+ public static class GroupMgmtCipher {
+ private GroupMgmtCipher() { }
+
+ /** CMAC-256 = Cipher-based Message Authentication Code */
+ public static final int BIP_CMAC_256 = 0;
+
+ /** GMAC-128 = Galois Message Authentication Code */
+ public static final int BIP_GMAC_128 = 1;
+
+ /** GMAC-256 = Galois Message Authentication Code */
+ public static final int BIP_GMAC_256 = 2;
+
+ private static final String varName = "groupMgmt";
+
+ private static final String[] strings = { "BIP_CMAC_256",
+ "BIP_GMAC_128", "BIP_GMAC_256"};
+ }
+
+ /**
+ * Recognized suiteB ciphers.
+ * <pre>
+ * ECDHE_ECDSA
+ * ECDHE_RSA
+ * </pre>
+ * @hide
+ */
+ public static class SuiteBCipher {
+ private SuiteBCipher() { }
+
+ /** Diffie-Hellman with Elliptic Curve_ECDSA signature */
+ public static final int ECDHE_ECDSA = 0;
+
+ /** Diffie-Hellman with_RSA signature */
+ public static final int ECDHE_RSA = 1;
+
+ private static final String varName = "SuiteB";
+
+ private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
}
/** Possible status of a network configuration. */
@@ -413,6 +487,17 @@
*/
public BitSet allowedGroupCiphers;
/**
+ * The set of group management ciphers supported by this configuration.
+ * See {@link GroupMgmtCipher} for descriptions of the values.
+ */
+ public BitSet allowedGroupMgmtCiphers;
+ /**
+ * The set of SuiteB ciphers supported by this configuration.
+ * To be used for WPA3-Enterprise mode.
+ * See {@link SuiteBCipher} for descriptions of the values.
+ */
+ public BitSet allowedSuiteBCiphers;
+ /**
* The enterprise configuration details specifying the EAP method,
* certificates and other settings associated with the EAP.
*/
@@ -737,7 +822,8 @@
public boolean isOpenNetwork() {
final int cardinality = allowedKeyManagement.cardinality();
final boolean hasNoKeyMgmt = cardinality == 0
- || (cardinality == 1 && allowedKeyManagement.get(KeyMgmt.NONE));
+ || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE)
+ || allowedKeyManagement.get(KeyMgmt.OWE)));
boolean hasNoWepKeys = true;
if (wepKeys != null) {
@@ -1542,6 +1628,8 @@
allowedAuthAlgorithms = new BitSet();
allowedPairwiseCiphers = new BitSet();
allowedGroupCiphers = new BitSet();
+ allowedGroupMgmtCiphers = new BitSet();
+ allowedSuiteBCiphers = new BitSet();
wepKeys = new String[4];
for (int i = 0; i < wepKeys.length; i++) {
wepKeys[i] = null;
@@ -1595,7 +1683,8 @@
@UnsupportedAppUsage
public boolean isEnterprise() {
return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
- || allowedKeyManagement.get(KeyMgmt.IEEE8021X))
+ || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
+ || allowedKeyManagement.get(KeyMgmt.SUITE_B_192))
&& enterpriseConfig != null
&& enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
}
@@ -1613,6 +1702,7 @@
append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
.append(" PRIO: ").append(this.priority)
.append(" HIDDEN: ").append(this.hiddenSSID)
+ .append(" PMF: ").append(this.requirePMF)
.append('\n');
@@ -1725,10 +1815,35 @@
}
}
}
- sbuf.append('\n').append(" PSK: ");
+ sbuf.append('\n');
+ sbuf.append(" GroupMgmtCiphers:");
+ for (int gmc = 0; gmc < this.allowedGroupMgmtCiphers.size(); gmc++) {
+ if (this.allowedGroupMgmtCiphers.get(gmc)) {
+ sbuf.append(" ");
+ if (gmc < GroupMgmtCipher.strings.length) {
+ sbuf.append(GroupMgmtCipher.strings[gmc]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" SuiteBCiphers:");
+ for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) {
+ if (this.allowedSuiteBCiphers.get(sbc)) {
+ sbuf.append(" ");
+ if (sbc < SuiteBCipher.strings.length) {
+ sbuf.append(SuiteBCipher.strings[sbc]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n').append(" PSK/SAE: ");
if (this.preSharedKey != null) {
sbuf.append('*');
}
+
sbuf.append("\nEnterprise config:\n");
sbuf.append(enterpriseConfig);
@@ -1891,6 +2006,12 @@
return KeyMgmt.WPA_EAP;
} else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return KeyMgmt.IEEE8021X;
+ } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+ return KeyMgmt.SAE;
+ } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+ return KeyMgmt.OWE;
+ } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+ return KeyMgmt.SUITE_B_192;
}
return KeyMgmt.NONE;
}
@@ -1922,6 +2043,12 @@
key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
} else if (wepKeys[0] != null) {
key = SSID + "WEP";
+ } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.OWE];
+ } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.SAE];
+ } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192];
} else {
key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
}
@@ -2090,6 +2217,8 @@
allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone();
allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone();
+ allowedGroupMgmtCiphers = (BitSet) source.allowedGroupMgmtCiphers.clone();
+ allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone();
enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
defaultGwMacAddress = source.defaultGwMacAddress;
@@ -2132,6 +2261,7 @@
recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
mRandomizedMacAddress = source.mRandomizedMacAddress;
macRandomizationSetting = source.macRandomizationSetting;
+ requirePMF = source.requirePMF;
}
}
@@ -2167,6 +2297,8 @@
writeBitSet(dest, allowedAuthAlgorithms);
writeBitSet(dest, allowedPairwiseCiphers);
writeBitSet(dest, allowedGroupCiphers);
+ writeBitSet(dest, allowedGroupMgmtCiphers);
+ writeBitSet(dest, allowedSuiteBCiphers);
dest.writeParcelable(enterpriseConfig, flags);
@@ -2235,6 +2367,8 @@
config.allowedAuthAlgorithms = readBitSet(in);
config.allowedPairwiseCiphers = readBitSet(in);
config.allowedGroupCiphers = readBitSet(in);
+ config.allowedGroupMgmtCiphers = readBitSet(in);
+ config.allowedSuiteBCiphers = readBitSet(in);
config.enterpriseConfig = in.readParcelable(null);
config.setIpConfiguration(in.readParcelable(null));
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9ce5486..954b51f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1454,8 +1454,8 @@
*<p>
* When the device decides to connect to one of the provided network suggestions, platform fires
* the associated {@code pendingIntent} if
- * {@link WifiNetworkSuggestion#isAppInteractionRequired} is {@code true} and the
- * provided {@code pendingIntent} is non-null.
+ * the network was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()}
+ * flag set and the provided {@code pendingIntent} is non-null.
*<p>
* Registration of a non-null pending intent {@code pendingIntent} requires
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
@@ -1473,10 +1473,9 @@
*
* @param networkSuggestions List of network suggestions provided by the app.
* @param pendingIntent Pending intent to be fired post connection for networks. These will be
- * fired only when connecting to a network which has the
- * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set.
+ * fired only when connecting to a network that was created with
+ * {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} flag set.
* Pending intent must hold a foreground service, else will be rejected.
- * (i.e {@link PendingIntent#isForegroundService()} should return true)
* @return true on success, false if any of the suggestions match (See
* {@link WifiNetworkSuggestion#equals(Object)} any previously provided suggestions by the app.
* @throws {@link SecurityException} if the caller is missing required permissions.
@@ -1856,7 +1855,12 @@
public static final int WIFI_FEATURE_SCAN_RAND = 0x2000000; // Random MAC & Probe seq
/** @hide */
public static final int WIFI_FEATURE_TX_POWER_LIMIT = 0x4000000; // Set Tx power limit
-
+ /** @hide */
+ public static final int WIFI_FEATURE_WPA3_SAE = 0x8000000; // WPA3-Personal SAE
+ /** @hide */
+ public static final int WIFI_FEATURE_WPA3_SUITE_B = 0x10000000; // WPA3-Enterprise Suite-B
+ /** @hide */
+ public static final int WIFI_FEATURE_OWE = 0x20000000; // Enhanced Open
private int getSupportedFeatures() {
try {
@@ -2081,7 +2085,10 @@
* even when Wi-Fi is turned off.
*
* To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}.
+ * @deprecated The ability for apps to trigger scan requests will be removed in a future
+ * release.
*/
+ @Deprecated
public boolean isScanAlwaysAvailable() {
try {
return mService.isScanAlwaysAvailable();
@@ -4246,4 +4253,31 @@
private void updateVerboseLoggingEnabledFromService() {
mVerboseLoggingEnabled = getVerboseLoggingLevel() > 0;
}
+
+ /**
+ * @return true if this device supports WPA3-Personal SAE
+ * @hide
+ */
+ @SystemApi
+ public boolean isWpa3SaeSupported() {
+ return isFeatureSupported(WIFI_FEATURE_WPA3_SAE);
+ }
+
+ /**
+ * @return true if this device supports WPA3-Enterprise Suite-B-192
+ * @hide
+ */
+ @SystemApi
+ public boolean isWpa3SuiteBSupported() {
+ return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B);
+ }
+
+ /**
+ * @return true if this device supports Wi-Fi Enhanced Open (OWE)
+ * @hide
+ */
+ @SystemApi
+ public boolean isOweSupported() {
+ return isFeatureSupported(WIFI_FEATURE_OWE);
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
index ae4f405..67e2189 100644
--- a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
+++ b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
@@ -435,7 +435,7 @@
* context.getSystemService(Context.CONNECTIVITY_SERVICE);
* final NetworkCallback networkCallback = new NetworkCallback() {
* ...
- * @Override
+ * {@literal @}Override
* void onAvailable(...) {}
* // etc.
* };
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 5a4c898..e6892be 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -16,9 +16,13 @@
package android.net.wifi.p2p;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
-import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.wifi.WpsInfo;
@@ -480,6 +484,12 @@
/** @hide */
public static final int REPORT_NFC_HANDOVER_FAILED = BASE + 81;
+ /** @hide */
+ public static final int FACTORY_RESET = BASE + 82;
+ /** @hide */
+ public static final int FACTORY_RESET_FAILED = BASE + 83;
+ /** @hide */
+ public static final int FACTORY_RESET_SUCCEEDED = BASE + 84;
/**
* Create a new WifiP2pManager instance. Applications use
@@ -776,6 +786,7 @@
case STOP_LISTEN_FAILED:
case SET_CHANNEL_FAILED:
case REPORT_NFC_HANDOVER_FAILED:
+ case FACTORY_RESET_FAILED:
if (listener != null) {
((ActionListener) listener).onFailure(message.arg1);
}
@@ -802,6 +813,7 @@
case STOP_LISTEN_SUCCEEDED:
case SET_CHANNEL_SUCCEEDED:
case REPORT_NFC_HANDOVER_SUCCEEDED:
+ case FACTORY_RESET_SUCCEEDED:
if (listener != null) {
((ActionListener) listener).onSuccess();
}
@@ -1521,4 +1533,21 @@
c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0,
c.putListener(listener), bundle);
}
+
+ /**
+ * Removes all saved p2p groups.
+ * @param c is the channel created at {@link #initialize}.
+ * @param listener for callback on success or failure. Can be null.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void factoryReset(@NonNull Channel c, @Nullable ActionListener listener) {
+ checkChannel(c);
+ Bundle callingPackage = new Bundle();
+ callingPackage.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());
+ c.mAsyncChannel.sendMessage(FACTORY_RESET, 0, c.putListener(listener),
+ callingPackage);
+ }
+
}
diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java
new file mode 100644
index 0000000..eede23b
--- /dev/null
+++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java
@@ -0,0 +1,415 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License") {
+ * throw new UnsupportedOperationException();
+ }
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import android.content.pm.ParceledListSlice;
+import android.net.DhcpInfo;
+import android.net.Network;
+import android.net.wifi.INetworkRequestMatchCallback;
+import android.net.wifi.ISoftApCallback;
+import android.net.wifi.ITrafficStateCallback;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.PasspointManagementObjectDefinition;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiActivityEnergyInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.hotspot2.IProvisioningCallback;
+import android.net.wifi.hotspot2.OsuProvider;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.os.IBinder;
+import android.os.Messenger;
+import android.os.ResultReceiver;
+import android.os.WorkSource;
+import android.util.Slog;
+
+import java.util.List;
+
+/**
+ * Abstract class implementing IWifiManager with stub methods throwing runtime exceptions.
+ *
+ * This class is meant to be extended by real implementations of IWifiManager in order to facilitate
+ * cross-repo changes to WiFi internal APIs, including the introduction of new APIs, the removal of
+ * deprecated APIs, or the migration of existing API signatures.
+ *
+ * When an existing API is scheduled for removal, it can be removed from IWifiManager.aidl
+ * immediately and marked as @Deprecated first in this class. Children inheriting this class are
+ * then given a short grace period to update themselves before the @Deprecated stub is removed for
+ * good. If the API scheduled for removal has a replacement or an overload (signature change),
+ * these should be introduced before the stub is removed to allow children to migrate.
+ */
+public abstract class AbstractWifiService extends IWifiManager.Stub {
+
+ private static final String TAG = AbstractWifiService.class.getSimpleName();
+
+ @Override
+ public int getSupportedFeatures() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WifiActivityEnergyInfo reportActivityInfo() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void requestActivityInfo(ResultReceiver result) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ParceledListSlice getConfiguredNetworks() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ParceledListSlice getPrivilegedConfiguredNetworks() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int addOrUpdateNetwork(WifiConfiguration config, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addOrUpdatePasspointConfiguration(
+ PasspointConfiguration config, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removePasspointConfiguration(String fqdn, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<PasspointConfiguration> getPasspointConfigurations() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void queryPasspointIcon(long bssid, String fileName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int matchProviderWithCurrentNetwork(String fqdn) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void deauthenticateNetwork(long holdoff, boolean ess) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeNetwork(int netId, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean enableNetwork(int netId, boolean disableOthers, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean disableNetwork(int netId, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean startScan(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<ScanResult> getScanResults(String callingPackage) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void disconnect(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void reconnect(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void reassociate(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WifiInfo getConnectionInfo(String callingPackage) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean setWifiEnabled(String packageName, boolean enable) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getWifiEnabledState() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setCountryCode(String country) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getCountryCode() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isDualBandSupported() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean needs5GHzToAnyApBandConversion() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DhcpInfo getDhcpInfo() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isScanAlwaysAvailable() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean releaseWifiLock(IBinder lock) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void initializeMulticastFiltering() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isMulticastEnabled() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void acquireMulticastLock(IBinder binder, String tag) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void releaseMulticastLock(String tag) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void updateInterfaceIpState(String ifaceName, int mode) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean startSoftAp(WifiConfiguration wifiConfig) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean stopSoftAp() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int startLocalOnlyHotspot(Messenger messenger, IBinder binder, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void stopLocalOnlyHotspot() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void startWatchLocalOnlyHotspot(Messenger messenger, IBinder binder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void stopWatchLocalOnlyHotspot() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getWifiApEnabledState() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WifiConfiguration getWifiApConfiguration() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void notifyUserOfApBandConversion(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Messenger getWifiServiceMessenger(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableTdls(String remoteIPAddress, boolean enable) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getCurrentNetworkWpsNfcConfigurationToken() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableVerboseLogging(int verbose) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getVerboseLoggingLevel() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableWifiConnectivityManager(boolean enabled) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void disableEphemeralNetwork(String SSID, String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void factoryReset(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Network getCurrentNetwork() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] retrieveBackupData() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void restoreBackupData(byte[] data) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void startSubscriptionProvisioning(
+ OsuProvider provider, IProvisioningCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void registerSoftApCallback(
+ IBinder binder, ISoftApCallback callback, int callbackIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unregisterSoftApCallback(int callbackIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void registerTrafficStateCallback(
+ IBinder binder, ITrafficStateCallback callback, int callbackIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unregisterTrafficStateCallback(int callbackIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void registerNetworkRequestMatchCallback(
+ IBinder binder, INetworkRequestMatchCallback callback, int callbackIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unregisterNetworkRequestMatchCallback(int callbackIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 3b9f93e..5f3e1b2 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -155,7 +155,10 @@
@Test
public void testIsOpenNetwork_NotOpen_HasAuthType() {
for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) {
- if (keyMgmt == WifiConfiguration.KeyMgmt.NONE) continue;
+ if (keyMgmt == WifiConfiguration.KeyMgmt.NONE
+ || keyMgmt == WifiConfiguration.KeyMgmt.OWE) {
+ continue;
+ }
WifiConfiguration config = new WifiConfiguration();
config.allowedKeyManagement.clear();
config.allowedKeyManagement.set(keyMgmt);